Prolog: Distance between cities - prolog

I'm new to Prolog. I'm trying to make a simple program that find the distance between cities using recursive structure. The problem occurs when I try to find sum distance between cities that are not directly connected (e.g. london to sydney).
distance(london,newyork,3.2).
distance(london,capetown,5.8).
distance(london,rome,0.8).
distance(london,panama,4.5).
distance(panama,sydney,7.7).
distance(newyork,sanfrancisco,2.5).
distance(newyork,panama,1.9).
distance(sanfrancisco,sydney,6.2).
distance(sanfrancisco,tokyo,4.5).
distance(tokyo,calcutta,2.5).
distance(tokyo,sydney,4.1).
distance(sydney,calcutta,4.4).
distance(sydney,capetown,6.0).
distance(capetowm,rome,5.1).
distance(calcutta,cairo,2.2).
distance(cairo,rome,0.9).
connected(X,Y,Distance):-
distance(X,Y,Distance).
connected(X,Y,Distance):-
distance(X,Z,NewDistance),
connected(Z,Y,NewDistance),
Distance is Distance+NewDistance.

You can modify your last rule like this:
connected(X,Y,Distance):- distance(X,Z,Distance1),
distance(Z,Y,Distance2),
SumDistance is Distance1+Distance2,
write(SumDistance).
Here is my result:
1 ?- connected(london,sydney,X).
12.2
true .
The route is London -> Panama -> Sydney. I used trace. to see how it works:
2 ?- trace.
true.
[trace] 2 ?- connected(london,sydney,X)
....
Redo: (7) distance(london, _G1945, _G1946) ? creep
Exit: (7) distance(london, panama, 4.5) ? creep
Call: (7) distance(panama, sydney, _G1950) ? creep
Exit: (7) distance(panama, sydney, 7.7) ? creep
Call: (7) _G1955 is 4.5+7.7 ? creep
Exit: (7) 12.2 is 4.5+7.7 ? creep
Call: (7) write(12.2) ? creep
12.2
Exit: (7) write(12.2) ? creep
Exit: (6) connected(london, sydney, _G1871) ? creep
(I have removed some of the tracing because it was too long).

Related

prolog questions.. fails to invoke predicate

I am trying to understand why duck2 is not called.. Should I cover all cases of the two list being empty, non empty.
duck([H|T], something ) :-
write("*"),
write("?"),
duck2([H|T], T, something_else),
write("Over").
duck2([], [], something_else) :- write("AllDone").
duck2([H|T], [H1,T1], something_else) :-
write("I am here").
trace gives this..
Call: (16) duck([dog, eats], [eats], something) ? creep
Call: (17) write("*") ? creep
*
Exit: (17) write("*") ? creep
Call: (17) write("?") ? creep
?
Exit: (17) write("?") ? creep
Call: (17) duck2([dog, eats], [eats], something_else) ? creep
Fail: (17) duck2([dog, eats], [eats], something_else) ? creep
Fail: (16) duck([dog, eats], [eats], something) ? creep
duck2([H|T], [H1,T1], something_else) :-
% spaced out to line up with the below trace
duck2([H|T], [H1,T1], something_else) :-
Call: (17) `duck2([dog, eats], [eats], something_else)` ? creep
[H1, T1] is a list of two items and [eats] is a list of one item; if you try and unify them, they don't unify:
?- [H1, T1] = [eats].
false
so the call fails.
Should I cover all cases
Well, at least cover enough cases to make the code work. All cases is up to you.

Brother in law predicate for Prolog not working

