prolog how to evaluate math expressions - prolog

I am studying for an exam and I am having trouble with the prolog section and this question in my book. I would like to create a predicate 'evaluate' that when given any expression sets the value to R. IE: A=4,B=5, evaluate(((A*B)-2)/3,R) it evaluates to R = 400. How would I go about creating this?

As #Dmitri Chubarov suggested you could use is/2:
evaluate(X,R):- R is X.
The above simply says R is the arithmetic result of X, so is/2 make all arithmetic operations and returns the arithmetic result.
Example:
?- A=4,B=5, evaluate(((A*B)-2)/3,R).
A = 4,
B = 5,
R = 6.

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.

Difference between `is` and `=`?

I have defined these two plus predicates:
plus1(A, B, C):- C is A + B.
plus2(A, B, C):- C = A + B.
As expected, plus1(4, 5, X) gives the result X = 9.
But plus2(4, 5, X) gives the result X = 4+5, which is not wrong, but I had expected the result 9.
So why does it not perform any calculation, what is the difference between is and =, and when should I use what?
I didn't want to leave this question without an answer.
As Willem Van Onsem has commented, is is for evaluates the numerical expressions while = is for unification.
I also found this article about unification for future readers with the same question.

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?

Building a base 2 exponent calculator in Prolog

log2(I,E):-
I is 2.0**E,
E is log(I)/log(2).
I am trying to use Prolog to compute either the power 2 was raised to 'I' or 2 raised to the 'E' power equals 'I'. I am extremely new to this language and from my understanding it infers the answer based on the information provided.
Queries:
log2(I,3).
-->false.
log2(I,3.0).
-->I = 8.0.
log2(8,E).
-->ERROR: is/2: Arguments are not sufficiently instantiated
log2(8,E).
-->ERROR: is/2: Arguments are not sufficiently instantiated
I'm confused why I have to provide a float in the first circumstance to get the correct answer and why Prolog is unable to infer the answer from the second circumstance at all.
What you have there is a conjunction. In Prolog, a conjunction a, b means:
Evaluate a, and if it succeeds, evaluate b.
You are trying to do something else, maybe:
Try a, and if it doesn't succeed, try b.
The first thing you should consider is using library(clpr), if it is available in your Prolog implementation.
With SWI-Prolog:
?- use_module(library(clpr)).
true.
?- {I = 2^3}.
I = 8.0 ;
false.
?- {8 = 2^E}.
E = 3.0 ;
false.
You literally have no problem any more.
If this is not an option, you need to do something along these lines:
log2(I, E) :-
( number(I)
-> E is /* expression here, now that I is a number */
; number(E)
-> I is /* expression here, now that E is a number */
; /* what do you do if both are variables? */
).
Note that X is Expr will work even if Expr is an expression and not a number. If you want to allow this, then you need to maybe try eval(Expr) first and catch the error or something along these lines.

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