Learning prolog - prolog

I am trying to learn Prolog and i have a really big problem to convert my programming knowledge to this language. I cant solve really newbie problems.
For example i have this
a(b(1)).
a(b(2)).
a(b(3)).
a(b(4)).
a(b(6)).
The exercise wants to print (using writeln(X)) all b(Y) if Y is an even number.
I can find if it is an even number using this if i am not wrong
a(b(X)) mod 2 =:= 0
but i cant understand how to check it and print all numbers.

A very basic concept in prolog is pattern matching
there are plenty of tutorials explaining it, like this one
you might also want to check the first and rest of the second chapter.
one of the reasons i really like prolog is that i just write what i want:
I want to print all the X that have a certain attribute.
Lets describe the attribute first.
X has the attribute if
it belongs to the database
is even
has_attribute(X):-
belongs_db(X),
is_even(X).
X belongs in the database if there is a clause a(b(X))
belongs_in_db(X):-
a(b(X)).
X is even if the remainder of the division with 2 is 0:
is_even(X):-
0 =:= X mod 2.
now we can ask has_attribute(X) and prolog will reply, listing every X.
but we want all X. to do this we will use the findall/3 predicate
Find all X that have the attribute i want and put them in a list
findall(X,has_attribute(X),List).
now we have all the X in the list and we want to print them
a simple way is to just use the writeln/1:
writeln(List)
so, in the end:
run:-
findall(X,has_attribute(X),List),
writeln(List).
has_attribute(X):-
a(b(X),
0 =:= X mod 2.
on the other hand, you may want to print the numbers in some other way.
for this, you should use recursion
if the list is empty, i'm done
my_print_list([]).
if the list has a haed and tail i'll print the first element and then the tail:
my_print_list([Head|Tail]):-
writeln(Head),
my_print_list(Tail).

is_even(N) :-
0 =:= N mod 2.
all_even_number :-
a(b(X)),
is_even(X),
writeln(X),
fail.
all_even_number.

Related

Prolog predicate different solution cases

I have 2 simple rules, which defines if 2 variables are in relation ship
grandfather: grandfather(X,Y):-male(X), parent(X,Z), parent(Z,Y).
father: svekr(X,Y):-male(X), female(Y),parent(X,Z),(marriage(Z,Y);marriage(Y,Z)).
for grandfather, when I'm trying to get all possible results using ; , program gives me answer yes.
This is what I'm talking about:
As you can see, program understands that there is no more possible solutions, so the program gives final answer is X = pat and Y = tony without confirmation.
But for father in law it goes like this:
This time, program does ask, if there is a need to find another solution it will fail and answer is no.
So my quesstion is, why in one case it gives YES with no confirmation and in other case it gives NO with confirmation?
Full code in here https://pastebin.com/9HpEnuAz
Consider
a(1).
a(2).
resulting in
?- a(X).
X = 1 ;
X = 2.
true.
Prolog knows that there is no rule after a(2), so it can give a definite answer.
Now, on the other hand:
a(1).
a(2).
a(3) :- 0 > 1.
Here, after a(2), we see another rule, giving another choice point. This is like a closed door - you can choose to try to open it, but you don't know whether anything is behind at or whether it will open at all. However, Prolog sees the door and asks you if it should try:
a(X).
X = 1 ;
X = 2 ;
false.
Since this particular door is locked (0 is not greater than 1), it responds with false, meaning "I failed to find another answer".
You can usually just ignore extra choice points although there can be performance implications sometimes.

Programming the Quadratic Formula in Prolog

First of all, I saw this same question being asked earlier today and I decided to give it a try myself (and had trouble with it). I hope it's alright that I created a new question for this!
I'm trying to make a prolog program that solves the quadratic formula X = ​(​​−b±√​b​2​​−4ac)​/2a. The implemented predicate quadratic([A,B,C], [Result]) takes a list of a, b and c as an the first argument and a list of the result(s) as the second. The lists are giving me trouble however; I wrote this code:
quadratic([A,B,C], [X]):-
underRoot([A,B,C], UnderRootResult),
UnderRootResult<0,
X is 0.
quadratic([A,B,C], [X]):-
underRoot([A,B,C], UnderRootResult),
UnderRootResult=:=0,
X is -B/2*A.
quadratic([A,B,C], [X]):-
underRoot([A,B,C], UnderRootResult),
UnderRootResult>0,
X is -B - sqrt(UnderRootResult)/2*A,
X is -B + sqrt(UnderRootResult)/2*A.
(This is probably full of mistakes, so excuse me in advance)
Running this will give me the undefined procedure error for underRoot/2. I don't really get why this happens. I feel like I have the general idea of how to program this but that I'm making lots of newbie mistakes. I can;t seem to find out what the problem is though, so I would appreciate any help!
edit: Also, if I'm allowed to ask two questions at once, how would I get both X's in the case of >0 in a list as one result?
There are many things here. First of all, usually all calls in the body are put on the same column, but that is not really an error.
Furthermore I do not find an underRoot/2 predicate. We can implement one like:
underRoot([A,B,C],X) :-
X is B*B-4*A*C.
Furthermore you always put [X] in the head of the clauses. But in case UnderRoot is less than zero, there are no solutions, so the list should be []. Furthermore in case UnderRoot > 0, there are two solutions, so the solution should be [X1,X2].
Finally if you write -B/2*A, it will be interpreted like: (-B/2)*A, so you will multiply with A. So you will need to use -B/(2*A).
So this brings us to a following proposal:
quadratic(L, []) :-
underRoot(L, U),
U < 0.
quadratic([A,B,C], [X]) :-
underRoot([A,B,C],0),
X is -B/(2*A).
quadratic([A,B,C], [X1, X2]) :-
underRoot([A,B,C],U) :-
SU is sqrt(U),
X1 is (-B-SU)/(2*A),
X2 is (-B+SU)/(2*A).

Determining successor in prolog using recursion

I'm trying (failing) to understand an exercise where I'm given the following clauses;
pterm(null).
pterm(f0(X)) :- pterm(X).
pterm(f1(X)) :- pterm(X).
They represent a number in binary, eg. f0(null) is equivalent to 0, f1(null) is equivalent to 1, etc.
The objective is to define a predicate over pterm such that one is the successor of the other when true. It seems like a relatively simple exercise but I'm struggling to get my head around it.
Here is the code I've written so far;
incr(X,Y) :- pterm(f0(X)), pterm(f1(Y)).
incr(X,Y) :- pterm(f0(f1(X))), pterm(f1(f1(Y))).
Having tested this I know it's very much incorrect. How might I go about inspecting the top level arguments of each pterm?
I've made minimal progress in the last 4 hours so any hints/help would be appreciated.
1)
I'll start with the "how to inspect" question, as I think it will be the most useful. If you're using swi-prolog with xpce, run the guitracer:
?- consult('pterm'). % my input file
% pterm compiled 0.00 sec, 5 clauses
true.
?- guitracer.
% The graphical front-end will be used for subsequent tracing
true.
?- trace. % debugs step by step
true.
[trace] ?- pterm(f0(f1(null))). % an example query to trace
true.
A graphical interface will come up. Press the down arrow to unify things step by step. What's going on should make sense fairly quickly.
(use notrace. and nodebug. appropriately to exit trace and debug modes afterwards).
2) You seem to misunderstand how predicates work. A predicate is a logical statement, i.e. it will always return either true or false. You can think of them as classical boolean functions of the type "iseven(X)" (testing if X is even) or "ismemberof(A,B)" (testing if A is a member of B) etc. When you have a rule like "pred1 :- pred2, pred3." this is similar to saying "pred1 will return true if pred2 returns true, and pred3 returns true (otherwise pred1 returns false)".
When your predicates are called using constants, checking its truth value is a matter of checking your facts database to see if that predicate with those constants can be satisfied. But when you call using variables, prolog goes through a wild goose chase, trying to unify that variable with all the allowable stuff it can link it to, to see if it can try to make that predicate true. If it can't, it gives up and says it's false.
A predicate like incr(X,Y) is still something that needs to return true or false, but, if by design, this only becomes true when Y is the incremented version of X, where X is expected to be given at query time as input, then we have tricked prolog into making a "function" that is given X as input, and "returns" Y as output, because prolog will try to find an appropriate Y that makes the predicate true.
Therefore, with your example, incr(X,Y) :- pterm(f0(X)), pterm(f1(Y)). makes no sense, because you're telling it that incr(X,Y) will return true for any X,Y, as long as prolog can use X to find in the fact database any pterm(f0(X)) that will lead to a known fact, and also use Y to find a pterm(f1(Y)) term. You haven't made Y dependent on X in any way. This query will succeed for X = null, and Y = null, for instance.
Your first clause should be something like this.
incr(X,Y) :- X = pterm(f0(Z)), Y = pterm(f1(Z)).
where = performs unification. I.e. "find a value for Z such that X is pterm(f0(Z)), and for the same value of Z it also applies that Y = pterm(f1(Z))."
In fact, this could be more concisely rewritten as a fact:
incr( pterm(f0(Z)), pterm(f1(Z)) ).
3)
Your second clause can be adapted similarly. However, I'm not sure if this is correct in terms of the logic of what you're trying to achieve (i.e. binary arithmetic). But I may have misunderstood the problem you're trying to solve.
My assumption is that if you have (0)111, then the successor should be 1000, not 1111. For this, I would guess you need to create a predicate that recursively checks if the incrementation of the digits below the currently processed one results in a 'carried' digit.
(since the actual logic is what your assignment is about, I won't offer a solution here. but hope this helps get you into grips with what's going on. feel free to have a go at the recursive version and ask another question based on that code!)

