Thats the code of the two provers. First leanTap you might easily recognize:
prove((A|B),UnExp,Lits,FreeV,VarLim) :- !,
prove(A,[B|UnExp],Lits,FreeV,VarLim).
prove((A&B),UnExp,Lits,FreeV,VarLim) :- !,
prove(A,UnExp,Lits,FreeV,VarLim),
prove(B,UnExp,Lits,FreeV,VarLim).
prove((?[X]:Fml),UnExp,Lits,FreeV,VarLim) :- VarLim>0, !,
copy_term((X,Fml,FreeV),(X1,Fml1,FreeV)),
append(UnExp,[(?[X]:Fml)],UnExp1),
VarLim2 is VarLim-1,
prove(Fml1,UnExp1,Lits,[X1|FreeV],VarLim2).
prove(Lit,_,Lits,_,_) :-
\+ Lit = (?_),
member(L,Lits), unify_with_occurs_check(Lit,L).
prove(Fml,[Next|UnExp],Lits,FreeV,VarLim) :-
opposite(Fml, Fml1),
prove(Next,UnExp,[Fml1|Lits],FreeV,VarLim).
And here leanSeq, which expects NNF and does literal saturation:
prove((A|B),UnExp,Lits,FreeV,VarLim,J,K) :- !,
prove(A,[B|UnExp],Lits,FreeV,VarLim,J,K).
prove((A&B),UnExp,Lits,FreeV,VarLim,J,K) :- !,
prove(A,UnExp,Lits,FreeV,VarLim,J,H),
prove(B,UnExp,Lits,FreeV,VarLim,H,K).
prove((![X]:Fml),UnExp,Lits,FreeV,VarLim,J,K) :- !,
copy_term((X:Fml,FreeV),(h(J,FreeV):Fml1,FreeV)),
J1 is J+1,
prove(Fml1,UnExp,Lits,FreeV,VarLim,J1,K).
prove(Lit,_,Lits,_,_,J,J) :-
\+ Lit = (?_),
member(L,Lits),
unify_with_occurs_check(Lit,L).
prove(Fml,[Next|UnExp],Lits,FreeV,VarLim,J,K) :- !,
opposite(Fml, Fml1),
prove(Next,UnExp,[Fml1|Lits],FreeV,VarLim,J,K).
% we are saturated
prove(Fml,[],Lits,FreeV,VarLim,J,K) :- VarLim>0, opposite(Fml, L),
member(H,[L|Lits]),
H = ~ (?_),
opposite(H,M),
block(M,[L|Lits],FreeV,VarLim,J,K).
% quantifier block
block((?[X]:Fml),Lits,FreeV,VarLim,J,K) :- !, VarLim>0,
copy_term((X:Fml,FreeV),(Y:Fml1,FreeV)),
VarLim2 is VarLim-1,
block(Fml1,Lits,[Y|FreeV],VarLim2,J,K).
block(Fml,Lits,FreeV,VarLim,J,K) :-
prove(Fml,[],Lits,FreeV,VarLim,J,K).
The new leanSeq has a little more backtracking in the handling of (?[X]:Fml),
block/6 is mitigating the problem a little bit. Overall the penality seems to be
not so high, measured by the simple Pelletier problems