prolognumbersclpfdnumber-theorylogical-purity

Prolog program to get an (integer) number as the sum of two integer squares, why does it not work?


I'm starting learning Prolog and I want a program that given a integer P gives to integers A and B such that P = A² + B². If there aren't values of A and B that satisfy this equation, false should be returned

For example: if P = 5, it should give A = 1 and B = 2 (or A = 2 and B = 1) because 1² + 2² = 5.

I was thinking this should work:

giveSum(P, A, B) :- integer(A), integer(B), integer(P), P is A*A + B*B.

with the query:

giveSum(5, A, B).

However, it does not. What should I do? I'm very new to Prolog so I'm still making lot of mistakes.

Thanks in advance!


Solution

  • integer/1 is a non-monotonic predicate. It is not a relation that allows the reasoning you expect to apply in this case. To exemplify this:

    ?- integer(I).
    false.
    

    No integer exists, yes? Colour me surprised, to say the least!

    Instead of such non-relational constructs, use your Prolog system's CLP(FD) constraints to reason about integers.

    For example:

    ?- 5 #= A*A + B*B.
    A in -2..-1\/1..2,
    A^2#=_G1025,
    _G1025 in 1..4,
    _G1025+_G1052#=5,
    _G1052 in 1..4,
    B^2#=_G406,
    B in -2..-1\/1..2
    

    And for concrete solutions:

    ?- 5 #= A*A + B*B, label([A,B]).
    A = -2,
    B = -1 ;
    A = -2,
    B = 1 ;
    A = -1,
    B = -2 ;
    etc.
    

    CLP(FD) constraints are completely pure relations that can be used in the way you expect. See for more information.

    Other things I noticed: