What is the explanation of this code (Prolog)? - prolog

I am trying to learn Prolog. I have a problem and the solution for that in Prolog. Though I am unable to understand the code completely.
The call of the code goes like this-
conc(Before,[c|After],[a,b,c,d]) .
This code will return
Before = [a,b]
After = [d]
I have the solution -
conc([],L,L).
conc([X|L1],L2,[X|L3]) :- conc(L1,L2,L3) .
I am not able to understand the flow of the program completely. Let me start with a dry run. I added some write command in order understand the code flow. The code now looks like this -
conc([],L,L):- write("Line1: "), write(L).
conc([X|L1],L2,[X|L3]) :-
write("Line-2: "), write(L1), write(" "),
write(L2), write(" "), write(L3), conc(L1,L2,L3) .
Initial call is -
conc(Before,[c|After],[a,b,c,d]) .
At this moment, the call goes to line 2 (because, Before is unknown term which is not empty)which is :
conc([X|L1],L2,[X|L3]) :-
write("Line-2: "), write(L1), write(" "),
write(L2), write(" "), write(L3), conc(L1,L2,L3) .
At this point, X=[a], l1= unknown, L2=[c|After] and L3=[b,c,d]. This prints -
Line2: _G481 [c|_G368] [b,c,d]
This will again call the recursion(code line 2) with the following value:
cons(L1, [c|After], [b,c,d]). (L1 is unknown still now)
And, prints -
Line2: _G494 [c|_G368] [c,d]
Now the next call will be :
cons(L1, [c|After], [c,d]).
But , I can see while printing the customized comments in the code, that, at this point the code control goes to #line 1 which I am not able to understand. Because, now,
L1= unknown(just as all the previous calls).
L(parameter 2)= [c|After]
L(parameter 3) = [c,d].
But, the control goes to the #line 1, and it prints :
Line1: [c,d]
I thought prolog executes the code from left to right. So, as per my understanding, while executing the value of L should be [c,d].
My question is:
1. After the second call, L1 is undefined as all the calls as before. And, second and third parameters , both are L. So, why, after second call the control goes to the #line1.?
2. Is my understanding correct in this matter ? "I thought prolog executes the code from left to right. So, as per my understanding, while executing the value of L should be [c,d]."
Thanks in advance...
Please help me out!!

You cannot expect to understand everything that is happening here if you look at it procedurally, because there is too much going on at the same time. This is especially true if you are just beginning to learn the language.
A good approach for learning Prolog is to think declaratively, and ask: What are the conditions that make this hold?
In addition, you are currently writing atoms when you actually mean to write variables. Please correct your post to say for example:
cons(L1, [c|After], [c,d])
Note that After is a variable, and after is an atom.
Now, leaving everything else aside, just consider this single goal in isolation. Try it with:
?- cons(L1, [c|After], [c,d]).
In complete accordance with our expectation, we get the solution:
L1 = [],
After = [d]
Thus, it suffices to understand that this goal can be derived in isolation. Also notice the difference between X = [a] and X = a, which you are currently intermingling.

Related

Not getting full result when output is on one line

Im new at Prolog , and I am trying some manipulation on graphs .
I have a problem in my implementation, and since it is very long and complicated to expose , I will give a simple and similar problem .
Let say we have the following graph :
edge(a,e).
edge(e,d).
edge(d,c).
edge(c,b).
edge(b,a).
edge(d,a).
edge(e,c).
edge(f,b).
And I wanted to make this graph bidirected . I use the following code :
graph(Graph):-findall(A-B, edge(A,B), L),
findall(B-A, edge(A,B), L1),
append(L, L1, Graph).
when executing the query I get this result :
?- graph(Graph).
Graph = [a-e, b-a, c-b, d-a, d-c, e-c, e-d, f-b, ... - ...|...].
My problem is not in the code my problem is in the results as you can see I don't get the complete results, its always giving me only 8 edges and the rest are not shown.
How to solve this ?
graph(Graph),writeln(Graph).
writeln/1 writes out the entire variable to the output.
From #WillemVanOnsem
If you write graph(G);true. then the program will pause after the first statement. Next you can hit W and it will again write the answer but now in full.

Changing order of arguments in predicate changes result