Here's the relevant code:
married(X,Y) :- wife(X,Y);husband(X,Y).
parent(X,Y) :- father(X,Y) ;mother(X,Y).
brother(X,Y) :-
man(X),
parent(Z,X),
parent(Z,Y),
X \= Y.
brother_in_law(X,Y) :-
brother(X,Z),married(Z,Y).
I've googled and it seems other have been using the exact code for the brother in law predicate so it should be fine? I checked the other predicates and they seem good too.. not sure what is happening.
Also, by not working I mean that it's not acknowledging the relevant relation when I check.
Look at the trace and you will see the problem:
?- trace, brother_in_law(prins-daniel, Y).
Call: (9) brother_in_law(prins-daniel, _11346) ? creep
Call: (10) brother(prins-daniel, _11680) ? creep
Call: (11) man(prins-daniel) ? creep
Exit: (11) man(prins-daniel) ? creep
Call: (11) parent(_11678, prins-daniel) ? creep
Call: (12) father(_11678, prins-daniel) ? creep
Fail: (12) father(_11678, prins-daniel) ? creep
Redo: (11) parent(_11678, prins-daniel) ? creep
Call: (12) mother(_11678, prins-daniel) ? creep
Fail: (12) mother(_11678, prins-daniel) ? creep
Fail: (11) parent(_11678, prins-daniel) ? creep
Redo: (11) man(prins-daniel) ? creep
Fail: (11) man(prins-daniel) ? creep
Fail: (10) brother(prins-daniel, _11680) ? creep
Fail: (9) brother_in_law(prins-daniel, _11346) ? creep
false.
Who is prins-daniel's father? You don't have a fact for that. Who is prins-daniel's mother? You don't have a fact for that either. As a result, you can't find any brothers, so the query fails.
Does this mean you are missing facts or missing code? The code says X and Y are brothers-in-law if X has a brother Z who is married to Y. Is this the only way to have a brother-in-law?
Side note: prins-daniel is not an atom in Prolog as it would be in Lisp. This is a term:
?- write_canonical(prins-daniel).
-(prins,daniel)
The situation is compounded by longer terms:
?- write_canonical(johann-georg-av-hohenzollern).
-(-(-(johann,georg),av),hohenzollern)
Just something to be aware of.

Prolog checking the same fact twice

This is the knowledge database
student(jack,100,21,m).
takes(100,cs01).
takes(100,cs02).
takes(100,cs03).
teaches(doe,cs01).
course(cs01,ai).
course(cs02,cpp).
course(cs03,java).
isTaughtBy(Sname,Lname) :-
teaches(Lname,Mcode),
student(Sname,Scode,_,_),
takes(Scode,Mcode).
When running isTaughtBy(jack,doe) it returns true (like its supposed to) and false (for some reason, probably because jack takes multiple modules).
This is the trace:
[trace] ?- isTaughtBy(jack,doe).
Call: (8) isTaughtBy(jack, doe) ? creep
Call: (9) teaches(doe, _18526) ? creep
Exit: (9) teaches(doe, cs01) ? creep
Call: (9) student(jack, _18526, _18528, _18530) ? creep
Exit: (9) student(jack, 100, 21, m) ? creep
Call: (9) takes(100, cs01) ? creep
Exit: (9) takes(100, cs01) ? creep
Exit: (8) isTaughtBy(jack, doe) ? creep
true ;
Redo: (9) takes(100, cs01) ? creep
Fail: (9) takes(100, cs01) ? creep
Fail: (8) isTaughtBy(jack, doe) ? creep
false.
Why is it redoing takes(100,cs01) if it was already checked above? Why is it returning false even though its clearly defined in the database? What am i not understanding here? I just want it to return true or false if a student is taught by a lecturer on any of the modules they are taking.

singleton variables in prolog query

