Crinkley Crewms
Crinkley Crewms

Reputation: 123

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.

Upvotes: 1

Views: 680

Answers (1)

user1812457
user1812457

Reputation:

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.

Upvotes: 3

Related Questions