Using 'or' in Prolog - prolog

For some reason, these two pieces of code aren't equivalent, with the first producing very strange (and incorrect results).
-- Method 1
highestElement1([],A,A).
highestElement1([H|T],A,Max) :-
H > A,
highestElement1(T,H,Max);
highestElement1(T,A,Max).
-- Method 2
highestElement2([],A,A).
highestElement2([H|T],A,Max) :-
H > A,
highestElement2(T,H,Max).
highestElement2([H|T],A,Max) :-
H =< A,
highestElement2(T,A,Max).
From my understanding, they should be identical, as I believe(d) that pattern matching and 'or' are basically syntatic sugar for one another. Is this not the case?

Method1 is actually equivalent to:
highestElement2([],A,A).
highestElement2([H|T],A,Max) :-
H > A,
highestElement2(T,H,Max).
highestElement2([H|T],A,Max) :-
highestElement2(T,A,Max).
This is due to the relative priorities of the (,)/2 and (;)/2 operators:
| ?- current_op(Priority, Type, ',').
Priority = 1000
Type = xfy
yes
| ?- current_op(Priority, Type, ';').
Priority = 1100
Type = xfy
yes
I.e. the second clause of highestElement1 is parsed as:
highestElement1([H|T],A,Max) :-
(H > A, highestElement1(T,H,Max))
;
highestElement1(T,A,Max).
One way to visualize how a term is parsed if we're not sure about operator notation is to use the standard write_canonical/1 built-in predicate:
| ?- write_canonical((a :- b,c; d)).
:-(a,;(','(b,c),d))
(1 ms) yes
The output tells us that we have a compound term with name :- and two arguments, a and ;(','(b,c),d). The second argument is also a compound term with name ; and two arguments, ','(b,c) and d.

Related

What exactly is the vertical slash function in PROLOG? Is it an operator?

I was studying the PROLOG programming language, testing some examples and reading documentations. I started then to do heavy research about lists in PROLOG. The idea is: Head and Tail. I then learned that lists can be expressed in PROLOG like this:
[Head | Tail]
The syntax is pretty simple, square brackets with a head and a tail, separated by a vertical slash |. I then asked myself what is the meaning (the semantics) of the vertical slash | in PROLOG. As I said, I had done research concerning lists and the vertical slash as well, but I was not able to find something helpful about the it.
So this is why I am a little bit confused. I suppose it is indeed a special character, but why does it necessarily have to be a vertical slash? Is it an operator? Is it used for system or language (meta) applications? What is its specific function in the language?
Yes, | is a right-associative infix operator of precedence 1105, right-associative meaning that an expression like
a|b|c|d
binds as
'|'( a , '|'( b , '|'( c , d ) ) )
rather than the left-associative binding
'|'( '|'( '|'( a , b ) , c ) , d )
It is part of Prolog's syntactic sugar for list notation. In Prolog, any non-empty list, has a single item that is denoted as its head, and the remainder of the list, itself another list (which may be empty), denoted as the tail. (A rather nice recursive definition, eh?)
So one can easily partition a list into its head and tail using |. So
[Head|Tail] = [a,b,c,d]
results in
Head = a
Tail = [b,c,d]
From my answer here,
Prolog's list notation is syntactic sugar on top of very simple prolog terms. Prolog lists are denoted thus:
The empty list is represented by the atom []. Why? Because that looks like the mathematical notation for an empty list. They could have used an atom like nil to denote the empty list but they didn't.
A non-empty list is represented by the term .\2, where the first (leftmost) argument is the head of the list and the second (rightmost) argument is the tail of the list, which is, recursively, itself a list.
Some examples:
An empty list: [] is represented as the atom it is:
[]
A list of one element, [a] is internally stored as
.(a,[])
A list of two elements [a,b] is internally stored as
.(a,.(b,[]))
A list of three elements, [a,b,c] is internally stored as
.(a,.(b,.(c,[])))
Examination of the head of the list is likewise syntactic sugar over the same ./2 notation:
[X|Xs] is identical to .(X,Xs)
[A,B|Xs] is identical to .(A,.(B,Xs))
[A,B] is (see above) identical to .(A,.(B,[]))
There seems to be a bit of confusion b/w the usage of vertical bar | generally used in list pattern matching and the |/2 operator.
I am not familiar with other prologs so this might be swi-prolog specific. Help for '|' states the following:
help('|').
:Goal1 | :Goal2
Equivalent to ;/2. Retained for compatibility only. New code should use ;/2.
So, the | used in list notation is not this operator.
?- X = '[|]'(1, []).
X = [1].
?- X = '|'(1, []).
X = (1| []).
?- [1] = '|'(1, []).
false.
?- [1] = '[|]'(1, []).
true.
As seen above using just | only creates a compound term and not a list.
Following uses Univ =.. and makes it more clear.
?- X = '[|]'(a, '[|]'(b, [])).
X = [a, b].
?- [a, b, c] =.. X.
X = ['[|]', a, [b, c]].
?- deep_univ([a, b, c, d], X).
X = ['[|]', a, ['[|]', b, ['[|]', c, ['[|]', d, []]]]].
I have used deep_univ/2 from here

