What answers will I get when asking this questions - prolog

I started to learn Prolog and want to solve this task. But I am not quite shure whether I am right or not. Pls, help me
pilots(A,london) = pilots(london, paris)
point(X,Y,Z) = point(X1,Y1,Z1)
letter(C) = word(letter)
noun(alpha) = alpha
'vicar' = vicar
I think that everything will give "no", but the last one will be yes. Z will be equal b, X=Z=b

Just try them in prolog.
Expression
Result
Explanation
pilots(A,london) = pilots(london,paris)
false
Variable A unifies with the atom london, but the atoms london and paris do not.
point(X,Y,Z) = point(X1,Y1,Z1)
true
The variable pairs X and X1, Y and Y1, and Z and Z1 each unify and become the same variable.
letter(C) = word(letter)
false
Although letter/1 and word/1 have the same arity, they have different functors and so do not unify.
noun(alpha) = alpha
false
The structure/term noun(alpha) with functor noun and arity 1 (noun/1) cannot unify with the atom alpha
'vicar' = vicar
true
Text delimited by single quotes (e.g., 'vicar') denotes an atom; the bare word vicar likewise denotes an atom, and, in fact, the exact, same atom as vicar: they unify (because they are identical.

Related

When does Prolog break lines?

Consider the following example program in Prolog:
p(0).
p(1).
b1(T) :-
T = tri(X, Y, Z), p(X), p(Y), c(T), !, p(Z).
c(tri(X, X, _Z)).
SWI Prolog gives some interesting answers for certain queries:\
?- b1(tri(0, Y, Z)).
Y = Z, Z = 0 ;
Y = 0,
Z = 1.
Note that it did break the line in the second answer, but not in the first one.
This makes me wonder, what are the exact rules of line-breaking? When does SWI Prolog break the lines and when does it not? What does this depend on?
All bindings (Var = Value) appear on their own line, except when two or more variables are bound to the same value. In that case it uses the following syntax on a single line.
V1 = V2, V2 = V3, ..., Vn-1 = Vn, Vn = value.
It does this because it is valuable to know two variables have the same value. The answer in SWI-Prolog is printed as a valid Prolog program. There are no further promises and the layout, ordering, etc. may change without notice between versions. If you want a machine to read results, do not use the toplevel.

Prolog Array Pipe Meaning

Can anybody explain the following code? I know it returns true if X is left of Y but I do not understand the stuff with the pipe, underscore and R. Does it mean all other elements of the array except X and Y?
left(X,Y,[X,Y|_]).
left(X,Y,[_|R]) :- left(X,Y,R).
If you are ever unsure about what a term "actually" denotes, you can use write_canonical/1 to obtain its canonical representation.
For example:
| ?- write_canonical([X,Y|_]).
'.'(_16,'.'(_17,_18))
and also:
| ?- write_canonical([a,b|c]).
'.'(a,'.'(b,c))
and in particular:
| ?- write_canonical([a|b]).
'.'(a,b)
This shows you that [a|b] is the term '.'(a,b), i.e., a term with functor . and two arguments.
To reinforce this point:
| ?- [a|b] == '.'(a,b).
yes
#mat answered the original question posted quite precisely and completely. However, it seems you have a bigger question, asked in the comment, about "What does the predicate definition mean?"
Your predicate, left(X, Y, L), defines a relation between two values, X and Y, and a list, L. This predicate is true (a query succeeds) if X is immediately left of Y in the list L.
There are two ways this can be true. One is that the first two elements in the list are X and Y. Thus, your first clause reads:
left(X, Y, [X,Y|_]).
This says that X is immediately left of Y in the list [X,Y|_]. Note that we do not care what the tail of the list is, as it's irrelevant in this case, so we use _. You could use R here (or any other variable name) and write it as left(X, Y, [X,Y|R]). and it would function properly. However, you would get a singleton variable warning because you used R only once without any other references to it. The warning appears since, in some cases, this might mean you have done this by mistake. Also note that [X,Y|_] is a list of at least two elements, so you can't just leave out _ and write [X,Y] which is a list of exactly two elements.
The above clause is not the only case for X to be immediately left of Y in the list. What if they are not the first two elements in the list? You can include another rule which says that X is immediately left of Y in a list if X is immediately left of Y in the tail of the list. This, along with the base case above, will cover all the possibilities and gives a complete recursive definition of left/3:
left(X, Y, [_|R]) :- left(X, Y, R).
Here, the list is [_|R] and the tail of the list is R.
This is about the pattern matching and about the execution mechanism of Prolog, which is built around the pattern matching.
Consider this:
1 ?- [user].
|: prove(T):- T = left(X,Y,[X,Y|_]).
|: prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ).
|:
|: ^Z
true.
Here prove/1 emulates the Prolog workings proving a query T about your left/3 predicate.
A query is proven by matching it against a head of a rule, and proving that rule's body under the resulting substitution.
An empty body is considered proven right away, naturally.
prove(T):- T = left(X,Y,[X,Y|_]). encodes, "match the first rule's head. There's no body, so if the matching has succeeded, we're done."
prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ). encodes, "match the second rule's head, and if successful, prove its body under the resulting substitution (which is implicit)".
Prolog's unification, =, performs the pattern matching whilst instantiating any logical variables found inside the terms being matched, according to what's being matched.
Thus we observe,
2 ?- prove( left( a,b,[x,a,b,c])).
true ;
false.
3 ?- prove( left( a,b,[x,a,j,b,c])).
false.
4 ?- prove( left( a,b,[x,a,b,a,b,c])).
true ;
true ;
false.
5 ?- prove( left( a,B,[x,a,b,a,b,c])).
B = b ;
B = b ;
false.
6 ?- prove( left( b,C,[x,a,b,a,b,c])).
C = a ;
C = c ;
false.
The ; is the key that we press to request the next solution from Prolog (while the Prolog pauses, awaiting our command).

