Chain of dominos - prolog

I am learning prolog and solving some exercises on exercism.io. And I am stuck. I don't want to search for a solution on the internet, thus I will only a little help on the part of the exercise, since I don't understand where my mistake is, nor how to debug it.
The exercise is to create a legal chain of dominos. For that I wanted to write a simple checker.
[(1,2), (2,3), (3,4), (4,1)] as well as [(1,1)] or [] are legal. [(1,2)], [(1,2), (3,1)] or [(1,2),(2,3)] are illegal. I can check it with my is_chain:
is_loop([]).
is_loop([(X,X)]).
is_loop([(L,_)|Xs]) :-
last(Xs, (_, L)).
is_chain_no_loop([]).
is_chain_no_loop([(_, _)]).
is_chain_no_loop([(_,L), (L,Y)|Xs]) :-
is_chain_no_loop([(L,Y)|Xs]).
is_chain(X) :-
is_loop(X), is_chain_no_loop(X).
I split it into two parts. is_loop checks, whether the first and last element is compatible, is_chain_no_loop check the inner chain.
Here is where my confusion begins.
I can ask prolog, what kind of list are valid:
is_chain(R).
I get the following:
R = []
R = [(_1370,_1370)]
R = [(_1370,_1372), (_1372,_1370)]
R = [(_1370,_1372), (_1372,_1384), (_1384,_1370)]
R = [(_1370,_1372), (_1372,_1384), (_1384,_1396), (_1396,_1370)]
R = [(_1370,_1372), (_1372,_1384), (_1384,_1396), (_1396,_1408), (_1408,_1370)]
R = [(_1370,_1372), (_1372,_1384), (_1384,_1396), (_1396,_1408), (_1408,_1420), (_552,_502)]
I understand all but the last one. I am using SWISH, the online SWI-Prolog.
Why on earth is the last domino of R wrong? _1420 doesn't match with _552, and _502 doesn't match the first one's _1370.
On top of that, (since I assumed that is_chain is working correctly, but apparently it isn't) I started to implement chain, were given a Pile of dominos, I could get the proper Chain (if any).
chain([], Chain) :- is_chain(Chain).
chain([P, Pile], []) :- chain(Pile, [P]).
Now, this is not complete, but I don't understand things here either.
Given a Chain, it is a valid chain, if it is_chain. Simple.
If I don't have a Chain, then I just pick one P from the Pile and start with that.
Except that chain([(1,1)], R) is false. However is_chain([(1,1)]) is true.
Considering everything, there seems to be something profound, that I don't understand about prolog or its execution (or its search). I am sorry that I can't break it down to a simpler example.
Edit:
After thinking more, I realized that is_chain can be implemented way simpler with a recursion that "eats" up the dominos:
is_chain([]).
is_chain([(X,X)]).
is_chain([(X,Y), (Y, Z)|Ls]) :-
is_chain([(X,Z)|Ls]).
However, this leads to the same solutions...

The problem is that I don't understand prolog :D
#TessellatingHeckler pointed out, that I can test is_chain with is_chain(Dominos), Dominos = [(First,_)|_Rest].
This confirms, that the code works just fine.
chain is just obviously wrong.

Related

Comprehend Prolog Function, how to intermittently print results

I'm endeavouring to understand the following Prolog code:
most_probable_hmm_path(Words,Path) :-
probable_paths(Words,[1-[start]],PPaths),
keymax(PPaths,_P-Path1),
reverse(Path1,[start|Path]).
probable_paths([],PPaths,PPaths).
probable_paths([Word|Words],PPaths0,PPaths) :-
findall(PPath,
(outprob(Word,Tag2,PL),
findall(P2-[Tag2,Tag1|Tags],
(member(P1-[Tag1|Tags],PPaths0),
transprob(Tag1,Tag2,PT),
P2 is PL*PT*P1),
AllPaths),
keymax(AllPaths,PPath)),
PPaths1),
probable_paths(Words,PPaths1,PPaths).
keymax(AllPaths,U-V) :-
aggregate(max(N,P), member(N-P,AllPaths), max(U,V)).
It is an implementation of the Viterbi algorithm.
I want to understand how the data structures within the code at various locations are populated, what they look like. Is it possible to intersperse the equivalent of 'print' statements within the algorithm so I can see what is going on at each step? I've often done this when coding in Java or Python and I find it's a more or less useful mechanism to 'grok' the guts of a program.
In case you're interested I've been using it with the following probabilities:
outprob(a,det,0.300).
outprob(can,aux,0.010).
outprob(can,v,0.005).
outprob(can,n,0.001).
outprob(he,pron,0.070).
transprob(start,det,0.30). transprob(v,det,0.36).
transprob(start,aux,0.20). transprob(v,aux,0.01).
transprob(start,v,0.10). transprob(v,v,0.01).
transprob(start,n,0.10). transprob(v,n,0.26).
transprob(start,pron,0.30). transprob(v,pron,0.36).
transprob(det,det,0.20). transprob(n,det,0.01).
transprob(det,aux,0.01). transprob(n,aux,0.25).
transprob(det,v,0.01). transprob(n,v,0.39).
transprob(det,n,0.77). transprob(n,n,0.34).
transprob(det,pron,0.01). transprob(n,pron,0.01).
transprob(aux,det,0.18). transprob(pron,det,0.01).
transprob(aux,aux,0.10). transprob(pron,aux,0.45).
transprob(aux,v,0.50). transprob(pron,v,0.52).
transprob(aux,n,0.01). transprob(pron,n,0.01).
transprob(aux,pron,0.21). transprob(pron,pron,0.01).
And checking the results like so:
?- most_probable_hmm_path([he,can,can,a,can],Sequence).
Sequence = [pron, aux, v, det, n].

Parse To Prolog Variables Using DCG

I want to parse a logical expression using DCG in Prolog.
The logical terms are represented as lists e.g. ['x','&&','y'] for x ∧ y the result should be the parse tree and(X,Y) (were X and Y are unassigned Prolog variables).
I implemented it and everything works as expected but I have one problem:
I can't figure out how to parse the variable 'x' and 'y' to get real Prolog variables X and Y for the later assignment of truth values.
I tried the following rule variations:
v(X) --> [X].:
This doesn't work of course, it only returns and('x','y').
But can I maybe uniformly replace the logical variables in this term with Prolog variables? I know of the predicate term_to_atom (which is proposed as a solution for a similar problem) but I don't think it can be used here to achieve the desired result.
v(Y) --> [X], {nonvar(Y)}.:
This does return an unbound variable but of course a new one every time even if the logical variable ('x','y',...) was already in the term so
['X','&&','X'] gets evaluated to and(X,Y) which is not the desired result, either.
Is there any elegant or idiomatic solution to this problem?
Many thanks in advance!
EDIT:
The background to this question is that I'm trying to implement the DPLL-algorithm in Prolog. I thought it would by clever to directly parse the logical term to a Prolog-term to make easy use of the Prolog backtracking facility:
Input: some logical term, e.g T = [x,'&&',y]
Term after parsing: [G_123,'&&',G_456] (now featuring "real" Prolog variables)
Assign a value from { boolean(t), boolean(f) } to the first unbound variable in T.
simplify the term.
... repeat or backtrack until a assignment v is found so that v(T) = t or the search space is depleted.
I'm pretty new to Prolog and honestly couldn't figure out a better approach. I'm very interested in better alternatives! (So I'm kinda half-shure that this is what I want ;-) and thank you very much for your support so far ...)
You want to associate ground terms like x (no need to write 'x') with uninstantiated variables. Certainly that does not constitute a pure relation. So it is not that clear to me that you actually want this.
And where do you get the list [x, &&, x] in the first place? You probably have some kind of tokenizer. If possible, try to associate variable names to variables prior to the actual parsing. If you insist to perform that association during parsing you will have to thread a pair of variables throughout your entire grammar. That is, instead of a clean grammar like
power(P) --> factor(F), power_r(F, P).
you will now have to write
power(P, D0,D) --> factor(F, D0,D1), power_r(F, P, D1,D).
% ^^^^ ^^^^^ ^^^^
since you are introducing context into an otherwise context free grammar.
When parsing Prolog text, the same problem occurs. The association between a variable name and a concrete variable is already established during tokenizing. The actual parser does not have to deal with it.
There are essentially two ways to perform this during tokenization:
1mo collect all occurrences Name=Variable in a list and unify them later:
v(N-V, [N-V|D],D) --> [N], {maybesometest(N)}.
unify_nvs(NVs) :-
keysort(NVs, NVs2),
uniq(NVs2).
uniq([]).
uniq([NV|NVs]) :-
head_eq(NVs, NV).
uniq(NVs).
head_eq([], _).
head_eq([N-V|_],N-V).
head_eq([N1-_|_],N2-_) :-
dif(N1,N2).
2do use some explicit dictionary to merge them early on.
Somewhat related is this question.
Not sure if you really want to do what you asked. You might do it by keeping a list of variable associations so that you would know when to reuse a variable and when to use a fresh one.
This is an example of a greedy descent parser which would parse expressions with && and ||:
parse(Exp, Bindings, NBindings)-->
parseLeaf(LExp, Bindings, MBindings),
parse_cont(Exp, LExp, MBindings, NBindings).
parse_cont(Exp, LExp, Bindings, NBindings)-->
parse_op(Op, LExp, RExp),
{!},
parseLeaf(RExp, Bindings, MBindings),
parse_cont(Exp, Op, MBindings, NBindings).
parse_cont(Exp, Exp, Bindings, Bindings)-->[].
parse_op(and(LExp, RExp), LExp, RExp)--> ['&&'].
parse_op(or(LExp, RExp), LExp, RExp)--> ['||'].
parseLeaf(Y, Bindings, NBindings)-->
[X],
{
(member(bind(X, Var), Bindings)-> Y-NBindings=Var-Bindings ; Y-NBindings=Var-[bind(X, Var)|Bindings])
}.
It parses the expression and returns also the variable bindings.
Sample outputs:
?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'y']).
Exp = and(_G683, _G696),
Bindings = [bind(y, _G696), bind(x, _G683)].
?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'x']).
Exp = and(_G683, _G683),
Bindings = [bind(x, _G683)].
?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'y', '&&', 'x', '||', 'z']).
Exp = or(and(and(_G839, _G852), _G839), _G879),
Bindings = [bind(z, _G879), bind(y, _G852), bind(x, _G839)].