I am new to Prolog and running into a problem. When I ask the query ?-grandfather(daniel,george) on the data below, I get the wrong answer. I don't understand why my query doesn't work. I also received a warning message stating that [C,D] are singleton variables. This warning no longer occurs. Again, I'm unsure why.
mother(jules,mary).
mother(jules,martha).
mother(jules,andy).
mother(mary,annie).
mother(mary,george).
mother(martha,jesse).
mother(martha,june).
mother(june,camile).
father(daniel,mary).
father(daniel,martha).
father(daniel,andy).
father(adrian,annie).
father(adrian,george).
father(carlo,camile).
brothers(A,B):-father(C,A),father(C,B);mother(D,A),mother(D,B).
grandfather(E,W):-father(E,father(C,W));father(E,mother(D,W)).
You can write your grandfather query more simply:
grandfather(E,W):-father(E,A),father(A,W).
grandfather(E,W):-father(E,A),mother(A,W).
or
grandfather(E,W):-father(E,A),father(A,W);father(E,A),mother(A,W).
and now:
6 ?- grandfather(daniel,george).
true .
7 ?- grandfather(daniel,annie).
true .
Here, we ask Prolog to find the grandson of E where: E is the father of A and A is the father/mother of W.
Or more specifically, to check if daniel has a grandson named george. Prolog checks: daniel has a daughter mary and mary has a son george. So it would return true. If you trace it, you see:
[trace] 3 ?- grandfather(daniel,george).
Call: (6) grandfather(daniel, george) ? creep
Call: (7) father(daniel, _G1931) ? creep
Exit: (7) father(daniel, mary) ? creep
Call: (7) father(mary, george) ? creep
Fail: (7) father(mary, george) ? creep
Redo: (7) father(daniel, _G1931) ? creep
Exit: (7) father(daniel, martha) ? creep
Call: (7) father(martha, george) ? creep
Fail: (7) father(martha, george) ? creep
Redo: (7) father(daniel, _G1931) ? creep
Exit: (7) father(daniel, andy) ? creep
Call: (7) father(andy, george) ? creep
Fail: (7) father(andy, george) ? creep
Redo: (6) grandfather(daniel, george) ? creep
Call: (7) father(daniel, _G1931) ? creep
Exit: (7) father(daniel, mary) ? creep
Call: (7) mother(mary, george) ? creep
Exit: (7) mother(mary, george) ? creep
Exit: (6) grandfather(daniel, george) ? creep
true .
[C,D] are singleton variables indicates that there is one or more variable in the clause that appears only once. This isn't affecting the program, you can still run your queries.
Singleton Variables on SWI Documentation
Thanks for the answer, one last question, i tried to do a rule for cousins like this
cousins(X,Y):-mother(A,X),mother(B,Y),mother(D,A),mother(D,B),father(C,A),father(C,B).
it states that if the mother of X and the mother of Y have the same mother and father X,Y are cousins. but when i ask the query ?- cousins(annie,george) prolog answers YES, and it should not be that way because annie and george are brothers, so i guess there must be a logical mistake
A and B (Mothers of X and Y) can be equal, that is why it gives Yes to brothers.
You should specify that they don't have the same mother and father (A\=B).
Off question:
Using "parent" can reduce your coding in this kind of problems (family trees).
mother(A,B) :- parent(A,B).
Or even:
mother(A,B) :- parent(A,B), female(A).
This way you don't need to apply the cousin problem (or any of this kind, like brothers) to the mother and the father.
In the brothers you have:
brothers(A,B):-father(C,A),father(C,B);mother(D,A),mother(D,B).
It could be:
brothers(A,B):-parent(X,A),parent(X,B).

Some doubts about declarative meaning of a program that prints a list of lists in Prolog

