
%% TABLEAUX IPC benchmarks.



%================================================
% for Prolog
% Prolog operator definitions

:- op(425,  fy,  ~ ).
:- op(450, yfx,  & ).    % left associative
:- op(475, yfx,  v ).    % left associative
:- op(500, xfx,  <-> ).  % non associative
:- op(500, xfy,  ->).    % right associative  
      %%% WARNING, this overwrites Prolog's ->

% Timing tools differ between implementations...

%#################################################
%#################################################
%# 9.1 de Bruijn formulae
%#################################################

%Prolog code--------------------------------------

de_bruijn_p(N, F ) :-
  N1 is 2*N + 1,
  dB(N1, F).

de_bruijn_n(N, F ) :-
  N1 is 2*N,
  dB(N1, A -> C),
  F = A -> ( p(0) v C v ~p(0) ). %the p(0) bits used to say p0

dB(N, A -> C) :-
  atoms(N, N, [], Ps),
  conj(Ps, C),
  make(Ps, C, As),
  conj(As, A).

atoms(_, M, Atoms, Atoms) :- M =< 0.
atoms(N, M, Atoms, Result) :-
  M > 0,
  M1 is M-1,
  atoms(N, M1, [p(M) | Atoms], Result).

conj( [H], H).
conj( [H1, H2 | Tail], C) :-
  conj( [H1 & H2 | Tail], C).

make([ P0 | Ps], C, As ) :-
  make4([ P0 | Ps], P0, C, As). 

make4( [Pn], P0, C, [(Pn<->P0)->C] ).
make4( [P1, P2 | Tail], P0, C, [(P1<->P2)->C | Rest] ) :-
  make4( [P2 | Tail], P0, C, Rest).

%#################################################
%#################################################
%#9.2 Pigeonhole formulae
%#################################################


%Prolog code--------------------------------------

ph_p(N, L -> R ) :-
  left(N, pos, L),
  right(N,R).

ph_n(N, L -> R ) :-
  left(N, neg, L),
  right(N,R).

right(N, R) :-
  disj(N, 1, false, R).

disj( N, H, D, D ) :-
  H > N.
disj( N, H, D, D1 ) :-
  H =< N,  
  N1 is N+1, 
  disj1(N1, H, 1, D, D0),
  H1 is H+1, 
  disj(N, H1, D0, D1).

disj1( N1, _, P1, D, D ) :- 
  P1 > N1.
disj1( N1, H, P1, D, D1 ) :- 
  P1 =< N1,
  P11 is P1 + 1,
  disj2(N1, H, P1, P11, D, D0),
  disj1(N1, H, P11, D0, D1).

disj2( N1, _, _, P2, D, D ) :-  
  P2 > N1.
disj2( N1, H, P1, P2, D, D1 ) :-
  P2 =< N1,
  P21 is P2+1, 
  disjoin(D, pr(P1,H) & pr(P2,H), DC), 
  disj2(N1, H, P1, P21, DC, D1).
  

left( N, Sign, L ) :-
  N1 is N+1, 
  conj(N1, N, 1, Sign, true, L).

conj(N1, _, P, _, C, C ) :- 
  P > N1.
conj(N1, N, P, Sign, C, C1 ) :-
  P =< N1,
  cd(N, 1, P, false, Sign, D),
  P1 is P+1, 
  conjoin(C, D, CD), 
  conj(N1, N, P1, Sign, CD, C1).

cd( N, H, _, D,  _,  D )  :-  
  H > N.
cd( N, H, P, D, Sign, D1 ) :-
  H =< N,
  H1 is H+1,
  signify(Sign, pr(P,H), H-N,  SOPH), 
  disjoin(D, SOPH, DOPH), 
  cd(N, H1, P, DOPH, Sign, D1).
  
signify( neg, X,  H - H, ~ ~X) :- !. 
signify( _, X, _ - _, X). 

disjoin(false, D, D) :- !.
disjoin(D1, D, D1 v D).

