I am new to prolog and was trying to create a binary predicate which will give
a list in which all numbers are squared, including those in sublists.
e.g.
?-dcountSublists([a,[[3]],b,4,c(5),4],C).
C=[a,[[9]],b,c(5),16]
Can anyone guide me how i can do this.
Thank You. Answer with a snippet is appreciated
This is easily achieved using recursion in Prolog. Remember that everything in Prolog is either a variable, or a term (atoms are just 0-arity terms), so a term like the following:
[a,[[3]],b,4,c(5),4]
...is easily deconstructed (also note that the list syntax [..] is sugar for the binary predicate ./2). Prolog offers a range of predicates to test for particular types of terms as well, such as numbers, strings, or compound terms (such as compound/1).
To build the predicate you're after, I recommend writing it using several predicates like this:
dcountSublists(In, Out) :-
% analyze type of In
% based on type, either:
% 1. split term into subterms for recursive processing
% 2. term cannot be split; either replace it, or pass it through
Here's an example to get you started which does the hard bit. The following recognizes compound terms and breaks them apart with the term de/constructor =../2:
dcountSublists(In, Out) :-
% test if In has type compound term
compound(In),
% cut to exclude backtracking to other cases below this predicate
!,
% deconstruct In into functor and an argument list
In =.. [Func|Args],
% apply dcountSublists/2 to every argument, building new args
maplist(dcountSublists, Args, NewArgs),
% re-construct In using the new arguments
Out =.. [Func|NewArgs].
dcountSublists(In, Out) :-
% test if In has type atom
atom(In), !,
% pass it through
Out = In.
Testing:
?- dcountSublists([a,[[e]],b,a,c(s),a], L).
L = [a, [[e]], b, a, c(s), a].
Note that this fails if the input term has numbers, because it doesn't have a predicate to recognize and deal with them. I'll leave this up to you.
Good luck!
SWI-Prolog has the predicate maplist/[2-5] which allows you to map a predicate over some lists.
Using that, you only have to make a predicate that will square a number or the numbers in a list and leave everything else the same. The predicates number/1, is_list/1 are true if their argument is a number or a list.
Therefore:
square(N,NN):-
integer(N),
NN is N*N.
square(L,LL):-
is_list(L),
dcountSublists(square,L,LL).
square(Other,Other):-
\+ number(Other),
\+ is_list(Other).
dcountSublists(L,LSquared):-
maplist(square,L,LSquared).
with the negation in the final predicate we avoid multiple (wrong) solutions:
for example dcountSublists([2],X) would return X=[4] and X=[2] otherwise.
This could be avoided if we used an if-then-else structure for square or once/1 to call square/2.
If this is homework maybe you should not use maplist since (probably) the aim of the exercise is to learn how to build a recursive function; in any case, I would suggest to try and write an equivalent predicate without maplist.
Related
intersection([],L1,L2,L3).
intersection([H|T],L2,L3,[H|L4]):-member(H,L2),intersection(T,L3,L3,L4).
member(H,[H|T]).
member(X,[H|T]):-member(X,T).
This code makes the third list from the first and second list.
last([U],U).
last([_|L3],U) :- last(L3,U).
This piece of code looks for the last item in the list.
My problem is that I can’t figure out how to make these two pieces of code fit into one. That is, the program should find duplicate elements in the first and second list and display them in the third, and from the third list, display the last element multiplied by 3.
The main problem is intersection/4. I assume you wanted to write a deterministic predicate intersection/3 the first two arguments of which are fully instantiated at call time and the last argument of which is an output argument. By deterministic, I mean that intersection/3 should succeed exactly once without leftover choice points. The SWI-Prolog documentation contains a useful overview of determinism and mode declarations (although it does not enforce them).
It is useful to begin by writing a declarative specification of the predicate following the inductive definition of lists:
The intersection of [] and Ys is [].
The intersection of [A|Xs] and Ys is A prepended to the intersection of Xs and Ys if A is a member of Ys.
The intersection of [A|Xs] and Ys is the intersection of Xs and Ys if A is not a member of Ys.
The simplest translation of this specification into standard Prolog is:
intersection([],_,[]).
intersection([A|Xs],Ys,[A|Zs]) :-
member(A,Ys),
intersection(Xs,Ys,Zs).
intersection([A|Xs],Ys,Zs) :-
\+ member(A,Ys),
intersection(Xs,Zs).
If the first call to member/2 succeeds the second should fail. In order to avoid backtracking, unifying the current goal with the head of the second clause, and performing a redundant call to member/2, we place a cut after the occurrence of member/2 in the second clause.
intersection([],_,[]).
intersection([A|Xs],Ys,[A|Zs]) :-
member(A,Ys),
!,
intersection(Xs,Ys,Zs).
intersection([_|Xs],Ys,Zs) :-
intersection(Xs,Ys).
If the current goal unifies with the head of the first clause, it will not unify with the heads of later clauses. In order to prevent spurious backtracking, we place a cut in the (empty) body of the first clause. Whether this cut is necessary depends on your choice of Prolog implementation.
intersection([],_,[]) :-
!.
intersection([A|Xs],Ys,[A|Zs]) :-
member(A,Ys),
!,
intersection(Xs,Ys,Zs).
intersection([_|Xs],Ys,Zs) :-
intersection(Xs,Ys).
We are only interested in checking membership in the second list. Thus, we can replace the occurrence of member/2 with the semideterministic predicate memberchk/2. Here, semideterministic means that memberchk/2 succeeds or fails exactly once without leftover choice points.
intersection([],_,[]).
!.
intersection([A|Xs],Ys,[A|Zs]) :-
memberchk(A,Ys),
!,
intersection(Xs,Ys,Zs).
intersection([_|Xs],Ys,Zs) :-
intersection(Xs,Ys).
This implementation of intersection/3 is nearly identical to the implementation found in the SWI-Prolog library lists.pl. You can combine this predicate with an implementation of last/2 in order to complete your program. For example:
last_duplicate_tripled(Xs,Ys,N) :-
intersection(Xs,Ys,Zs),
last(Zs,M),
N is M * 3.
From here, I recommend doing the following:
Implement intersection/3 using metalogical predicates like findall/3.
Read #false's answer to this question.
Read #repeat's answer to this question.
They are doing something much more interesting and sophisticated than I attempted in this answer.
According to my university's course in logic we could expect a different outcome than defined by Prolog for the following query:
append([], a, X)
(which unifies for X=a).
However I don't get what they're aiming at? What should be expected as a valid response, given that append should unify X for (in this example) the concatenation of [] and a?
I assume they may be expecting a return of false or [a]; however I suppose that should be the result of concatenating a and [], not [] and a (since [] is the tail of [a]).
The point here is that we expect append/3 to hold only for lists.
In the query you show, a is not a list, yet append/3 still holds.
Thus, the relation is in fact more general than we would initially expect: It holds for other cases too!
The reason why this is so can be soon from the first clause of the traditional definition of append/3:
append([], Bs, Bs).
This clause alone already makes the query succeed! No additional pure clause can prevent this. Thus, it is this clause that must be restricted if we want the relation to hold only for lists. This means, we must put a constraint on the second argument, which we do by stating it in the body of the clause:
append([], Bs, Bs) :- ... (left as an exercise)
This obviously comes at a price: Performance.
So, the trade-off here is between performance and precision. In Prolog, we often accept such a trade-off because we implicitly use such predicates only with the intended terms. On the other hand, for many predicates, we want to benefit from domain errors or type errors if they are not called with the expected types.
Your course is aiming at a very important point of Prolog programming.
Manuals are often quite sloppy on the precise definition of append/3 and similar predicates. In fact, the complete definition is so complex that it is often preferred to define only part of the actual relation. Consider the first definition in the Prolog prologue:
append(Xs, Ys, Zs) is true if Zs is the concatenation of the lists Xs and Ys.
Note the if. The definition thus gives cases, where the relation holds but does not explicitly exclude further cases. To exclude further cases, it would say iff instead. The cases mentioned (that we are talking about lists) are the intended use of the predicate. So which cases now may be additionally included? Those cases where the precondition (that the arguments are lists) does not hold.
Consider a definition of append/3 with 'iff' in place of 'if':
append([], Xs, Xs) :-
list(Xs).
append([X|Xs], Ys, [X|Zs]) :-
append(Xs, Ys, Zs).
list([]).
list([X|Xs]) :-
list(Xs).
The cost for appending two lists is now |Xs|+|Ys|. That is quite an overhead compared to |Xs| alone.
But the situation is even worse. Consider the query:
?- append([1,2], Ys, Zs).
; Ys = [], Zs = [1,2]
; Ys = [_A], Zs = [1,2,_A]
; Ys = [_A,_B], Zs = [1,2,_A,_B]
; ... .
So we get infinitely many answers to this query. Contrast this to the usual definition:
?- append([1,2], Ys, Zs).
Zs = [1,2|Ys].
There is a single answer only! It contains all the answers for all lists plus some odd cases as you have observed. So the usual definition for append has better termination properties. In fact, it terminates if either the first or the third argument is a list of known length1.
Note that the answer contains Ys. In this manner infinitely many answers can be collapsed into a single one. This in fact is the power of the logical variable! We can represent with finite means infinitely many solutions. The price to pay are some extra solutions2 that may lead to programming errors. Some precaution is thus required.
1 It also terminates in some further obscure cases like append([a|_],_,[b|_]).
2 append([a], Zs, Zs). produces (in many systems) an answer, too.
However I don't get what they're aiming at?
Knowing exactly what they are aiming at is of course impossible without asking them.
Nevertheless I think they aim to show that Prolog is (more or less) untyped. append/3 is documented as:
append(?List1, ?List2, ?List1AndList2)
List1AndList2 is the concatenation of List1 and List2.
So clearly one expects that the three arguments are lists and a is not a list. a is not the concatenation of [] and a since one would consider the two not "concatenatable".
Now this still succeeds, because append/3 is usually implemented as:
append([],T,T).
append([H|T],T2,[H|R]) :-
append(T,T2,R).
So if you give it append([],a,X)., it will simply unify with the first clause and unify X = a.
The same "weird" behavior happens with append([14],a,X). Here X = [14|a] which is not a list as well. This is because the Prolog interpreter does not "know" it is working with lists. For Prolog [A|B] is the same like any other functor.
A more "type safe" way to handle this could be:
append([],[],[]).
append([H|T],T2,[H|R]) :-
append(T,T2,R).
append([],[H|T],[H|R]) :-
append([],T,R).
Or more elegantly:
list([]).
list([_|T]) :-
list(T).
append([],T,T) :-
list(T).
append([H|T],T2,[H|R]) :-
append(T,T2,R).
since here we check whether the second argument is a list. The downside however is that now we will append/3 in O(m+n) with m the length of the first list and n the length of the second list whereas in the original code it would take only O(m) time. Furthermore note that Prolog will not raise a warning/error at parse time. It will only fail to append [] with a at the moment you query these.
Not checking types results in the fact that you have less guarantees if the program compiles/does not raises errors when you feed it to an interpreter. This can be a good thing, but a problem might be that you call some predicates in a way they don't expect which may raise errors eventually later. That is why statically typed languages are sometimes used: they "guarantee" (at least to some extent) that if you call the problem, no such errors will occur. Of course that does not mean that the program cannot error on other things (or simply make no sense). haskell for instance is statically typed and has an append like:
(++) [] t2 = t2
(++) (h:t) t2 = h:((++) t t2)
The definition is "more or less" the same, but Haskell will derive that the type of (++) is (++) :: [a] -> [a] -> [a]. Because it know the type of the input and output of every function, it can perform calculus on it, and therefore at compile time, it will raise errors if you would give (++) something different than a list.
Whether that is a good thing is of course a different question: dynamically typed programming languages are designed that way deliberately since it allows more flexibility.
In Prolog, [H|T] is the list that begins with H and where the remaining elements are in the list T (internally represented with '.'(H, '.'(…))).
Is it possible to define new syntax in a similar fashion? For example, is it possible to define that [T~H] is the list that ends with H and where the remaining elements are in the list T, and then use it as freely as [H|T] in heads and bodies of predicates? Is it also possible to define e.g. <H|T> to be a different structure than lists?
One can interpret your question literally. A list-like data structure, where accessing the tail can be expressed without any auxiliary predicate. Well, these are the minus-lists which were already used in the very first Prolog system — the one which is sometimes called Prolog 0 and which was written in Algol-W. An example from the original report, p.32 transliterated into ISO Prolog:
t(X-a-l, X-a-u-x).
?- t(nil-m-e-t-a-l, Pluriel).
Pluriel = nil-m-e-t-a-u-x.
So essentially you take any left-associative operator.
But, I suspect, that's not what you wanted. You probably want an extension to lists.
There have been several attempts to do this, one more recent was Prolog III/Prolog IV. However, quite similar to constraints, you will have to face how to define equality over these operators. In other words, you need to go beyond syntactic unification into E-unification. The problem sounds easy in the beginning but it is frightening complex. A simple example in Prolog IV:
>> L = [a] o M, L = M o [z].
M ~ list,
L ~ list.
Clearly this is an inconsistency. That is, the system should respond false. There is simply no such M, but Prolog IV is not able to deduce this. You would have to solve at least such problems or get along with them somehow.
In case you really want to dig into this, consider the research which started with J. Makanin's pioneering work:
The Problem of Solvability of Equations in a Free Semi-Group, Akad. Nauk SSSR, vol.233, no.2, 1977.
That said, it might be the case that there is a simpler way to get what you want. Maybe a fully associative list operator is not needed.
Nevertheless, do not expect too much expressiveness from such an extension compared to what we have in Prolog, that is DCGs. In particular, general left-recursion would still be a problem for termination in grammars.
It is possible to extend or redefine syntax of Prolog with iso predicate
:- op(Precedence, Type, Name).
Where Precedence is a number between 0 and 1200, Type describe if the operatot is used postfix,prefix or infix:
infix: xfx, xfy, yfx
prefix: fx, fy
suffix: xf, yf
and finally name is the operator's name.
Operator definitions do not specify the meaning of an operator, but only describe how it can be used syntactically. It is only a definition extending the syntax of Prolog. It doesn't gives any information about when a predicate will succeed. So you need also to describe when your predicate succeeds. To answer your question and also give an example you could define :
:- op( 42, xfy, [ ~ ]).
where you declare an infix operator [ ~ ]. This doesn't means that is a representation of a list (yet). You could define clause:
[T ~ H]:-is_list([H|T]).
which matches [T~H] with the list that ends with H and where the remaining elements are in the list T.
Note also that it is not very safe to define predefined operators
like [ ] or ~ because you overwrite their existing functionality.
For example if you want to consult a file like [file]. this will
return false because you redefined operators.
So I just started Prolog and I was wondering two things:
1) Is there built in functions (or are they all called predicates?) for simple things like max of 2 numbers, or sine of a number, etc... If so, how do I access them?
2) How can I call a predicate from another one? I wrote two predicates called car and cdr. car returns the head of a list and cdr returns the list without the head. But now I want to call car on the cdr. Here are some examples for clarification:
car([3,4,5,5], H). would return H = 3
cdr([3,4,5,5],L). would return L = [4,5,5]
and what I am asking is how can I do this:
car(cdr[3,4,5,5]))
??
As others have pointed out, the predicates in Prolog are called that for a reason: they really aren't functions. Many newcomers to Prolog start out by trying to map the functionality they know in other languages over to Prolog and it generally fails. Prolog is a very different programming tool than most other languages. So it's a bit like using a variety of hammers for a long time, then having someone hand you a wrench, and you wonder why it doesn't make a good hammer.
In Prolog, predicates are a means of declaring relations between entities. If you say foo(a, b) it means there's a relationship between a and b called foo. You've probably seen the examples: knows(joe, jim). and knows(jim, sally). And you can define a relation, like:
remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).
Or something like that.
A predicate does not return a value. It either succeeds or it fails. If you have a sequence of predicates separated by commas (an "and" relationship) and Prolog encounters a predicate that fails, it backs up (backtracks) to the nearest prior predicate which it can make succeed again with different instantiation of its arguments and moves forward again.
Just to add a little to the confusion, there are some predicates in Prolog designed specifically for the evaluation of arithmetic expressions. These act like functions, but they are special case. For example:
X is Y / gcd(Z, 4).
Here, gcd of Z and 4 is computed an its value returned, and then Y is divided by that value and the result is instantiated into X. There are a variety of other functions as well, such as max/2, sin/1, etc. You can look them up in the documentation.
Arithmetic comparative operators function this way as well (using =:=/2, >/2, </2, etc with numeric expressions). So if you say:
X < Y + Z
The Prolog will consider numerical evaluation of these arguments and then compare them.
So having said all that, Prolog does allow embedding of term structures. You could have something like:
car(cdr([1,2,3]))
as a term. Prolog will not interpret it. Interpretation is left up to the programmer. I could then create a predicate which defines an evaluation of such terms:
car([H|_], H).
cdr([_|T], T).
proc_list(car(X), Result) :-
proc_list(X, R1),
car(R1, Result), !.
proc_list(cdr(X), Result) :-
proc_list(X, R1),
cdr(R1, Result), !.
proc_list(X, X).
The cut in the above clauses prevents backtracking to proc_list(X, X) when I don't want it.
Then:
| ?- proc_list(car(cdr([1,2,3])), R).
R = 2
yes
| ?- proc_list(car(cdr(cdr([1,2,3]))), R).
R = 3
yes
| ?-
Note this is a simple case and I may not have captured all of the subtleties of doing a proper sequence of car and cdr. It can also be made more general using =.. and call, etc, instead of discrete terms car and cdr in the parameters. For example, a slightly more general proc_list might be:
proc_list(Term, Result) :-
Term =.. [Proc, X], % Assumes terms have just one argument
member(Proc, [car, cdr]), % True only on recognized terms
proc_list(X, R1), % Recursively process embedded term
ProcCall =.. [Proc, R1, Result], % Construct a calling term with Result
call(ProcCall), !.
proc_list(X, X).
This technique of processing a term does step away from relational behavior which Prolog is best at, and leans into functional behavior, but with an understand of how Prolog works.
Prolog has a really different attitude to computing...
You don't define functions, but relations among arguments. The most similar and well known language I'm aware of is SQL. Think of predicates as tables (or stored procedures, when some computation not predefined by database engine is required).
car([H|_],H).
cdr([_|T],T).
car_of_cdr(L, Car) :- cdr(L, Cdr), car(Cdr, Car).
but since lists' syntax is a core part of the language, a better definition could be
car_of_cdr([_,X|_], X).
Anyway, I think you should spend some time on some Prolog tutorial. SO info page has much more information...
:- use_module(support).
This means the module will use predicates written in other modules.
<module_name>:<predicate_name>(<atoms / Variables>).
This way you can call a predicate in another module.
Is there any difference between input and output parameters in Prolog predicate definitions? How does this this compare with other languages such as Scheme and C?
I hope I understand your question. You should look into how unification is implemented in Prolog, as it will make things clearer. Anyway:
Briefly, there is no built-in way to declare an argument to a Prolog predicate as input, output, or input/output.
In C, you could say:
void foo(int const *a, int *b)
{
*b += *a;
}
and you could argue that in the context of foo, a is an input argument, while b is an output argument. In Prolog, you can use this notation when describing predicates, but there is no way to declare in the head of the predicate definition that an argument must be bound or a free variable when the predicate is called. And anyway, most predicates in pure Prolog have arguments that can be input, output, or input/output, depending how the predicate is used. Look at the list library of SWI-Prolog for many examples.
You can of course demand that an argument is instantiated, or a free variable, but this is done in the body of the predicate definition:
add_2(A, B) :- integer(A), var(B), B is A+2.
Compare this to:
plus_2(A, B) :- integer(A), integer(B), B =:= A+2.
which checks whether B=A+2 holds true, instead of adding 2 to A and unifying the result with B. integer/1, var/1, and the other predicates that verify the type of a term cannot be implemented in pure Prolog.
In my very limited experience with Prolog, I have noticed that one will try to define predicates that work as long as enough arguments are instantiated to either:
Instantiate the other variables according to the logic of the predicate
Infer whether the relationship between the arguments described by the predicate holds true.
For example, length(List, Integer) can tell you how long a list is, make a list of uninstantiated variables of the given length, or check whether the list is that long.
What you can do, however, is have a ground term in the head of the predicate definition, for example foo(1). This sort of predicates are called facts. A clause with a ground term in the head is the usual way for defining the end-of-recursion for recursive predicates.
Is there any difference between the input/output parameters in Prolog definitions?
No, and in fact a parameter can be either one depending on how it is used. Boris's length example is a good one, because you can calculate length:
?- length([1,2,3], X).
X = 3.
Or test an answer:
?- length([1,2,3], 3).
true.
Or generate a list of specified length:
?- length(X, 3).
X = [_G273, _G276, _G279].
Or even generate lists and lengths:
?- length(X, Y).
X = [],
Y = 0 ;
X = [_G15],
Y = 1 ;
X = [_G15, _G18],
Y = 2 ;
...
So you see either argument of length/2 can be instantiated or not and you'll still get meaningful answers. Not every predicate in Prolog is this flexible, but many are.
How does this this compare with other languages such as scheme and C ?
This is the principal difference between Prolog and other languages. There is no other, better-known language which behaves analogously to help you grok it. It means that, among other differences, there is no implicit "return value," you must have a parameter to pass results back in, but you're not limited to just one result parameter. In the case where both arguments to length/2 were uninstantiated, they were both acting as return values.
By convention, you will want to write your predicates so that input parameters go before output parameters for the common cases (or at least, in a sensible way for the name you've chosen).