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.