prologsuccessor-arithmeticslogical-purity

`less/2` relation in Peano arithmetic


This less-than predicate in Peano arithmetic

less(0, s(_)).
less(s(X), s(Y)) :- less(X, Y).

loops when

?- less(X, Y), X=s(0), Y=0.

Is there a better way to write less/2 (using Horn clauses only)?


Solution

  • You can use when/2. Making it not anymore an infinitely enumerating predicate and still keeping it 100% pure. The when/2 modifies the S (selection rule) in SLD-Resolution, an idea that can be traced back to Alain Colmerauer.

    less(X, Y) :- when((nonvar(X),nonvar(Y)), less2(X,Y)).
    less2(0, s(_)).
    less2(s(X), s(Y)) :- less(X, Y).
    

    The rewriting of less/2 into less/2 and less2/2 is similary like tabling rewriting. You insert a stub and rename the clause head. But the recursive call in the body is not rewritten, is then a call to the stub again.

    You now get steadfastness:

    ?- less(s(s(0)), s(s(s(0)))).
    true.
    
    ?- less(X, Y), X = s(s(0)), Y = s(s(s(0))).
    X = s(s(0)),
    Y = s(s(s(0))).
    

    And even failfastness and truefastness sometimes:

    ?- less(s(s(_)), s(0)).
    false.
    
    ?- less(s(0), s(s(_))).
    true.
    

    Some Prolog systems even provide a table/1 like directive, so that you don't need to do the rewriting, only make the declaration. One such system is SICStus Prolog. In SICStus Prolog, thanks to the block/1 directive,

    you would only write:

    :- block less(-,?), less(?,-).
    less(0, s(_)).
    less(s(X), s(Y)) :- less(X, Y).
    

    For a 1980's Paper see for example:

    An Implementation of dif and freeze in the WAM
    Mats Carlsson - December 18, 1986
    http://www.softwarepreservation.com/projects/prolog/sics/doc/Carlsson-SICS-TR-86-12.pdf/view