Generate and test

In these approaches, the early subgoals generate a solution and the late subgoals test it for correctness.

If an attempted solution is rejected by a test, then we backtrack and generate another solution to try.

Cuts are applied when we know there is only one possible solution that can pass the early subgoals - if it fails later then there is no point in trying to generate a new solution with the current rule.

Consider the following example to see if a Numerator/Denominator == Result:

% check if something is an integer, instantiates 0,1,2,...
is_integer(0).
is_integer(N) :- N > 0, A is N-1, is_integer(A).

% check if R*D == N, if all three given as numbers
divides(Numerator,Denominator,Result) :-
   nonvar(Numerator), nonvar(Denominator), nonvar(Result),
   number(Numerator), number(Denominator), number(Result),
   is_integer(Result), 
   Result * Denominator =< Numerator,       
   (Result + 1) * Denominator > Denominator,
   !. 
% the cut ensures we stop as soon as the denominator gets
%   so large that Denominator*Result > Numerator
% (no solutions are possible above that point)

% evaluate if Numerator is unspecified but other two are numbers
divides(Numerator,Denominator,Result) :-
   nonvar(Denominator), nonvar(Result), var(Numerator),
   number(Denominator), number(Result),
   Numerator is Denominator*Result.

% evaluate if Result is unspecified but other two are numbers
divides(Numerator,Denominator,Result) :-
   nonvar(Numerator), nonvar(Denominator), var(Result),
   number(Numerator), number(Denominator), 0 =\= Denominator,
   Result is Numerator / Denominator.

% evaluate if Denominator is unspecified but other two are numbers
divides(Numerator,Denominator,Result) :-
   nonvar(Numerator), var(Denominator), nonvar(Result),
   number(Numerator), number(Result), 0 =\= Result,
   Denominator is Numerator / Result.