Search code examples
matherror-handlingcompiler-errorsprologinstantiation-error

Why this Goldbach's conjecture program does not work in Prolog?


Why does this program does not work in Prolog ?

%  Goldbach's conjecture. 
% Goldbach's conjecture says that every positive even number greater 
% than 2 is the sum of two prime numbers. Example: 28 = 5 + 23.

:- ensure_loaded(p31).

% goldbach(N,L) :- L is the list of the two prime numbers that
%    sum up to the given N (which must be even).
%    (integer,integer) (+,-)

goldbach(4,[2,2]) :- !.
goldbach(N,L) :- N mod 2 =:= 0, N > 4, goldbach(N,L,3).

goldbach(N,[P,Q],P) :- Q is N - P, is_prime(Q), !.
goldbach(N,L,P) :- P < N, next_prime(P,P1), goldbach(N,L,P1).

next_prime(P,P1) :- P1 is P + 2, is_prime(P1), !.
next_prime(P,P1) :- P2 is P + 2, next_prime(P2,P1).

First off, I had to remove the code line :- ensure_loaded(p31). Otherwise marked an error saying that does not exist.

Second, when I run it on SWI-Prolog screen with ?-goldbach(4,X,Y). marked an error that says:

ERROR: Arguments are not sufficiently instantiated

Why?

Could someone please help me to fix the program?

Thank you.


Solution

  • Observe that goldbach/2 is the predicate being defined, which uses an auxiliary predicate goldbach/3. goldbach/3 is called by goldbach/2 when certain conditions on N are met in order to compute the doubleton L, using 3 as the initial value for the auxiliary parameter P of goldbach/3.

    In fact, you can see that goldbach/3 will always be called with its first and third parameters instantiated. The requirement on the first parameter is clear from the documentation of goldbach/2, which marks it as +; the third parameter is provided when goldbach/2 calls its helper goldbach/3 to perform the computation.

    A call like goldbach(4, X, Y) fails because it tries to perform arithmetic (Q is N - P) involving uninstantiated variables, which results in an error: arithmetic on logic variables does not make sense to Prolog. To clarify, the program should work fine, but you are not supposed to call goldbach/3 directly.

    As it stands, the predicate is_prime/1 is missing. The ensure_loaded/1 directive you removed was looking for the file where this predicate would be defined (in this development).