Why don't I need to check in the member_of_set if Element and Element1 are different?

When using sets, adding an Element to the Set is done like this:
add_to_set(Element, [], [Element]).
add_to_set(Element, [Element | Set], [Element | Set]).
add_to_set(Element, [Element1 | Set], [Element1 | NewSet]) :-
not(Element = Element1),
add_to_set(Element, Set, NewSet).
Now, with this, I thought member_of_set would be like:
member_of_set(Element, [Element|_]).
member_of_set(Element, [Element1|Set]) :-
not(Element = Element1), /* Not necessary */
member_of_set(Element, Set).
This works like a charm, but in this case, not(Element = Element1) is not necessary. I can't seem to figure out why. If you ask for more answers from Prolog, won't it backtrack and succeed on the second clause of member_of_set?
An if it's not necessary in the member_of_set, then why is it necessary in the add_to_set?
Please keep in mind that I'm only studying since one month Prolog, so I'm still in some kind of mind switch...
I know that using cut, there's probably better alternatives, but cut shouldn't be used.
it's not necessary in the member_of_set
because it doesn't hurt if the list is not a set. Only you will end up - in case you pass a list with repeated elements inside - with multiple solution, but still each solution is valid.
OTOH, add_to_set leads to invalid data if you remove the test:
?- add_to_set(1,[],A),add_to_set(1,A,B).
A = B, B = [1] ;
A = [1],
B = [1, 1] ;
false.
for a friendly explanation of cuts, and why are necessary in Prolog, see this page
contains(Element, [Element|_]).
contains(Element, [_|Set]) :-
contains(Element, Set).
You can read this as: "Element is in a Set, if it's the head of that Set, or if it's in the tail of that Set". If you're checking if it's in the tail, there's no need to check if it's equal to the head, except for performance reasons.
Actually, this way, you're not even restricting it to a Set. It's a general contains.

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

