Prolog, using expressions - prolog

I'm trying to learn SWI prolog,
but my simple program fails when I believe it should succeed.
%My code:
orthogonal((X1,Y1,Z1),(X2,Y2,Z2)) :- (X1*X2)+(Y1*Y2)+(Z1*Z2)==0.
integerVector((X,Y,Z)) :- integer(X),integer(Y),integer(Z).
?-orthogonal((1,0,0),(0,0,1)).
I press compile Buffer in the pseudoemacs window and the output is:
% [PATH].pl compiled 0.00 sec, 136 bytes
ERROR: emacs_prolog_mode ->error_at_location: Argument 1 (int): `int' expected, found `#11470948?start'
ERROR: emacs_prolog_mode ->error_at_location: Argument 1 (int): `int' expected, found `#11470948?start'
Warning: [PATH]s.pl:5:
Goal (directive) failed: user:orthogonal((1,0,0), (0,0,1))

You have used (==)/2 in place of (=:=)/2 which evaluates its arguments as arithmetic expressions.
You can use (X,Y,Z), but it isn't a triple as in e.g. Haskell. To see this:
?- write_canonical((1,2,3)).
','(1,','(2,3))
?- (1,2,3) = (X,Y).
X = 1, Y = (2,3).

Expressions in Prolog simply represent syntactic term trees. To evaluate an expression you need to X is Y which evaluates Y as an arithmetic expression and unifies the result with X. Alternatively you can use X =:= Y which evaluates both X and Y as arithmetic expressions, then unifies the results.
Cheers!

Related

Prolog: what is difference between, for example, X is 3 and 3 is X?

three(X) :- 3 is X.
three2(X) :- X is 3.
Requests three(3), three(5) and three2(3), three2(5) respectively have the same answers.
But three2(X) has answer 3, while three(X) has answer "Arguments are not sufficiently instantiated".
If there's enough data to solve that three(3) is true and three(5) is false, why there's not enough data to find that X is equals 3 when we request for the value of X?
That's because is/2 is the numeric expression evaluator of Prolog. Everything on the Right Hand Side of is/2 must be fully instantiated so that the expression can then be evaluated to a number (possibility missed: evaluate to something else than numbers). The result is then unified with the Left Hand Side of is/2. This succeeds if the LHS is an unbound variable or the same as the result obtained.
In your case, you can make the predicate three/1 symmetric by just unifying, as there is really nothing to evaluate:
three_sym(X) :- 3 = X.
Succeeds with 3 and outputs the answer X = 3 for an unbound X.

Prolog Error: Out of Local Stack in factorial

I'm trying to make a factorial code in prolog but am getting error of out of local stack, that is, it is stuck in infinite loop. I can't understand how.
Here is my code:
fact(0,1).
fact(1,1).
fact(X,Y):- X\==0, A=X-1, fact(A,Z), Y=X*Z.
Where am I going wrong?
It is the A=X-1, and later the Y=X*Z. The great thing about the Prolog top level is that you can easily try out what your code does:
?- A = X-1.
A = X-1.
?- A = 5-1.
A = 5-1.
Apparently, Prolog is mocking us :). The = operator is used for unification; if you want to do arithmetic, you must use is/2:
?- is(A, -(5, 1)).
A = 4.
usually written as:
?- A is 5-1.
A = 4.
This just to show you that an expression is a term, and is evaluates the term in its second argument:
?- Expr = X-1, X = 3, Result is Expr.
Expr = 3-1,
X = 3,
Result = 2.
To your definition for factorial: it should work if you fix the arithmetic. Note that it would be cleaner if the condition for X at the beginning says X > 1 instead of X \== 0: what does your current program do for fact(1,F), and how many answers do you get?

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.

What does the bitwise negation operator(\) do in prolog?

I have to implement some functions, one of which is f= ~p/\~q.
I have the following :
p(a). p(b).
q(a). q(b). q(c).
I found the function as:
f(X):-p(\X);q(\X).
When I verify it ( f(X). , f(a). , f(b). , f(c). ) it always returns false.
Shouldn't it return true for c since c is not of type p?
Thank you!
(\)/1 is an evaluable functor for bitwise complement. If you use it directly in an argument, it is only an uninterpreted functor. Evaluation is only performed with (is)/2, (>)/2 and other comparison operators.
In all current Prolog implementations you get:
?- X is \ 1.
X = -2.
Fine print: An ISO conforming system is free to define the value for \. That is, it is free, whether it uses 2's complement or another representation. However, there are only systems that use 2's complement.
Your implementation of that formula seems flawed.
You are required about f : (not p) and (not q)
A restricted negation is available in Prolog, using operator (\+)/1, and conjunction (X and Y) is expressed by comma i.e. (,)/2.
Semicolon i.e. (;)/2 means or, as for instance in the following test, that shows your initial assumption about f(c) is also wrong.
?- forall(member(X,[a,b,c,d]),(f(X)->writeln(y);writeln(n))).
n
n
n
y
(of course, after f/1 has been translated correctly)

Prolog Functor - Computing x^y

I am new to prolog and trying out to learn how to program. I want to know how to compute x^y in Prolog both being integers.
I know for a fact that it goes something like this:
% exp(y,x,z) <- z is x**y
Try this:
?- [user].
exp(X,Y,Z) :- Z is round(X**Y).
Yes
?- exp(3,4,R).
R = 81
Difference to your solution:
1) The (:-)/2 operator is usually used in Prolog to define rules and not the (->)/2 operator.
2) (* * )/2 yields a float. There are a couple of possibilties to convert a float to
a integer. Besides floor/1 and truncate/1, the round/1 function probably works best
here sind the result of (**)/2 might not be precise.
Bye
P.S.: There is a proposal for a native integer power function, it would use the operator
(^)/2. For more information see:
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#pow
The native power function might yield better results where the above implementation might run into an overflow or imprecise results. Here is an example with different results (SWI Prolog 5.11.33):
?- X is round(123.0**45.0).
X = 11110408185131957010659080963921001637101840276079092263812695592440203675146350059871151325184.
?- X is 123^45.
X = 11110408185131956285910790587176451918559153212268021823629073199866111001242743283966127048043.

Resources