Search code examples
prologexponentiation

SWI-Prolog evaluate -1 raised to a fraction, can this be done


In evaluating math expressions with SWI-Prolog I need to evaluate -1 raised to an exponential. When the exponential is an integer the result is as expected but when the exponential is a non-integer the result is undefined.

Is it possible to evaluate a -1 to a non-integer with SWI-Prolog?

e.g. (-1)^0.5

A preferred answer should not take more then several lines to accomplish. The use of a package is acceptable. The use of calling into another language would be acceptable but less preferred.

Supplement

With SWI-Prolog when using either ^/2 or **/2 with a base of -1 and a fraction as the exponent results in undefined

?- V is **(-1.0,-0.5).
ERROR: Arithmetic: evaluation error: `undefined'
ERROR: In:
ERROR:    [8] _3688 is -1.0** -0.5
ERROR:    [7] <user>

?- V is **(-1.0,0.5).
ERROR: Arithmetic: evaluation error: `undefined'
ERROR: In:
ERROR:    [8] _43410 is -1.0**0.5
ERROR:    [7] <user>

?- V is ^(-1.0,-0.5).
ERROR: Arithmetic: evaluation error: `undefined'
ERROR: In:
ERROR:    [8] _6100 is -1.0^ -0.5
ERROR:    [7] <user>

?- V is ^(-1.0,0.5).
ERROR: Arithmetic: evaluation error: `undefined'
ERROR: In:
ERROR:    [8] _7294 is -1.0^0.5
ERROR:    [7] <user>

However when using either ^/2 or **/2 with a base of -1 and an integer as the exponent results in a valid value.

?- V is ^(-1.0,-3.0).
V = -1.0.

?- V is ^(-1.0,-2.0).
V = 1.0.

?- V is ^(-1.0,-1.0).
V = -1.0.

?- V is ^(-1.0,0.0).
V = 1.0.

?- V is ^(-1.0,1.0).
V = -1.0.

?- V is ^(-1.0,2.0).
V = 1.0.

?- V is ^(-1.0,3.0).
V = -1.0.

?- V is **(-1.0,-3.0).
V = -1.0.

?- V is **(-1.0,-2.0).
V = 1.0.

?- V is **(-1.0,-1.0).
V = -1.0.

?- V is **(-1.0,0.0).
V = 1.0.

?- V is **(-1.0,1.0).
V = -1.0.

?- V is **(-1.0,2.0).
V = 1.0.

?- V is **(-1.0,3.0).
V = -1.0.

I am aware that SWI-Prolog math is based on GNU multiple precision arithmetic library (GMP), which as noted on Wikipedia does not support complex numbers.

I am also aware that a plot of -1^X is a continuous function of both real and imaginary parts. Currently I am only interested in the real part.


Solution

  • Noticing that the plot of (-1)^x is a periodic function similar to cos function with a frequency shift, start with

    cos((10 * x) / pi)
    

    To adjust the frequency of the function, plot the function with a translation on the X-axis by 10 then adjust the cos function to match, e.g.

    cos((9.9 * x) / pi)
    

    Then keep translating further out and adjusting. After a few iterations of adjusting this function is close to what is needed even for x of 10,000.

    cos((9.8696 * x) / pi)
    
    ?- V is cos((9.8696*(10000.0))/pi).
    V = 0.9999018741279994.
    

    Supplement

    To make the adjustments easier to do, the functions were plotted using Wolfram Alpha. Note that due to differences between SWI-Prolog and Wolfram Alpha, the adjustment factors are slightly different. For Wolfram Alpha the factor is 9.86955 while with SWI-Prolog it is 9.8696