Hello I'm new to Prolog and some things about it just confuse me.
So I have this list of Facts and a predecate:
parent(gerlinde,mark).
parent(gerlinde,lena).
.
.
(and so on)
female(gerlinde).
.
.
(and so on)
male(mark).
sister(S,X) :- parent(F,S),parent(F,X),male(F),
parent(M,S),parent(M,X),female(M),female(S),S\==X.
So if I do ?-sister(S,X). I get the answers correclty without the answer that S is the sister of herself (S=X). However, if I Change the order like that:
sister(S,X) :- S\==X,parent(F,S),parent(F,X),male(F),
parent(M,S),parent(M,X),female(M),female(S).
or like that:
sister(S,X) :- parent(F,S),S\==X,parent(F,X),male(F),
parent(M,S),parent(M,X),female(M),female(S).
then I suddenly get the answer S=X too. So why is that happening? In my understanding there should be no difference between both predicates.
This is because X\==S is the same as \+X == S, and \+T means 'T cannot be proven'. So, in your second predicate:
sister(S,X) :- S\==X,parent(F,S),parent(F,X),male(F),
parent(M,S),parent(M,X),female(M),female(S).
When S\==X is called, both S and X are variables. Thus, it 'cannot be proven' that S == X and this goal succeeds.
Then, as the predicate continues to be evaluated, parent(F,S) will ground S - in your case, to mark.
Then, parent(F,X) will ground X - to mark again! And it is never required again that S be different from X. Of course, with S = X = mark the predicate fails, as mark is not a female (female(S) fails). But not with lena; she will indeed be her own sister.

Using "=" in Prolog

I'd like to know why I get an error with my SWI Prolog when I try to do this:
(signal(X) = signal(Y)) :- (terminal(X), terminal(Y), connected(X,Y)).
terminal(X) :- ((signal(X) = 1);(signal(X) = 0)).
I get the following error
Error: trabalho.pro:13: No permission to modify static procedure
'(=)/2'
It doesn't recognize the "=" in the first line, but the second one "compiles". I guess it only accepts the "=" after the :- ? Why?
Will I need to create a predicate like: "equal(x,y) :- (x = y)" for this?
Diedre - there are no 'functions' in Prolog. There are predicates. The usual pattern
goes
name(list of args to be unified) :- body of predicate .
Usually you'd want the thing on the left side of the :- operator to be a predicate
name. when you write
(signal(X) = signal(Y))
= is an operator, so you get
'='(signal(X), signal(Y))
But (we assume, it's not clear what you're doing here) that you don't really want to change equals.
Since '=' is already in the standard library, you can't redefine it (and wouldn't want to)
What you probably want is
equal_signal(X, Y) :- ... bunch of stuff... .
or
equal_signal(signal(X), signal(Y)) :- ... bunch of stuff ... .
This seems like a conceptual error problem. You need to have a conversation with somebody who understands it. I might humbly suggest you pop onto ##prolog on freenode.net or
some similar forum and get somebody to explain it.
Because = is a predefined predicate. What you actually write is (the grounding of terms using the Martelli-Montanari algorithm):
=(signal(X),signal(Y)) :- Foo.
You use predicates like functions in Prolog.
You can define something like:
terminal(X) :- signal(X,1);signal(X,0).
where signal/2 is a predicate that contains a key/value pair.
And:
equal_signal(X,Y) :- terminal(X),terminal(Y),connected(X,Y).

Prolog error in loop

