Search code examples
prologlogarithm

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.


Solution

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