conjoin(true, D, D) :- !.
conjoin(D1, D, D1 & D).

%#################################################
%#################################################
%9.3	
%#################################################
%# Examples of Franzen
%# con_p(n) requires n contractions in LJ
%# con_n(n) similar but unprovable
%#################################################

%Prolog code--------------------------------------

con_p(N, ( (C v D) -> p(f)) -> p(f) ) :-
   disjs(N, pos, D),
   conjs(N, C). 

con_n(N, ( (C v D) -> p(f)) -> p(f) ) :-
   disjs(N, neg, D),
   conjs(N, C). 

conjs(1, p(1)).
conjs(N,  C & p(N) ) :-
  N > 1,
  N1 is N-1, 
  conjs(N1, C).

disjs(1, pos, p(1) -> p(f)).
disjs(1, neg, ( ~ ~p(1)) -> p(f)).
disjs(N,  Sign, D v ( p(N) -> p(f))  ) :-
  N > 1,
  N1 is N-1, 
  disjs(N1, Sign, D).

%#################################################
%#################################################
%9.4	
%#################################################
%# Schwichtenberg's formulae
%# normal natural deduction of schwicht_p(n) has size exponential in n
%% easy for sequent calculus-based systems
%#################################################

%------------------------------------------------
schwicht_p( N, A -> p(0) ) :-
  ant(N, 1, p(N), A).

schwicht_n( N, A -> p(0) ) :-
  ant(N, 1, ~ ~p(N), A).

ant( N, I, A, A ) :- I > N.
ant( N, I, A, A1 ) :- 
  I =< N,
  I1 is I+1, IM1 is I-1, 
  ant(N, I1, A & ( p(I) -> p(I) -> p(IM1)) , A1).

%#################################################
%################################################
%9.5	
%#################################################
%# Korn & Kreitz's formulae
%# modified to avoid use of Glivenko theorem
%#################################################



%Prolog code--------------------------------------

kk_p(N, (A->p(f)) & (AR->p(f)) ) :- kk_p(N, N, A), kkr(N,N,AR).

kk_p(N, 0,  (pr(a, 0) -> p(f)) & ((pr(b, N)->pr(b, 0))-> ( pr(a, N)) ) ).

kk_p(N, I, LHS & ((pr(b, I1)->pr(a, I))->( pr(a, I1))) ) :-
  0 < I, 
  I1 is I-1,
  kk_p(N, I1, LHS).


kkr(N, 0,  ((pr(b, N)->pr(b, 0))->  pr(a, N) )  & (pr(a, 0) -> p(f))  ).

kkr(N, I,  ((pr(b, I1)->pr(a, I))->  pr(a, I1) )  & LHS ) :-
  0 < I, 
  I1 is I-1,
  kkr(N, I1, LHS).


kk_n(N, A -> p(f) ) :- kk_n(N, N, A).

kk_n(N, 0,  (pr(a, 0) -> p(f)) & ((~ ~pr(b, N)->pr(b, 0))-> ( pr(a, N)) ) ).

kk_n(N, I, LHS & ((~ ~pr(b, I1)->pr(a, I))->( pr(a, I1))) ) :-
  0 < I, 
  I1 is I-1,
  kk_n(N, I1, LHS).

%#################################################
%#################################################
%# 9.6 Equivalences
%#################################################

%Prolog code--------------------------------------

equiv_p( N, A ) :- equiv( N, p, A).
equiv_n( N, A ) :- equiv( N, n, A).

equiv( 1, n,  (~ ~p(1)) <-> p(1) ).
equiv( 1, p,  p(1) <-> p(1) ).

equiv(N, S, AB <-> BA ) :- 
   N > 1,
   N1 is N-1,  AN = p(N),
  equiv( N1, S, A1 <-> A2), 
  AB = A1 <-> AN, 
  BA = AN <-> A2.

%#################################################
%#################################################
%#################################################
%#################################################
%#################################################
%#################################################
%#################################################