I would need help about Prolog.
I posted my code, the problem is that i do not obtain the expected result.
I want planning actions for moving on table all blocks until is possible. To do this I prompt :
?- do(while(some(x, block(x) & -onTable(x)),pi(x,putOnTable(x))),s0,S).
I expect to see a response like :
S = do(putOnTable(e), do(putOnTable(b), do(putOnTable(c), s0)))
but Prolog returns "false" only. Someone can help me??
% Golog interpreter
%:- [golog_swi].
:- discontiguous clear/2, on/3, onTable/2.
:- op(800,xfy,[&]).
do(E,S,do(E,S)):- primitive_action(E),poss(a,S).
% Primitive Action Declarations.
primitive_action(putOn(_,_)).
primitive_action(putOnTable(_)).
poss(putOn(X,Y),S) :- clear(X,S), clear(Y,S), \+ on(X,Y,S), \+ X=Y.
poss(putOnTable(X),S):- clear(X,S), \+(onTable(X,S)).
% Successor State Axioms.
on(X,Y,do(A,S)):- A = putOn(X,Y); on(X,Y,S), \+ (A = putOnTable(X); A = putOn(X,_)).
onTable(X,do(A,S)) :- A = putOnTable(X); onTable(X,S), \+ A= putOn(X,_).
clear(X,do(A,S)) :- on(Y,X,S), (A = putOn(Y,_) ; A = putOnTable(Y)); clear(X,S), \+ A = putOn(_,X).
% Restore suppressed situation arguments
restoreSitArg(onTable(X),S,onTable(X,S)).
restoreSitArg(on(X,Y),S,on(X,Y,S)).
restoreSitArg(clear(X),S,clear(X,S)).
block(X):- member(X,[a,b,c,d,e]).
% iniTial COndition
onTable(a,s0).
on(b,a,s0).
on(c,b,s0).
clear(c,s0).
onTable(d,s0).
on(e,d,s0).
clear(3,s0).
thank you!!!
Your predicate do/3 cannot succeed because the goal primitive_action/1 will fail with your query.
Currently, while/2 is not described in primitive_action/1 and it seems it is missing also from your program. So you need to extend primitive_action/1 by further facts, or add a new rule to do/3. And in addition to that you need to describe what while/2 means.
This question is actually about Golog. Your mistake is pretty mundane: you didn't copy the Golog interpreter code into your source file/directory.
Golog defines a number of high-level programming constructs, including while-loops and non-deterministic picks (pi), used here. I'm sure you don't want to reinvent Golog, so just go and get it. I'm assuming that your question is part of an assignment of sorts, and your teacher probably pointed you to the Golog interpreter. Otherwise, you can always find it on the pages of the cognitive robotics group at the Univ. of Toronto: http://www.cs.toronto.edu/cogrobo/main/systems/index.html

Prolog, how to show multiple output in write()

go :- match(Mn,Fn),
write('--Matching Result--'),
nl,
write(Mn),
write(' match with '),
write(Fn),
match(Mn1,Fn1).
person(may,female,25,blue).
person(rose,female,20,blue).
person(hock,male,30,blue).
person(ali,male,24,blue).
match(Mn,Fn):-person(Fn,'female',Fage,Fatt),
person(Mn,'male',Mage,Matt),
Mage>=Fage,
Fatt=Matt.
Hi,this is my code...but it's only can show the 1 output...but there are 3 pair of matching in match(X,Y).how to show them all in my go function.
Thank you
You get all your matches if you force backtracking, usually by entering ; (e.g. in SWI Prolog). But you also see that you are getting unnecessary outputs true. This is because the last clause in go is match(Mn1,Fn1). This clause succeeds three times and binds the variables Mn1,Fn1 but then only true is output, because you do not write() after that clause. The fourth time match(Mn1,Fn1) fails and by backtracking you come back to the first clause match(Mn,Fn) that matches, the match is output, etc.
You surely do not want to have this behavior. You should remove the last clause match(Mn1,Fn1) in go. Now by pressing ; you get the 3 matches without any output true in between.
But what you likely want is that the program does the backtracking. To achieve this, you just need to force backtracking by adding false as the last clause. To get proper formatting of the output, use the following program. The last clause go2. is added to get true at the very end.
go2 :- write('--Matching Result--'), nl,
match(Mn,Fn),
write(Mn), write(' match with '), write(Fn), nl,
fail.
go2.
This technique is called failure driven loop.
If you have any predicate that has multiple results and want to to find all of them, you should use findall/3
For example, in your case, you could do something like:
findall([X,Y], match(X,Y),L).
L will be a list that will contain all the X,Y that satisfy match(X,Y) in the format [X,Y].
for example, assuming that:
match(m1,f1).
match(m2,f2).
the result will be L = [ [m1,f1], [m2,f2] ]
note that you can define the format as you wish, for example you could write:
findall(pair(X,Y), match(X,Y), L).
L = [ pair(m1,f1), pair(m2,f2) ]
findall( X, match(X,Y), L).
L = [ m1, m2]
findall( 42, match(X,Y), L).
L = [42, 42]
then you have to recurse on the list to print them.
However, if you wish to find one result, run some code and then continue you could use forall/2:
forall(match(X,Y), my_print(X,Y).
Prolog is a lazy language. Which means that it will stop once it has found a condition that made your problem true. This will be the very first match alone.
IF your code is working (I haven't tried it), then you should try and run the match-statement like this in your prolog inspector: match(X,Y)
The prolog inspector will return all states and print them for you.

Resources