Prolog does not evalutate parenthesis

I am trying to make an expression simplifier in Prolog, but one part has me stuck.
What I want to happen is simplify(x*(4*x),R). evalutes to simplify(x*4*x,R). then the rest will work its magic. But I can't seem to remove the parens. Here is the evaluation code below
simplify(x,x).
simplify(C*x,C*x) :- atomic(C),number(C),C\==1,C\==0.
simplify(x*C*x,W):- atomic(C),number(C), simplify(C*x^2,W).
simplify(C*x^N,C*W) :- atomic(C),number(C),atomic(N),number(N), simplify(x^N,W).
simplify(x^1,x).
simplify(x^N,x^N) :- atomic(N),number(N),N \== 1.
simplify(U*(V),R2):- simplify(U,U1),simplify(V,V1),simplify(U1*V1,R2).%why will it not return a paren less output
simplify(U*V,R2):- simplify(U,U1),simplify(V,V1),simplify(U1*V1,R2).
Parenthesis are used to change a term interpretation in the presence of operators. Note that, for the Prolog parser, there's no distinction between simplify(U*(V),R2) and simplify(U*V,R2):
| ?- write_canonical(simplify(U*(V),R2)).
simplify(*(_279,_280),_284)
yes
| ?- write_canonical(simplify(U*V,R2)).
simplify(*(_279,_280),_284)
yes
Thus, the last two clauses have the same head; there's a single operator in the U*(V) term.
Now consider the goal simplify(x*(4*x),R). The operator definition for (*)/2 is:
| ?- current_op(Priority, Type, *).
Priority = 400
Type = yfx
yes
I.e. the operator is left-associative. This means that e.g. a*b*c is parsed as *(*(a,b),c). Therefore:
| ?- write_canonical(simplify(x*(4*x),R)).
simplify(*(x,*(4,x)),_285)
yes
| ?- write_canonical(simplify(x*4*x,R)).
simplify(*(*(x,4),x),_285)
yes

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).

Prolog converting text to number and doing arithmatic operations

