Ok, got a first version working. The first thing is to obtain
the negation normal form. For more efficiency we replace positive
and negative literals by a pos/1 and neg/1 wrapper:
% norm(+Form,-Norm)
norm(A, R) :- var(A), !, R = pos(A).
norm((A;B), R) :- !, norm(A, C), norm(B, D), R = or(C,D).
norm((A,B), R) :- !, norm(A, C), norm(B, D), R = and(C,D).
norm(all(A,B), R) :- !, norm(B, C), R = all(A,C).
norm(exist(A,B), R) :- !, norm(B, C), R = exist(A,C).
norm(-A, R) :- var(A), !, R = neg(A).
norm(- (A;B), R) :- !, norm(-A, C), norm(-B, D), R = and(C,D).
norm(- (A,B), R) :- !, norm(-A, C), norm(-B, D), R = or(C,D).
norm(- all(A,B), R) :- !, norm(-B, C), R = exist(A,C).
norm(- exist(A,B), R) :- !, norm(-B, C), R = all(A,C).
norm(- -A, R) :- !, norm(A, R).
norm(-A, R) :- !, R = neg(A).
norm(A, pos(A)).
The next step is simple, because we assume that the input
formula has distinct variables. So we assume for example
that the user does not input all(X,all(X,p(X)), but rather
all(Y,all(X,p(X)):
% herbrand(+Norm, +List, +Integer, -Integer, -Herbrand)
herbrand(pos(A), _, N, N, pos(A)).
herbrand(neg(A), _, N, N, neg(A)).
herbrand(or(A,B), L, N, M, or(C,D)) :-
herbrand(A, L, N, H, C),
herbrand(B, L, H, M, D).
herbrand(and(A,B), L, N, M, and(C,D)) :-
herbrand(A, L, N, H, C),
herbrand(B, L, H, M, D).
herbrand(all(A,B), L, N, M, C) :-
number_codes(N, R),
atom_codes(F, [0'$|R]),
A =.. [F|L],
H is N+1,
herbrand(B, L, H, M, C).
herbrand(exist(A,B), L, N, M, exist(A,C)) :-
herbrand(B, [A|L], N, M, C).
The rest is then the prover from the abstract, using
and/2 and or/2 instead. Further our implementation uses
a different iterative deepening approach, so that we can
better search for smaller proofs.
Testing is still ongoing, but we could already test
Aristoteles syllogism test cases such as:
case(1, aristo_conversion1, (all(A, (b(A) -: -a(A))) -: all(B, (a(B) -: -b(B))))).
case(2, aristo_conversion2, (exist(A, (b(A), a(A))) -: exist(B, (a(B), b(B))))).
case(3, aristo_conversion3, (all(A, (b(A) -: a(A))), exist(B, b(B)) -: exist(C, (a(C), b(C))))).
case(4, barbara, (all(A, (b(A) -: a(A))), all(B, (c(B) -: b(B))) -: all(C, (c(C) -: a(C))))).
case(5, celarent, (all(A, (b(A) -: -a(A))), all(B, (c(B) -: b(B))) -: all(C, (c(C) -: -a(C))))).
Etc...
Running the test cases shows me the number of (∃C) rule
applications. In total there are 21 test cases.
They all pass!
?- show.
test 1 passed with 1 existential rule applications.
test 2 passed with 1 existential rule applications.
test 3 passed with 2 existential rule applications.
test 4 passed with 2 existential rule applications.
test 5 passed with 2 existential rule applications.
Etc..
I have named the file with the prover fitting.pl in honor
of Melvin Fitting’s heroic 1990 book.
Source code:
Maslov Calculus over Herbrandisized Formulas
https://gist.github.com/jburse/820783d6e0fbfd55b907bdbe0e3e2c7e#file-fitting-pl
Aristoteles Test Cases from Isabelle/HOL
With Beckert and Posegga operators
https://gist.github.com/jburse/820783d6e0fbfd55b907bdbe0e3e2c7e#file-aristoteles-pl