Guess who-like game in Prolog

I'm developing a Guess Who? game using Prolog. The mechanics of the game are very easy. A player (in this case, the human) chooses one person among many possible ones, and the other player (the computer) starts asking yes/no questions about some attributes of the person. Eventually, with the given answers, there will only be one possible person.
So far, I've been able to make a set of rules and predicates so that the computer can guess the person based on the questions that have been asked so far. I have a set of suspects - those are the people that, with the available clues, could fit.
suspect('Person 1') :- eyes(blue) , age(old) , gender(male).
The predicates for the attributes are defined so that they will be true either if the question regarding that attribute has not been asked yet, or if the question has been asked and the answer matches the attribute of the suspect.
gender(X) :- not(asked_gender) ; value_of(gender, X).
That way, if two suspects share the same eyes and age and different gender, as long as the gender remains unasked, both of them will be plausible suspects.
However, the hard part now is to automate the process of asking those questions. Basically, I'm looking forward to a solution where Prolog were able to get the possible values for the attributes from the suspects' predicates, instead of listing theme somewhere else. I'm pretty sure there must be a way of doing this, given prolog is able to use the program's code as data itself.
How could I do that?
This works in SWI-Prolog :
:- dynamic value/1.
suspect('Person 1') :- eyes(blue) , age(old) , gender(male).
suspect('Person 2') :- eyes(green) , age(young) , gender(male).
suspect('Person 3') :- eyes(brown) , age(young) , gender(male).
fetch(Criterion, Value) :-
retractall(value(_)),
assert(value([])),
forall(clause(suspect(_), Body),
check(Body, Criterion)),
retract(value(Value)).
check((F, T), Criterion) :-
F =..[Criterion, V1],
retract(value(V2)),
( member(V1, V2) -> V3 = V2; V3 = [V1 | V2]),
assert(value(V3)).
check(T, Criterion).
check((_F, T), Criterion) :-
check(T, Criterion).
check((F), Criterion) :-
F =..[Criterion, V1],
retract(value(V2)),
( member(V1, V2) -> V3 = V2; V3 = [V1 | V2]),
assert(value(V3)).
check((_F), _Criterion).
For example :
?- fetch(gender, Value).
Value = [male].
?- fetch(eyes, Value).
Value = [brown,green,blue].
Well, I would imagine a construction like this:
go :-
findall(People,suspect(People),SuspectList),
length(SuspectList,1),
member(Perb,SuspectList),
write('It is '),write(Perb),write('!!'),nl,!.
go :-
askQuestion,
go.
Where in askQuestion/0 you'd ask questions with the read/1 predicate and assert/1 the answers.
This is where you could try and make it 'intelligent' or you could just iterate over the different questions.

Resources