I working in prolog for first time.
I am trying to convert operations in text.
Such as,
THREE + THREE = SIX
should return true.
I tried this.
I am getting error on last line and when I try add(ONE,ONE,TWO) it returns false instead of true.
numericValue(ONE, 1).
numericValue(TWO, 2).
numericValue(THREE, 3).
numericValue(FOUR, 4).
numericValue(FIVE, 5).
numericValue(SIX, 6).
numericValue(SEVEN, 7).
numericValue(EIGHT, 8).
numericValue(ZERO, 0).
numericValue(NINE, 9).
add(num1,num2,num3):-
numericValue(num1,a),
numericValue(num2,b),
numericValue(num3,c),
(c =:= a+b -> true ; false).
istBiggerThen(XinEng,YinEng) :-
numericValue(XinEng, X),
numericValue(YinEng, Y),
( X < Y -> true ; false).
A + B = C :- add(A,B,C).
Error on last line is
ERROR: /home/name/prolog_examples/crypt.pl:24:
No permission to modify static procedure `(=)/2'
literals (lower-case) vs. Variabls (upper-case):
as #lurker pointed out, you have your atoms and variables mixed up. So your facts should look something like this:
text_to_number(one, 1).
text_to_number(two, 2).
text_to_number(three, 3).
%% etc...
while your rules will need to use variables, like so:
add(A_Text, B_Text, C_Text) :-
text_to_number(A_Text, A_Num),
text_to_number(B_Text, B_Num),
C_Num is A_Num + B_Num,
text_to_number(C_Text, C_Num).
bigger_than(A_Text, B_Text) :-
text_to_number(A_Text, A_Num),
text_to_number(B_Text, B_Num),
A_Num > B_Num.
The reason reason why add(ONE, ONE, TWO) turns out false is because your original rule for add/3 only defines relationships between the atoms num1, num2, num3, a, b, c. When you query add(ONE, ONE, TWO) Prolog tries to unify the variables with the atoms in the head of your rule, which is add(num1, num2, num3). Because you have ONE as the first and second argument of your query, this unification is impossible, since ONE = ONE but num1 \= num2. As there are no further rules or facts for add/3, the query simply returns false.
Using the pattern (|Condition| -> true ; false):
Statements in the body of a clause (i.e., to the right of the :- operator) is evaluated to be either true or false, so you will almost never need to use the pattern (|Condition| -> true ; false). E.g. C_Num is A_Num + B_Num is true iff C_Num can be unified with the sum of A_Num and B_Num, or else it is false, in which case Prolog will start back tracking.
Using =:=/2 vs. is/2:
=:=/2 checks for the equality of its first argument with the value of its second argument, which can be an arithmetical expression that can be evaluated using is/2. Query ?- X =:= 2 + 2 and you'll get an instantiation error, because =:=/2 cannot compare a free variable to a mathematical expression. is/2, on the other hand, unifies the variable on the left with the value of the expression on the right: ?- X is 2 + 2. X = 4.
Your use of =:=/2 would work (provided you straightened out the variable-atom thing), but your rule describes an inefficient and roundabout solution for the following reason: since numericValue(Num3,C) precedes evaluation of the arithmetic, Prolog will first unify numericValue(Num3,C) with the first fitting fact, viz. numericValue(one, 1) then test if 1 =:= A + B. When this fails, Prolog will unify with the next fact numericValue(two, 2) then test if 2 =:= A + B, then the next... until it finally happens upon the right value. Compare with my suggested rule: the numeric values A_Num and B_Num are summed with C_Num is A_Num + B_Num, unifying C_Num with the sum. Then Prolog unifies text_to_number(C_Text, C_Num) with the single fitting fact that has the appropriate value for C_Num.
Defining operators:
When a term appears on the right of a :-, or on the top level of the program, is being defined. However, you cannot simply redefine predicates (it can be done, but requires some bookkeeping and special declarations. Cf., dynamic/1). Moreover, you wouldn't want to redefine core terms like +/2 and =/2. But you can define your own predicates with relative ease. In fact, going crazy with predicate definitions is one of my favorite idle things to do with Prolog (though I've read cautions against using unnecessary operators in practice, since it makes your code recondite).
Operators are declared using op/3 in a directive. It has the signature op(+Precedence, +Type, :Name) (Cf., the SWI-Prolog documentation):
:- op(200, xfx, user:(++)).
:- op(300, yfx, user:(=::=)).
A ++ B =::= C :- add(A, B, C).
In action:
?- one ++ two =::= X.
X = three.

SWI-Prolog. Check correctness of mathematical expression

I try to check the correctness of student mathematical expression using Prolog (SWI-Prolog). So, for example if the student were asked to add three variable x, y, and z, and there's a rule that the first two variable that must be added are: x and y (in any order), and the last variable that must be added is z then I expect that prolog can give me true value if the student's answer is any of these:
x+y+z
(x+y)+ z
z+(x+y)
z+x+y
y+x+z
and many other possibilities.
I use the following rule for this checking:
addData :-
assert(variable(v1)),
assert(variable(v2)),
assert(variable(v3)),
assert(varName(v1,x)),
assert(varName(v2,y)),
assert(varName(v3,z)),
assert(varExpr(v1,x)),
assert(varExpr(v2,y)),
assert(varExpr(v3,z)).
add(A,B,R) :- R = A + B.
removeAll :- retractall(variable(X)),
retractall(varName(X,_)),
retractall(varExpr(X,_)).
checkExpr :-
% The first two variable must be x and y, in any combination
( (varExpr(v1,AExpr), varExpr(v2,BExpr));
(varExpr(v2,AExpr), varExpr(v1,BExpr))
),
add(AExpr, BExpr, R1),
% store the expression result as another variable, say v4
retractall(variable(v4)),
retractall(varName(v4, _)),
retractall(varExpr(v4, _)),
assert(variable(v4)),
assert(varName(v4, result)),
assert(varExpr(v4, R1)),
% add the result from prev addition with Z (in any combination)
( (varExpr(v3,CExpr), varExpr(v4,DExpr));
(varExpr(v4,CExpr), varExpr(v3,DExpr))
),
add(CExpr, DExpr, R2),
R2 = z + x + y. % will give me false
% R2 = z + (x + y). % will give me true
% Expected: both should give me true
checkCorrect :- removeAll,
addData,
checkExpr.
You should try to specify a grammar and write a parser for your expressions.
Avoid assert/retract, that make the program much more difficult to understand, and attempt instead to master the declarative model of Prolog.
Expressions are recursive data structures, using operators with known precedence and associativity to compose, and parenthesis to change specified precedence where required.
See this answer for a parser and evaluator, that accepts input from text. In your question you show expressions from code. Then you are using Prolog' parser to do the dirty work, and can simply express your requirements on the resulting syntax tree:
expression(A + B) :-
expression(A),
expression(B).
expression(A * B) :-
expression(A),
expression(B).
expression(V) :-
memberchk(V, [x,y,z]).
?- expression(x+y+(x+z*y)).
true .
edit: we can provide a template of what we want and let Prolog work out the details by means of unification:
% enumerate acceptable expressions
checkExpr(E) :-
member(E, [F = A + D, F = D + A]),
F = f,
A = c * N,
N = 1.8,
D = d.
And so on...
Test:
?- checkExpr(f=(c*1.8)+d).
true.
?- checkExpr(f=(c*1.8)+e).
false.
?- checkExpr(f=d+c*1.8).
true.

Resources