Nested pairs using operator hyphen

I want to represent edges as pairs using the hyphen operator, i.e., From-To.
I want to represent nodes as pairs as well (denoting FCA concepts), i.e., Extent-Intent.
So I get something like the following:
([1]-[a])-([2,3]-[b])
The brackets make sure the expression is properly disambiguated: the single outer hyphen denotes the edge operator, the two inner hyphens denote the node operator.
Here is my problem:
?- X = (a-b)-(c-d), X = Y1-Y2-Y3.
X = a-b- (c-d),
Y1 = a,
Y2 = b,
Y3 = c-d
I was expecting this to fail instead...
My questions:
Why are the brackets removed in the (displayed) binding of X?
Why is the first hyphen interpreted in a different way than the third one?
Possibly relevant, precedence rules for the hyphen operator:
?- current_op(P,T,-).
P = 200,
T = fy ;
P = 500,
T = yfx.
(This is in SWI-Prolog developer branch, but I doubt this will be SWI-specific.)
Usually, write_canonical is very useful in understanding how Prolog interprets operators.
?- write_canonical(a-b-c).
-(-(a,b),c)
true.
?- write_canonical(a-(b-c)).
-(a,-(b,c))
true.
?- write_canonical(a-b-c-d).
-(-(-(a,b),c),d)
true.
?- write_canonical(a-b-(c-d)).
-(-(a,b),-(c,d))
true.
And then, this sort of makes sense, assuming that all hyphens here are binary operators with the right hand argument having the strictly lower precedence:
?- X = (a-b)-(c-d), X = Y1-(Y2-Y3).
X = a-b- (c-d),
Y1 = a-b,
Y2 = c,
Y3 = d.
?- X = (a-b)-(c-d), X = (Y1-Y2)-Y3.
X = a-b- (c-d),
Y1 = a,
Y2 = b,
Y3 = c-d.
The first brackets are not strictly necessary to display the nested term -(-(a,b),-(c,d)). The second pair of brackets is necessary, otherwise it would mean -(-(-(a,b),c),d).
PS. Since I am not good enough to always keep operator precedence rules in my head, I try to avoid operators. There is nothing wrong with explicit functors. The hyphen of course is very useful for predicates like keysort/2 and libraries like library(ugraphs).

Unification in Prolog