Write a rule that take a list whose elements are themselves lists and
print on each line the elements of internals list:
Example:
?- printList[[1,a],[2,b]]).
1 a
2 b
The solution it the following one:
/* BASE CASE: The list is empty, so there is nothing to print */
printList([]).
printList([P|R]):- printList(P),
!,
nl,
printList(R).
printList([X|R]):- write(X),
!,
printList(R).
I have the printList rule that reaches the base case when the list is empty and in this case there is nothing to print.
If I am not in the base case (the list is not empty) it calls the second rule printList([P|R]) and now I have my first doubt:
The element P is a list because Prolog automatically handles an internal list as an element?
So, If I have something like:
[[1,a],[2,b],[3,c],[4,d]] I have that Prolog automatically match in this way:
P = [1,a] (the first list as the head element)
R = [[2,b],[3,c],[4,d]] (the other 3 list are the element of a tail list)
And then the program calls the printList predicate on the head element (the first list) and this version of the rule writes all the elements in the current list.
Is this right this interpretation?
Now I have some doubts about about the trace of this program, for example if I execute this statement I obtain the following trace:
[trace] ?- printList([[1,a], [2,b]]).
Call: (6) printList([[1, a], [2, b]]) ? creep
Call: (7) printList([1, a]) ? creep
Call: (8) printList(1) ? creep
Fail: (8) printList(1) ? creep
Redo: (7) printList([1, a]) ? creep
Call: (8) write(1) ? creep
1
Exit: (8) write(1) ? creep
Call: (8) printList([a]) ? creep
Call: (9) printList(a) ? creep
Fail: (9) printList(a) ? creep
Redo: (8) printList([a]) ? creep
Call: (9) write(a) ? creep
a
Exit: (9) write(a) ? creep
Call: (9) printList([]) ? creep
Exit: (9) printList([]) ? creep
Exit: (8) printList([a]) ? creep
Exit: (7) printList([1, a]) ? creep
Call: (7) nl ? creep
Exit: (7) nl ? creep
Call: (7) printList([[2, b]]) ? creep
Call: (8) printList([2, b]) ? creep
Call: (9) printList(2) ? creep
Fail: (9) printList(2) ? creep
Redo: (8) printList([2, b]) ? creep
Call: (9) write(2) ? creep
2
Exit: (9) write(2) ? creep
Call: (9) printList([b]) ? creep
Call: (10) printList(b) ? creep
Fail: (10) printList(b) ? creep
Redo: (9) printList([b]) ? creep
Call: (10) write(b) ? creep
b
Exit: (10) write(b) ? creep
Call: (10) printList([]) ? creep
Exit: (10) printList([]) ? creep
Exit: (9) printList([b]) ? creep
Exit: (8) printList([2, b]) ? creep
Call: (8) nl ? creep
Exit: (8) nl ? creep
Call: (8) printList([]) ? creep
Exit: (8) printList([]) ? creep
Exit: (7) printList([[2, b]]) ? creep
Exit: (6) printList([[1, a], [2, b]]) ? creep
true.
This is quite clear for me (I think that my previous reasoning is right) but I am not understanding why whenever it reaches an element in an internal list it calls the printList relation on it (that is a simple element and not a list), for example here:
Call: (8) printList(1) ? creep
Fail: (8) printList(1) ? creep
the program had considered the first list of the original list and then, into it to have to print its first element, why call the printList relation on this simple element
Is it because this simple element may in turn be internal lists?
Something like:
[[[1.1,a1,a2],[1.2,b1,b2]], [2,b]] (in which I have a list that contains 2 lists and the first element it is a list that contains 2 lists. So the program checks if an element it is an element or an internal list?
I think you're over-thinking it. Look at the code:
printList([P|R]):- printList(P),
Right there you can see that printList/1 is being unified with the head of the list. The fact that all the rules of printList/1 match lists and only lists is a fact that you, the human, can immediately see. But Prolog does not "notice" this fact, so if you are to call, say,
printList([1])
the first matching rule is the one above, so it will immediately try to unify printList(1). This will fail, naturally, because 1 is not a list and so doesn't match any of the rules for printList/1. Prolog then backtracks and tries the next rule, which is the one that starts like this:
printList([X|R]):- write(X),
This is clearly going to unify [1] with X = 1, R = [], so it's clearly going to write the first element, the one, and then proceed as usual. There is no magic here involving "internal lists," which as far as I'm aware is not a concept in Prolog at all (if such a thing is treated in the compiler it is well hidden from the user of Prolog).
Prolog isn't psychic; it has to try the rules to see if they fail, even if that attempt is essentially a failing pattern-match in the head of the Horn clause.
I am unable to distinguish your first from your second question so I hope this answers both. :)

Resources