gprolog - Simple way to determine whether one list is a permutation of another

I'm trying to write a prolog program that determines whether one list is a permutation of another. Input is of the form perm(L,M), which will be true if and only if list L is a permutation of list M.
This is for my AI class, so I cannot just use the nifty little permutation predicate that gprolog already provides. Our professor noted that the member predicate might be useful, but any ideas I have that involve it seem to require very tricky and not-so-declarative things (and I'm assuming there is a way to solve this without getting too advanced, since the class is new to prolog.)
Anyway, one way to check would supposedly be to see that L and M are the same size, each L element is in M, and each M element is in L (there's a use of member!). However, this wouldn't be enough for cases like [2,2,4] and [4,4,2], among others.
Another way could be to ensure that the same counts of each element are in the opposite list, but my impression of prolog is that any kind of variable 'memory' is rather difficult business (in fact, it seems that the example programs I see that perform sorts, etc., aren't really manipulating data at all; they're just 'hypothetically' rearranging things and then telling you yes or no...?)
Mentally, one could just sort both lists and check elements side-by-side, but that, among tons of other ways to think of it, seems a little too object-oriented...
Any hints? My biggest trouble seems to be (as mentioned) the fact that doing "operations" seems to be more like asking about them and hoping that things stay true long enough to get where you want.
**UPDATE: gprolog does offer a delete functionality, but it comes with the declarative-related trouble I was expecting, given an attempt like this:
perm([LH|LT], R) :- member(LH,R), delete([LH|LT],LH,R), perm(LT,R).
In the manual, delete is defined like this: "delete(List1, Element, List2) removes all occurrences of Element in List1 to provide List2. A strict term equality is required, cf. (==)/2"
Execution:
{trace}
| ?- perm([1,2,3],[3,1,2]).
1 1 Call: perm([1,2,3],[3,1,2]) ?
2 2 Call: member(1,[3,1,2]) ?
2 2 Exit: member(1,[3,1,2]) ?
3 2 Call: delete([1,2,3],1,[3,1,2]) ?
3 2 Fail: delete([1,2,3],1,[3,1,2]) ?
2 2 Redo: member(1,[3,1,2]) ?
2 2 Fail: member(1,[3,1,2]) ?
1 1 Fail: perm([1,2,3],[3,1,2]) ?
(1 ms) no
**UPDATE 2: I think I might have figured it out! It's kind of verbose, but I have tested it for quite a few cases and haven't found a bad one yet. If someone sees a major issue, please point it out:
perm([],[]).
perm([LH|LT],R) :- length([LH|LT],A), length(R,B), A == B, member(LH,R), select(LH,[LH|LT],X), select(LH,R,Y), perm_recurse(X, Y), !.
perm_recurse([],X). %If we get here, all elements successfully matched
perm_recurse([LH|LT],R) :- member(LH,R), select(LH,[LH|LT],X), select(LH,R,Y), perm_recurse(X, Y), !.
I do like the cut operator..
Always good to define more general predicate and use it in a narrowed fashion:
perm(X,L):- mselect(X,L,[]).
mselect([A|B],L,R):- select(A,L,M), mselect(B,M,R).
mselect([],L,L).
member is no good as it leaves the second list unchanged. delete is no good either as it deletes the multiplicities.
You could use append though. :) It too combines picking and removing:
perm([A|B],L):- length(L,N), between(0,N,I),length(X,I),
append(X,[A],Y), append(Y,Z,L),
append(X,Z,M), perm(B,M).
perm([],[]).
perm(L, M) :- sort(L, X), sort(M, X).
This gets you pretty close and is fully declarative ("two lists are permutations of each other if they have the same sorted representation", but sorting in Prolog removes duplicates). However, it will succeed for cases like perm([1,2], [2,2,2,1]) which I'm not sure if you want. It will handle [2,2,4] and [4,4,2] though, since they both sort to [2,4]. Another solution would be something like this:
perm([], []).
perm([L|Ls], M) :- select(L, M, Ms), !, perm(Ls, Ms).
This version won't succeed for [2,2,4] and [4,4,2], but it will properly fail for [1,2] and [2,2,2,1]. I'm not sure which one you want, but I think one or the other of these is probably correct.
The usual model to follow is inductive.
If you know how to build all permutation of N-1 elements, then all permutations of N elements are obtained inserting the element in all available positions.
A 'trick of the trade' is using the select/3 builtin, that, like member, 'peek' an element, but removes it from the list and 'returns' the smaller list. Those verbs are not really appropriate for Prolog. Let's say that select/3 is a relation among an element, a list containing it, and an identical list where it's missing.
Then let Prolog do all the search... The resulting code is really tiny...
just sort both lists and compare result

Need Help Understanding Somethings In Prolog

Am a beginner in Prolog and finding it hard to understand how backtracking works when using rules. I don't even know if backtracking works in rules(want to know it properly).
I have the following program that sums all the even integers in a list. I wrote it myself but finding it hard to understand the steps it takes to find the solution.
evenN(X):- (X mod 2) =:= 0.
sumEven([], 0).
sumEven([H|T], X):- evenN(H), sumEven(T,Y), X is Y+H.
sumEven([H|T], X):- \+evenN(H), sumEven(T,X).
output:::
?- sumEven([1,2,3,4,5,6],X).
X = 12
Need help in understand it better. I try to use the trace utility to understand the output but i don't understand it, that is why am asking it here.
QUESTIONS:
1)
When i comment out the second rule(last line), it gives me fail as an answer because 1 is not an even number and the whole sumEven() fail because evenN() fails which i understand. My question is: what happens afterwards? Does it go back to the top and try the sumEven([], 0) fact or ? I just want to know what happens.
2)
When the last line(second rule) is included, and the first rule fails, when it backtracks, does it look for another sumEven() that follows it(like the way the second rule follows the first rule which fails) or it goes back to the top and test sumEven([], 0) fact and start it from there?
I need to understand how it backtracks when rules are being used in prolog specifically in recursive situations like this one.
3)
I found the following code(recursive) on the net. It divides a list into positive and negative lists.
% predicates
split(list,list,list)
% clauses
split([],[],[]).
split([X|L],[X|L1],L2):-
X>= 0,
!,
split(L,L1,L2).
split([X|L],L1,[X|L2]):-
split(L,L1,L2).
Output :
Goal: split([1,2,-3,4,-5,2],X,Y)
X=[1,2,4,2], Y=[-3,-5]
Can someone help me to understand the way it works to find the solution? I mean i want to understand step by step how it executes to come up with the solution.
Matching clauses are tried in the order they appear in the program. In nice declarative Prolog programs, the order of clauses does not change the meaning of your program. This is close to logic, where disjunction is commutative. sumEven/2 has this property. It is spectacularly misnamed though, since the sum is the second argument of the relation, not its first. A better name would be for example even_sum/2, you may come up with even better names. split/3 uses !/0, which destroys this property and lets the order of clauses matter. For this reason, a local if-then-else ((->)/2 and (;)/2) seems to be a better fit in this case. Instead of trace/0, use SWI-Prolog's graphical tracer with ?- gtrace, your_goal., it also shows you at which points alternatives remain to be tried. In general, think in terms of relations and ask: When does this clause hold? It holds if ... etc. This makes it possible to reason about much larger programs, where the exact flow of execution may be harder to understand.
See if you can get hold of "Prolog Programming for Artificial Intelligence" by Ivan Bratko.
He explains the process Prolog follows to satisfy goals very well.
I'll try to answer your questions individually:
clause 1: evenN(X):- (X mod 2) =:= 0.
clause 2: sumEven([], 0).
clause 3: sumEven([H|T], X):- evenN(H), sumEven(T,Y), X is Y+H.
clause 4: sumEven([H|T], X):- \+evenN(H), sumEven(T,X).
QUESTIONS:
1) When i comment out the second rule(last line), it gives me fail as an answer because 1 is not an even number and the whole sumEven() fail because evenN() fails which i understand. My question is: what happens afterwards? Does it go back to the top and try the sumEven([], 0) fact or ? I just want to know what happens.
A: You comment-out clause 4. Prolog tries to satisfy the goal, first trying clause 2, which fails because the list is not empty, it then tries clause 3, which fails on rule 1 when H is odd. It will now try to find another clause following on from clause 3 (it will not backtrack previous to clause 3) which will fail since you commented it out, and therefor the goal fails.
2) When the last line(second rule) is included, and the first rule fails, when it backtracks, does it look for another sumEven() that follows it(like the way the second rule follows the first rule which fails) or it goes back to the top and test sumEven([], 0) fact and start it from there?
A: No it does not backtrack when clause 3 fails but continues on to the next clause (4).
I need to understand how it backtracks when rules are being used in prolog specifically in recursive situations like this one.
A: If the rule evenN(H) succeeds, the sumEven(T, Y) starts the whole process again from clause 2 using T and Y. If sumEven(T,Y) fails for some reason, clause three will fail and Prolog backtrack and try clause 4. If the current call is sumEven([2,3,...],X) and sumEven([3,...],Y) fails for some reason, Prolog will backtrack and try to find another clause sumEven([2,3,...],X) following on from clause 3.
3) I found the following code(recursive) on the net. It divides a list into positive and negative lists.
clause 1: split([],[],[]).
clause 2: split([X|L],[X|L1],L2):- X>= 0, !, split(L,L1,L2).
clause 3: split([X|L],L1,[X|L2]):- split(L,L1,L2).
Can someone help me to understand the way it works to find the solution? I mean i want to understand step by step how it executes to come up with the solution.
A: I'll use a shorter goal split(numlist, PosList, NegList) with numlist = [1,-1,2,-2]. Very roughly it works as follows (It actually uses a stack to place the matched values on and only instantiates the variables when it's goal finally succeeds when it unrolls this stack - see the Bratko book for the finer details):
Clause 1 fails since numlist is not empty.
Clause 2 is applied with: split([1|-1,2,-2],[1|L1],[Y|L2]) - since 1 >=0 PosList will now be [1], and split will be applied to the tail of numlist=[-1,2,-2].
Clause 1 again fails. Clause 2 is applied with split([-1|2,-2],[-1| L1],[Y|L2]) - it fails since -1 < 0, and Prolog will apply clause 3 with split([-1|2,-2], [1], [-1|L2] - NegList will now be [-1], and again split will be aplied to the tail of numlist=[2,-2].
Clause 1 fails; clause 2 succeeds and PosList becomes [1,2], and split is applied to numlist=[-2].
Clause 1 & 2 fails; clause 3 succeeds and NegList becomes [-1,-2]. the tail of numlist is empty and clause 1 succeeds and PosList=[1,2] and NegList[-1,-2] is returned.

Resources