This is a question from a past exam about unification in Prolog.
we were supposed to say if they unified and then the instantiations.
f(a,g(b,a)) and f(X,g(Y,X))
This unifies quite a = X, g(b,a) = g(Y,X) and is quite straight forward
f(g(Y),h(c,d)) and f(X,h(W,d))
I dont think this one unifies because of g(Y) =/ X, though h(c,d) does unify with h(W,d). Though is it possible that X = g(Y) since uppercase X looks until it finds a solution?
Yes, it does unify, and it does so because g(Y) is a term to be evaluated, as well as a -- in the first example you pointed.
You can check the evaluation in a prolog interpreter:
?- f(g(Y),h(c,d)) = f(X,h(W,d)).
X = g(Y),
W = c.
The unification process works in a depth-first fashion, unifying members and returning each of the available answer, until no further combination is possible.
This means the unification method is called for f(g(Y),h(c,d)) = f(X,h(W,d)), that finds out the available matchings: g(Y) = X, h(c, d) = h(W, d).
Then, the unification is performed upon g(Y) = X, that, since there's no further possible reduction, returns X = g(Y).
Then, the same method is called upon the matching h(c, d) = h(W, d), which gives you c = W, and no other matching, resulting, thus, in W = c.
The answers, after unification, are returned, and it's usually returned false to point when no matching/further matching is possible.
As pointed by CapelliC, the variable Y, after the unification process, is still unbound. The unification is performed upon unbound variables, which means:
the unification of h(c, d) = h(W, d) returns h(_) = h(_), and this allows the unification to continue, since h is a term, and not an unbound var;
the unification of d = d is a matching of terms, and does not form an attribution -- or binding;
the unification of c = W forms an attribution, and the variable W is bound to the term c, since it was not bound before -- a comparison would be performed otherwise;
the unification of X = g(Y) simply binds the unbound variable X to the term g(Y), and g(Y) is a term with an unbound variable, since there's no available unification to g(Y).
Regards!

Categorise List in Prolog

Alright so I am coding a parser for arithmetic equations. I get the input in a list, e.g. "10+20" = [49,48,43,50,48] and then I convert all the digits to there corresponding numbers e.g. [49,48,43,50,48] = [1,0,43,2,0] and from there I want to put integers > 10 back together.
Converting from ascii -> digits I use a maplist and number_codes to convert.
One approach I had was to just traverse the list and if it's 0-9 store it in a variable and then check the next number, 0-9 append it to the other variable and so on until I hit an operator. I can't seem to simply append digits as it were. Here's my current code.
expression(L) :-
maplist(chars, L, Ls).
chars(C, N) :-
(
C >= "0", "9" >= C -> number_codes(N, [C]);
N is C
).
Not sure if there's a simple way to add to my code (as far as I know, maplist only gives back a list of equal length to the list passed in but I could be mistaken).
Any help is appreciated :)
Yes, maplist only 'gives back' a list of equal length. Moreover, maplist applies a predicate only to one element (basically it's context-free). Therefore, it is not possible to do what you want (combine digits between operators to a single number) with maplist and you would have to write the recursion yourself.
However, you can do something way easier than all this converting back and forth:
expression(L, E):-
string_to_atom(L,A),
atom_to_term(A,E,[]).
Which works like this:
2 ?- expression("1+2",E).
E = 1+2.
3 ?- expression("1+2",E), X is E.
E = 1+2, X = 3.
4 ?- expression("1+2",E), X+Y = E.
E = 1+2, X = 1, Y = 2.
5 ?- expression("1+2+3",E), X+Y = E.
E = 1+2+3, X = 1+2, Y = 3.
Naturally, if you want a list with all the numbers involved you will have to do something recursive but this is kinda trivial imho.
If however you still want to do the converting, I suggest checking Definite Clause Grammars; it will simplify the task a lot.
I answered some time ago with an expression parser.
It will show you how to use DCG for practical tasks, and I hope you will appreciate the generality and simplicity of such approach.
Just a library predicate is required from SWI-Prolog, number//1, easily implemented in Sicstus. Let me know if you need more help on that.

Resources