diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -15,8 +15,8 @@
 
 Afterwards, run `twee nameofproblem.p`. The problem should be in TPTP
 format (http://www.tptp.org). You can find a few examples in the
-`tests` directory. All axioms and conjectures must be equations, but
+`examples` directory. All axioms and conjectures must be equations, but
 you can freely use quantifiers. If it succeeds in proving your
 problem, twee will print a human-readable proof.
 
-For the official manual, see http://nick8325.github.io/twee.
+For the official manual, see https://twee.smallbone.se.
diff --git a/examples/BOO067-1.p b/examples/BOO067-1.p
new file mode 100644
--- /dev/null
+++ b/examples/BOO067-1.p
@@ -0,0 +1,32 @@
+%--------------------------------------------------------------------------
+% File     : BOO067-1 : TPTP v6.3.0. Released v2.6.0.
+% Domain   : Boolean Algebra (Ternary)
+% Problem  : Ternary Boolean Algebra Single axiom is complete, part 1
+% Version  : [MP96] (equality) axioms.
+% English  :
+
+% Refs     : [McC98] McCune (1998), Email to G. Sutcliffe
+%          : [MP96]  McCune & Padmanabhan (1996), Automated Deduction in Eq
+% Source   : [TPTP]
+% Names    :
+
+% Status   : Unsatisfiable
+% Rating   : 0.42 v6.3.0, 0.35 v6.2.0, 0.29 v6.1.0, 0.31 v6.0.0, 0.48 v5.5.0, 0.47 v5.4.0, 0.33 v5.3.0, 0.25 v5.2.0, 0.29 v5.1.0, 0.33 v5.0.0, 0.29 v4.1.0, 0.18 v4.0.1, 0.36 v4.0.0, 0.38 v3.7.0, 0.11 v3.4.0, 0.12 v3.3.0, 0.21 v3.1.0, 0.33 v2.7.0, 0.27 v2.6.0
+% Syntax   : Number of clauses     :    2 (   0 non-Horn;   2 unit;   1 RR)
+%            Number of atoms       :    2 (   2 equality)
+%            Maximal clause size   :    1 (   1 average)
+%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
+%            Number of functors    :    7 (   5 constant; 0-3 arity)
+%            Number of variables   :    7 (   0 singleton)
+%            Maximal term depth    :    5 (   3 average)
+% SPC      : CNF_UNS_RFO_PEQ_UEQ
+
+% Comments : A UEQ part of BOO035-1
+%--------------------------------------------------------------------------
+cnf(single_axiom,axiom,
+    ( multiply(multiply(A,inverse(A),B),inverse(multiply(multiply(C,D,E),F,multiply(C,D,G))),multiply(D,multiply(G,F,E),C)) = B )).
+
+cnf(prove_tba_axioms_1,negated_conjecture,
+    (  multiply(multiply(d,e,a),b,multiply(d,e,c)) != multiply(d,e,multiply(a,b,c)) )).
+
+%--------------------------------------------------------------------------
diff --git a/examples/GRP196-1.p b/examples/GRP196-1.p
new file mode 100644
--- /dev/null
+++ b/examples/GRP196-1.p
@@ -0,0 +1,40 @@
+%--------------------------------------------------------------------------
+% File     : GRP196-1 : TPTP v7.4.0. Released v2.2.0.
+% Domain   : Group Theory (Semigroups)
+% Problem  : In semigroups, xyyy=yyyx -> (uy)^9 = u^9v^9.
+% Version  : [MP96] (equality) axioms.
+% English  :
+
+% Refs     : [McC98] McCune (1998), Email to G. Sutcliffe
+%          : [MP96]  McCune & Padmanabhan (1996), Automated Deduction in Eq
+%          : [McC95] McCune (1995), Four Challenge Problems in Equational L
+% Source   : [McC98]
+% Names    : CS-3 [MP96]
+%          : Problem B [McC95]
+
+% Status   : Unsatisfiable
+% Rating   : 0.88 v7.4.0, 0.91 v7.3.0, 0.89 v7.0.0, 0.95 v6.4.0, 1.00 v4.0.1, 0.93 v4.0.0, 0.92 v3.7.0, 0.89 v3.4.0, 1.00 v3.3.0, 0.93 v3.1.0, 1.00 v2.2.1
+% Syntax   : Number of clauses     :    3 (   0 non-Horn;   3 unit;   1 RR)
+%            Number of atoms       :    3 (   3 equality)
+%            Maximal clause size   :    1 (   1 average)
+%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
+%            Number of functors    :    3 (   2 constant; 0-2 arity)
+%            Number of variables   :    5 (   0 singleton)
+%            Maximal term depth    :   18 (   8 average)
+% SPC      : CNF_UNS_RFO_PEQ_UEQ
+
+% Comments : The problem was originally posed for cancellative semigroups,
+%            Otter does this with a nonstandard representation [MP96].
+%--------------------------------------------------------------------------
+%----Include semigroups axioms
+include('Axioms/GRP008-0.ax').
+%--------------------------------------------------------------------------
+%----Hypothesis:
+cnf(condition,hypothesis,
+    ( '*'(X,'*'(Y,'*'(Y,Y))) = '*'(Y,'*'(Y,'*'(Y,X))) )).
+
+%----Denial of conclusion:
+cnf(prove_this,negated_conjecture,
+    (  '*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,b))))))))))))))))) != '*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(b,'*'(b,'*'(b,'*'(b,'*'(b,'*'(b,'*'(b,'*'(b,b))))))))))))))))) )).
+
+%--------------------------------------------------------------------------
diff --git a/examples/GRP666-4.p b/examples/GRP666-4.p
new file mode 100644
--- /dev/null
+++ b/examples/GRP666-4.p
@@ -0,0 +1,63 @@
+%------------------------------------------------------------------------------
+% File     : GRP666-4 : TPTP v7.2.0. Released v4.0.0.
+% Domain   : Group Theory (Quasigroups)
+% Problem  : Inverse property A-loops are Moufang
+% Version  : Especial.
+% English  :
+
+% Refs     : [KKP02] Kinyon et al. (2002), Every Diassociative A-loop is M
+%          : [PS08]  Phillips & Stanovsky (2008), Automated Theorem Proving
+%          : [Sta08] Stanovsky (2008), Email to G. Sutcliffe
+% Source   : [Sta08]
+% Names    : KKP02a [PS08]
+
+% Status   : Unsatisfiable
+% Rating   : 0.84 v7.1.0, 0.83 v7.0.0, 0.89 v6.3.0, 0.82 v6.2.0, 0.71 v6.1.0, 0.81 v5.5.0, 0.84 v5.4.0, 0.87 v5.3.0, 0.75 v5.2.0, 0.86 v5.1.0, 0.87 v5.0.0, 0.86 v4.1.0, 0.82 v4.0.1, 0.86 v4.0.0
+% Syntax   : Number of clauses     :   12 (   0 non-Horn;  12 unit;   1 RR)
+%            Number of atoms       :   12 (  12 equality)
+%            Maximal clause size   :    1 (   1 average)
+%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
+%            Number of functors    :    8 (   4 constant; 0-2 arity)
+%            Number of variables   :   25 (   0 singleton)
+%            Maximal term depth    :    5 (   3 average)
+% SPC      : CNF_UNS_RFO_PEQ_UEQ
+
+% Comments :
+%------------------------------------------------------------------------------
+cnf(c01,axiom,
+    ( mult(A,ld(A,B)) = B )).
+
+cnf(c02,axiom,
+    ( ld(A,mult(A,B)) = B )).
+
+cnf(c03,axiom,
+    ( mult(rd(A,B),B) = A )).
+
+cnf(c04,axiom,
+    ( rd(mult(A,B),B) = A )).
+
+cnf(c05,axiom,
+    ( mult(A,unit) = A )).
+
+cnf(c06,axiom,
+    ( mult(unit,A) = A )).
+
+cnf(c07,axiom,
+    ( ld(mult(A,B),mult(A,mult(B,mult(C,D)))) = mult(ld(mult(A,B),mult(A,mult(B,C))),ld(mult(A,B),mult(A,mult(B,D)))) )).
+
+cnf(c08,axiom,
+    ( rd(mult(mult(mult(A,B),C),D),mult(C,D)) = mult(rd(mult(mult(A,C),D),mult(C,D)),rd(mult(mult(B,C),D),mult(C,D))) )).
+
+cnf(c09,axiom,
+    ( ld(A,mult(mult(B,C),A)) = mult(ld(A,mult(B,A)),ld(A,mult(C,A))) )).
+
+cnf(c10,axiom,
+    ( mult(i(A),mult(A,B)) = B )).
+
+cnf(c11,axiom,
+    ( mult(mult(A,B),i(B)) = A )).
+
+cnf(goals,negated_conjecture,
+    ( mult(mult(a,b),mult(c,a)) != mult(mult(a,mult(b,c)),a) )).
+
+%------------------------------------------------------------------------------
diff --git a/examples/LAT071-1.p b/examples/LAT071-1.p
new file mode 100644
--- /dev/null
+++ b/examples/LAT071-1.p
@@ -0,0 +1,37 @@
+%--------------------------------------------------------------------------
+% File     : LAT071-1 : TPTP v7.2.0. Released v2.6.0.
+% Domain   : Lattice Theory (Orthomodularlattices)
+% Problem  : Given single axiom OML-21C, prove associativity
+% Version  : [MRV03] (equality) axioms.
+% English  : Given a single axiom candidate OML-21C for orthomodular lattices
+%            (OML) in terms of the Sheffer Stroke, prove a Sheffer stroke form
+%            of associativity.
+
+% Refs     : [MRV03] McCune et al. (2003), Sheffer Stroke Bases for Ortholatt
+% Source   : [MRV03]
+% Names    : OML-21C-associativity [MRV03]
+
+% Status   : Open
+% Rating   : 1.00 v2.6.0
+% Syntax   : Number of clauses     :    2 (   0 non-Horn;   2 unit;   1 RR)
+%            Number of atoms       :    2 (   2 equality)
+%            Maximal clause size   :    1 (   1 average)
+%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
+%            Number of functors    :    4 (   3 constant; 0-2 arity)
+%            Number of variables   :    4 (   2 singleton)
+%            Maximal term depth    :    6 (   4 average)
+% SPC      : CNF_OPN_RFO_PEQ_UEQ
+
+% Comments :
+%--------------------------------------------------------------------------
+%----Single axiom OML-21C
+cnf(oml_21C,axiom,
+    ( f(f(B,A),f(f(f(f(B,A),A),f(C,A)),f(f(A,A),D))) = A )).
+
+%----Denial of Sheffer stroke associativity
+cnf(associativity,negated_conjecture,
+    (  f(a,f(f(b,c),f(b,c))) != f(c,f(f(b,a),f(b,a))) )).
+
+cnf(bonus, axiom, f(A,B)=f(B,A)).
+
+%--------------------------------------------------------------------------
diff --git a/examples/LAT072-1.p b/examples/LAT072-1.p
new file mode 100644
--- /dev/null
+++ b/examples/LAT072-1.p
@@ -0,0 +1,37 @@
+%--------------------------------------------------------------------------
+% File     : LAT072-1 : TPTP v6.3.0. Released v2.6.0.
+% Domain   : Lattice Theory (Ortholattices)
+% Problem  : Given single axiom OML-23A, prove associativity
+% Version  : [MRV03] (equality) axioms.
+% English  : Given a single axiom candidate OML-23A for orthomodular lattices
+%            (OML) in terms of the Sheffer Stroke, prove a Sheffer stroke form
+%            of associativity.
+
+% Refs     : [MRV03] McCune et al. (2003), Sheffer Stroke Bases for Ortholatt
+% Source   : [MRV03]
+% Names    : OML-23A-associativity [MRV03]
+
+% Status   : Unsatisfiable
+% Rating   : 0.95 v6.3.0, 0.94 v6.2.0, 0.93 v6.1.0, 0.94 v6.0.0, 0.95 v5.4.0, 1.00 v2.6.0
+% Syntax   : Number of clauses     :    2 (   0 non-Horn;   2 unit;   1 RR)
+%            Number of atoms       :    2 (   2 equality)
+%            Maximal clause size   :    1 (   1 average)
+%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
+%            Number of functors    :    4 (   3 constant; 0-2 arity)
+%            Number of variables   :    4 (   2 singleton)
+%            Maximal term depth    :    7 (   4 average)
+% SPC      : CNF_UNS_RFO_PEQ_UEQ
+
+% Comments :
+%--------------------------------------------------------------------------
+%----Single axiom OML-23A
+cnf(oml_23A,axiom,
+    ( f(f(f(f(B,A),f(A,C)),D),f(A,f(f(C,f(f(A,A),C)),C))) = A )).
+
+cnf(a, axiom, f(X,Y) = f(Y, X)).
+
+%----Denial of Sheffer stroke associativity
+cnf(associativity,negated_conjecture,
+    (  f(a,f(f(b,c),f(b,c))) != f(c,f(f(b,a),f(b,a))) )).
+
+%--------------------------------------------------------------------------
diff --git a/examples/LAT073-1.p b/examples/LAT073-1.p
new file mode 100644
--- /dev/null
+++ b/examples/LAT073-1.p
@@ -0,0 +1,37 @@
+%--------------------------------------------------------------------------
+% File     : LAT073-1 : TPTP v7.2.0. Released v2.6.0.
+% Domain   : Lattice Theory (Ortholattices)
+% Problem  : Given single axiom MOL-23C, prove modularity
+% Version  : [MRV03] (equality) axioms.
+% English  : Given a single axiom candidate MOL-23C for modular ortholattices
+%            (MOL) in terms of the Sheffer Stroke, prove a Sheffer stroke form
+%            of modularity.
+
+% Refs     : [MRV03] McCune et al. (2003), Sheffer Stroke Bases for Ortholatt
+% Source   : [MRV03]
+% Names    : MOL-23C-modularity [MRV03]
+
+% Status   : Open
+% Rating   : 1.00 v2.6.0
+% Syntax   : Number of clauses     :    2 (   0 non-Horn;   2 unit;   1 RR)
+%            Number of atoms       :    2 (   2 equality)
+%            Maximal clause size   :    1 (   1 average)
+%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
+%            Number of functors    :    4 (   3 constant; 0-2 arity)
+%            Number of variables   :    4 (   1 singleton)
+%            Maximal term depth    :    7 (   4 average)
+% SPC      : CNF_OPN_RFO_PEQ_UEQ
+
+% Comments :
+%--------------------------------------------------------------------------
+%----Single axiom MOL-23C
+cnf(mol_23C,axiom,
+    ( f(f(f(B,f(A,B)),B),f(A,f(C,f(f(A,B),f(f(C,C),D))))) = A )).
+
+%----Denial of Sheffer stroke modularity
+cnf(modularity,negated_conjecture,
+    (  f(a,f(b,f(a,f(c,c)))) != f(a,f(c,f(a,f(b,b)))) )).
+
+cnf(bonus, axiom, f(A,B)=f(B,A)).
+
+%--------------------------------------------------------------------------
diff --git a/examples/PUZ037-3-2.p b/examples/PUZ037-3-2.p
new file mode 100644
--- /dev/null
+++ b/examples/PUZ037-3-2.p
@@ -0,0 +1,106 @@
+%--------------------------------------------------------------------------
+% File     : PUZ037-3 : TPTP v7.2.0. Released v2.3.0.
+% Domain   : Puzzles
+% Problem  : Rubik's Cube
+% Version  : [HM98] axioms : Especial.
+%            Theorem formulation : Rotation in all three planes.
+% English  : Rubik's Cube is a 3x3x3 cube consisting of 27 subcubes with
+%            colored faces. The three layers perpendicular to any axis may
+%            be rotated independently. The object is to take a scrambled
+%            cube and unscramble it so that each side consists entirely
+%            of one color(Blue, White, Green, Yellow, Orange, Red).
+
+% Refs     : [HM98]  Huang & Myers (1998), Subgoal Strategies for Solving B
+% Source   : [HM98]
+% Names    : Rubik's Cube [HM98]
+
+% Status   : Unsatisfiable
+% Rating   : 0.20 v7.2.0, 0.22 v7.1.0, 0.14 v6.4.0, 0.17 v6.3.0, 0.25 v6.2.0, 0.12 v6.1.0, 0.00 v5.5.0, 0.20 v5.4.0, 0.33 v5.0.0, 0.50 v4.1.0, 0.60 v3.7.0, 0.50 v3.5.0, 0.33 v3.1.0, 0.44 v2.7.0, 0.50 v2.6.0, 0.44 v2.5.0, 0.75 v2.4.0, 0.67 v2.3.0
+% Syntax   : Number of clauses     :   20 (   0 non-Horn;   2 unit;  20 RR)
+%            Number of atoms       :   38 (   0 equality)
+%            Maximal clause size   :    2 (   2 average)
+%            Number of predicates  :    1 (   0 propositional; 54-54 arity)
+%            Number of functors    :    6 (   6 constant; 0-0 arity)
+%            Number of variables   :  972 (   0 singleton)
+%            Maximal term depth    :    1 (   1 average)
+% SPC      : CNF_UNS_EPR
+
+% Comments : mzy, mzy, bzy, byx, lzx rotations to solve.
+%--------------------------------------------------------------------------
+cnf(a, axiom,
+    state(b,b,b,b,b,b,b,b,b,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,w,w,w,w,w,w,w,w,w) !=
+    state(b,r,r,w,w,w,y,b,b,g,y,r,b,g,g,o,g,y,w,w,r,g,o,r,b,g,g,o,r,b,y,y,r,g,o,g,o,o,o,y,r,b,y,y,r,w,w,w,b,b,y,w,o,o)).
+
+cnf(txy,axiom,
+    (  state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
+    = state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
+
+cnf(mxy,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
+    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
+
+cnf(bxy,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3)
+    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5) )).
+
+cnf(fzy,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6)
+    = state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6) )).
+
+cnf(mzy,axiom,
+    (  state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6)
+    = state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6) )).
+
+cnf(bzy,axiom,
+    (  state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4)
+    = state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7) )).
+
+cnf(lzx,axiom,
+    (  state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7)
+    = state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7) )).
+
+cnf(mzx,axiom,
+    (  state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6)
+    = state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6) )).
+
+cnf(rzx,axiom,
+    (  state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6)
+    = state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9) )).
+
+cnf(tyx,axiom,
+    (  state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
+    = state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
+
+cnf(myx,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
+    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
+
+cnf(byx,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5)
+    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3) )).
+
+cnf(fyz,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6)
+    = state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6) )).
+
+cnf(myz,axiom,
+    (  state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6)
+    = state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6) )).
+
+cnf(byz,axiom,
+    (  state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7)
+    = state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4) )).
+
+cnf(lxz,axiom,
+    (  state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7)
+    = state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7) )).
+
+cnf(mxz,axiom,
+    (  state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6)
+    = state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6) )).
+
+cnf(rxz,axiom,
+    (  state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9)
+    = state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6) )).
+
+%--------------------------------------------------------------------------
diff --git a/examples/PUZ037-3.p b/examples/PUZ037-3.p
new file mode 100644
--- /dev/null
+++ b/examples/PUZ037-3.p
@@ -0,0 +1,110 @@
+%--------------------------------------------------------------------------
+% File     : PUZ037-3 : TPTP v7.2.0. Released v2.3.0.
+% Domain   : Puzzles
+% Problem  : Rubik's Cube
+% Version  : [HM98] axioms : Especial.
+%            Theorem formulation : Rotation in all three planes.
+% English  : Rubik's Cube is a 3x3x3 cube consisting of 27 subcubes with
+%            colored faces. The three layers perpendicular to any axis may
+%            be rotated independently. The object is to take a scrambled
+%            cube and unscramble it so that each side consists entirely
+%            of one color(Blue, White, Green, Yellow, Orange, Red).
+
+% Refs     : [HM98]  Huang & Myers (1998), Subgoal Strategies for Solving B
+% Source   : [HM98]
+% Names    : Rubik's Cube [HM98]
+
+% Status   : Unsatisfiable
+% Rating   : 0.20 v7.2.0, 0.22 v7.1.0, 0.14 v6.4.0, 0.17 v6.3.0, 0.25 v6.2.0, 0.12 v6.1.0, 0.00 v5.5.0, 0.20 v5.4.0, 0.33 v5.0.0, 0.50 v4.1.0, 0.60 v3.7.0, 0.50 v3.5.0, 0.33 v3.1.0, 0.44 v2.7.0, 0.50 v2.6.0, 0.44 v2.5.0, 0.75 v2.4.0, 0.67 v2.3.0
+% Syntax   : Number of clauses     :   20 (   0 non-Horn;   2 unit;  20 RR)
+%            Number of atoms       :   38 (   0 equality)
+%            Maximal clause size   :    2 (   2 average)
+%            Number of predicates  :    1 (   0 propositional; 54-54 arity)
+%            Number of functors    :    6 (   6 constant; 0-0 arity)
+%            Number of variables   :  972 (   0 singleton)
+%            Maximal term depth    :    1 (   1 average)
+% SPC      : CNF_UNS_EPR
+
+% Comments : mzy, mzy, bzy, byx, lzx rotations to solve.
+%--------------------------------------------------------------------------
+cnf(make_like_this,negated_conjecture, lhs != rhs).
+
+cnf(a, axiom, lhs =
+    state(b,b,b,b,b,b,b,b,b,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,w,w,w,w,w,w,w,w,w)).
+
+cnf(b, axiom, rhs =
+    state(b,r,r,w,w,w,y,b,b,g,y,r,b,g,g,o,g,y,w,w,r,g,o,r,b,g,g,o,r,b,y,y,r,g,o,g,o,o,o,y,r,b,y,y,r,w,w,w,b,b,y,w,o,o)).
+
+cnf(txy,axiom,
+    (  state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
+    = state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
+
+cnf(mxy,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
+    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
+
+cnf(bxy,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3)
+    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5) )).
+
+cnf(fzy,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6)
+    = state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6) )).
+
+cnf(mzy,axiom,
+    (  state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6)
+    = state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6) )).
+
+cnf(bzy,axiom,
+    (  state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4)
+    = state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7) )).
+
+cnf(lzx,axiom,
+    (  state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7)
+    = state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7) )).
+
+cnf(mzx,axiom,
+    (  state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6)
+    = state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6) )).
+
+cnf(rzx,axiom,
+    (  state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6)
+    = state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9) )).
+
+cnf(tyx,axiom,
+    (  state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
+    = state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
+
+cnf(myx,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
+    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
+
+cnf(byx,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5)
+    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3) )).
+
+cnf(fyz,axiom,
+    (  state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6)
+    = state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6) )).
+
+cnf(myz,axiom,
+    (  state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6)
+    = state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6) )).
+
+cnf(byz,axiom,
+    (  state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7)
+    = state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4) )).
+
+cnf(lxz,axiom,
+    (  state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7)
+    = state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7) )).
+
+cnf(mxz,axiom,
+    (  state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6)
+    = state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6) )).
+
+cnf(rxz,axiom,
+    (  state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9)
+    = state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6) )).
+
+%--------------------------------------------------------------------------
diff --git a/examples/PUZ052-1.p b/examples/PUZ052-1.p
new file mode 100644
--- /dev/null
+++ b/examples/PUZ052-1.p
@@ -0,0 +1,129 @@
+%--------------------------------------------------------------------------
+% File     : PUZ052-1 : TPTP v7.2.0. Released v2.7.0.
+% Domain   : Puzzles
+% Problem  : Rubik's Cube unreachability
+% Version  : [HM98] axioms : Especial.
+%            Theorem formulation : Rotations in one plane only.
+% English  : Rubik's Cube is a 3x3x3 cube consisting of 27 subcubes with
+%            colored faces. The three layers perpendicular to any axis may
+%            be rotated independently. The object is to take a scrambled
+%            cube and unscramble it so that each side consists entirely
+%            of one color(Blue, White, Green, Yellow, Orange, Red).
+%            The objective here is unreachable: there are 10 b's and only
+%            8 r's.
+
+% Refs     : [HM98]  Huang & Myers (1998), Subgoal Strategies for Solving B
+%          : [Cla03] Claessen (2003), Email to G. Sutcliffe
+% Source   : [Cla03]
+% Names    :
+
+% Status   : Satisfiable
+% Rating   : 1.00 v2.7.0
+% Syntax   : Number of clauses     :   20 (   0 non-Horn;   2 unit;  20 RR)
+%            Number of atoms       :   38 (   0 equality)
+%            Maximal clause size   :    2 (   2 average)
+%            Number of predicates  :    1 (   0 propositional; 54-54 arity)
+%            Number of functors    :    6 (   6 constant; 0-0 arity)
+%            Number of variables   :  972 (   0 singleton)
+%            Maximal term depth    :    1 (   1 average)
+% SPC      : CNF_SAT_EPR
+
+% Comments : Replaced one b by an r in make_like_this from PUZ037-1.p
+%            Model never found; a domain of size 2 should be enough though.
+%--------------------------------------------------------------------------
+cnf(make_like_this,negated_conjecture,
+    ( state(b,b,b,b,b,b,b,b,b,b,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,w,w,w,w,w,w,w,w,w) !=
+     state(b,b,b,b,b,b,b,b,b,r,r,r,g,g,g,o,o,o,y,y,y,g,g,g,o,o,o,y,y,y,r,r,r,r,r,r,g,g,g,o,o,o,y,y,y,w,w,w,w,w,w,w,w,w) )).
+
+cnf(txy,axiom,
+    ( 
+state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) 
+= state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
+
+cnf(mxy,axiom,
+    ( 
+state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) 
+=
+    state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
+
+cnf(bxy,axiom,
+    ( state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3)
+    = 
+state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5) )).
+
+cnf(fzy,axiom,
+    ( state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6)
+    = 
+state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6) )).
+
+cnf(mzy,axiom,
+    ( state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6)
+    = 
+state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6) )).
+
+cnf(bzy,axiom,
+    ( state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4)
+    = 
+state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7) )).
+
+cnf(lzx,axiom,
+    ( state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7)
+    = 
+state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7) )).
+
+cnf(mzx,axiom,
+    ( state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6)
+    = 
+state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6) )).
+
+cnf(rzx,axiom,
+    ( state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6)
+    = 
+state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9) )).
+
+cnf(tyx,axiom,
+    ( state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
+    = 
+state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
+
+cnf(myx,axiom,
+    ( state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
+    = 
+state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
+
+cnf(byx,axiom,
+    ( state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5)
+    = 
+state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3) )).
+
+cnf(fyz,axiom,
+    ( state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6)
+    = 
+state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6) )).
+
+cnf(myz,axiom,
+    ( state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6)
+    = 
+state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6) )).
+
+cnf(byz,axiom,
+    ( state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7)
+    = 
+state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4) )).
+
+cnf(lxz,axiom,
+    ( state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7)
+    = 
+state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7) )).
+
+cnf(mxz,axiom,
+    ( state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6)
+    = 
+state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6) )).
+
+cnf(rxz,axiom,
+    ( state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9)
+    = 
+state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6) )).
+
+%--------------------------------------------------------------------------
diff --git a/examples/REL038-1.p b/examples/REL038-1.p
new file mode 100644
--- /dev/null
+++ b/examples/REL038-1.p
@@ -0,0 +1,14 @@
+cnf(maddux1_join_commutativity_1, axiom, join(A, B)=join(B, A)).
+cnf(maddux2_join_associativity_2, axiom, join(A, join(B, C))=join(join(A, B), C)).
+cnf(maddux3_a_kind_of_de_Morgan_3, axiom, A=join(complement(join(complement(A), complement(B))), complement(join(complement(A), B)))).
+cnf(maddux4_definiton_of_meet_4, axiom, meet(A, B)=complement(join(complement(A), complement(B)))).
+cnf(composition_associativity_5, axiom, composition(A, composition(B, C))=composition(composition(A, B), C)).
+cnf(composition_identity_6, axiom, composition(A, one)=A).
+cnf(composition_distributivity_7, axiom, composition(join(A, B), C)=join(composition(A, C), composition(B, C))).
+cnf(converse_idempotence_8, axiom, converse(converse(A))=A).
+cnf(converse_additivity_9, axiom, converse(join(A, B))=join(converse(A), converse(B))).
+cnf(converse_multiplicativity_10, axiom, converse(composition(A, B))=composition(converse(B), converse(A))).
+cnf(converse_cancellativity_11, axiom, join(composition(converse(A), complement(composition(A, B))), complement(B))=complement(B)).
+cnf(def_top_12, axiom, top=join(A, complement(A))).
+cnf(def_zero_13, axiom, zero=meet(A, complement(A))).
+cnf(goals_14, negated_conjecture, join(meet(composition(sk1, sk2), sk3), meet(composition(sk1, meet(sk2, composition(converse(sk1), sk3))), sk3))!=meet(composition(sk1, meet(sk2, composition(converse(sk1), sk3))), sk3)).
diff --git a/examples/RNG025-buggy.p b/examples/RNG025-buggy.p
new file mode 100644
--- /dev/null
+++ b/examples/RNG025-buggy.p
@@ -0,0 +1,9 @@
+% SPASS solves this instantly, Twee takes ages!
+cnf(axiom, axiom, multiply(U,add(V,W))=add(multiply(U,V),multiply(U,W))).
+cnf(axiom, axiom, add(U,additive_inverse(add(additive_inverse(V),U)))=V).
+cnf(axiom, axiom, add(U,additive_inverse(add(V,add(W,U))))=additive_inverse(add(V,W))).
+cnf(axiom, axiom, add(additive_inverse(U),V)=additive_inverse(add(U,additive_inverse(V)))).
+cnf(axiom, axiom, multiply(multiply(U,V),W)=add(associator(U,V,W),multiply(U,multiply(V,W)))).
+cnf(axiom, axiom, additive_inverse(add(multiply(U,multiply(V,W)),add(multiply(U,multiply(X,W)),additive_inverse(add(multiply(multiply(U,V),W),multiply(multiply(U,X),W))))))=associator(U,add(V,X),W)).
+
+cnf(conjecture, conjecture, add(associator(U,V,W),associator(U,X,W))=associator(U,add(V,X),W)).
diff --git a/examples/RNG035-7.p b/examples/RNG035-7.p
new file mode 100644
--- /dev/null
+++ b/examples/RNG035-7.p
@@ -0,0 +1,12 @@
+cnf(left_additive_identity, axiom, add(additive_identity, X)=X).
+cnf(right_additive_identity, axiom, add(X, additive_identity)=X).
+cnf(left_additive_inverse, axiom, add(additive_inverse(X), X)=additive_identity).
+cnf(right_additive_inverse, axiom, add(X, additive_inverse(X))=additive_identity).
+cnf(associativity_for_addition, axiom, add(X, add(Y, Z))=add(add(X, Y), Z)).
+cnf(commutativity_for_addition, axiom, add(X, Y)=add(Y, X)).
+cnf(associativity_for_multiplication, axiom, multiply(X, multiply(Y, Z))=multiply(multiply(X, Y), Z)).
+cnf(distribute1, axiom, multiply(X, add(Y, Z))=add(multiply(X, Y), multiply(X, Z))).
+cnf(distribute2, axiom, multiply(add(X, Y), Z)=add(multiply(X, Z), multiply(Y, Z))).
+cnf(x_fourthed_is_x, hypothesis, multiply(X, multiply(X, multiply(X, X)))=X).
+cnf(a_times_b_is_c, negated_conjecture, multiply(a, b)=c).
+cnf(prove_commutativity, negated_conjecture, multiply(b, a)!=c).
diff --git a/examples/ROB010-1.p b/examples/ROB010-1.p
new file mode 100644
--- /dev/null
+++ b/examples/ROB010-1.p
@@ -0,0 +1,11 @@
+cnf(condition,hypothesis,
+    ( negate(add(a,negate(b))) = c )).
+
+cnf(prove_result,negated_conjecture,
+    (  negate(add(c,negate(add(b,a)))) != a )).
+
+cnf(commutativity_of_add,axiom,
+    ( add(X,Y) = add(Y,X) )).
+
+cnf(robbins_axiom,axiom,
+    ( negate(add(negate(add(X,Y)),negate(add(X,negate(Y))))) = X )).
diff --git a/examples/ROB027-1-pretty.p b/examples/ROB027-1-pretty.p
new file mode 100644
--- /dev/null
+++ b/examples/ROB027-1-pretty.p
@@ -0,0 +1,56 @@
+%--------------------------------------------------------------------------
+% File     : ROB027-1 : TPTP v6.3.0. Released v1.2.0.
+% Domain   : Robbins Algebra
+% Problem  : -(-c) = c => Boolean
+% Version  : [Win90] (equality) axioms.
+%            Theorem formulation : Denies Huntington's axiom.
+% English  : If there are elements c and d such that c+d=d, then the
+%            algebra is Boolean.
+
+% Refs     : [HMT71] Henkin et al. (1971), Cylindrical Algebras
+%          : [Win90] Winker (1990), Robbins Algebra: Conditions that make a
+%          : [Wos94] Wos (1994), Two Challenge Problems
+% Source   : [Wos94]
+% Names    : - [Wos94]
+
+% Status   : Open
+% Rating   : 1.00 v2.0.0
+% Syntax   : Number of clauses     :    5 (   0 non-Horn;   5 unit;   2 RR)
+%            Number of atoms       :    5 (   5 equality)
+%            Maximal clause size   :    1 (   1 average)
+%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
+%            Number of functors    :    5 (   3 constant; 0-2 arity)
+%            Number of variables   :    7 (   0 singleton)
+%            Maximal term depth    :    6 (   3 average)
+% SPC      : CNF_UNK_UEQ
+
+% Comments : Commutativity, associativity, and Huntington's axiom
+%            axiomatize Boolean algebra.
+%--------------------------------------------------------------------------
+%----Include axioms for Robbins algebra
+%--------------------------------------------------------------------------
+cnf(commutativity_of_add,axiom,
+    ( '+'(X,Y) = '+'(Y,X) )).
+
+cnf(associativity_of_add,axiom,
+    ( '+'('+'(X,Y),Z) = '+'(X,'+'(Y,Z)) )).
+
+cnf(robbins_axiom,axiom,
+    ( '-'('+'('-'('+'(X,Y)),'-'('+'(X,'-'(Y))))) = X )).
+
+%--------------------------------------------------------------------------
+%--------------------------------------------------------------------------
+cnf(double_negation,hypothesis,
+    ( '-'('-'(c)) = c )).
+
+cnf(prove_huntingtons_axiom,negated_conjecture,
+    '+'('-'('+'(a,'-'(b))),'-'('+'('-'(a),'-'(b)))) != b).
+
+%--------------------------------------------------------------------------
+%----Definition of g
+cnf(sos04,axiom,(
+    g(A) = '-'('+'(A,'-'(A))) )).
+
+%----Definition of h
+cnf(sos05,axiom,(
+    h(A) = '+'(A,'+'(A,'+'(A,'-'('+'(A,'-'(A)))))))).
diff --git a/examples/ROB027-1.p b/examples/ROB027-1.p
new file mode 100644
--- /dev/null
+++ b/examples/ROB027-1.p
@@ -0,0 +1,56 @@
+%--------------------------------------------------------------------------
+% File     : ROB027-1 : TPTP v6.3.0. Released v1.2.0.
+% Domain   : Robbins Algebra
+% Problem  : -(-c) = c => Boolean
+% Version  : [Win90] (equality) axioms.
+%            Theorem formulation : Denies Huntington's axiom.
+% English  : If there are elements c and d such that c+d=d, then the
+%            algebra is Boolean.
+
+% Refs     : [HMT71] Henkin et al. (1971), Cylindrical Algebras
+%          : [Win90] Winker (1990), Robbins Algebra: Conditions that make a
+%          : [Wos94] Wos (1994), Two Challenge Problems
+% Source   : [Wos94]
+% Names    : - [Wos94]
+
+% Status   : Open
+% Rating   : 1.00 v2.0.0
+% Syntax   : Number of clauses     :    5 (   0 non-Horn;   5 unit;   2 RR)
+%            Number of atoms       :    5 (   5 equality)
+%            Maximal clause size   :    1 (   1 average)
+%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
+%            Number of functors    :    5 (   3 constant; 0-2 arity)
+%            Number of variables   :    7 (   0 singleton)
+%            Maximal term depth    :    6 (   3 average)
+% SPC      : CNF_UNK_UEQ
+
+% Comments : Commutativity, associativity, and Huntington's axiom
+%            axiomatize Boolean algebra.
+%--------------------------------------------------------------------------
+%----Include axioms for Robbins algebra
+%--------------------------------------------------------------------------
+cnf(commutativity_of_add,axiom,
+    ( add(X,Y) = add(Y,X) )).
+
+cnf(associativity_of_add,axiom,
+    ( add(add(X,Y),Z) = add(X,add(Y,Z)) )).
+
+cnf(robbins_axiom,axiom,
+    ( negate(add(negate(add(X,Y)),negate(add(X,negate(Y))))) = X )).
+
+%--------------------------------------------------------------------------
+%--------------------------------------------------------------------------
+cnf(double_negation,hypothesis,
+    ( negate(negate(c)) = c )).
+
+cnf(prove_huntingtons_axiom,negated_conjecture,
+    add(negate(add(a,negate(b))),negate(add(negate(a),negate(b)))) != b).
+
+%--------------------------------------------------------------------------
+%----Definition of g
+cnf(sos04,axiom,(
+    g(A) = negate(add(A,negate(A))) )).
+
+%----Definition of h
+cnf(sos05,axiom,(
+    h(A) = add(A,add(A,add(A,negate(add(A,negate(A)))))))).
diff --git a/examples/ROB033-1.p b/examples/ROB033-1.p
new file mode 100644
--- /dev/null
+++ b/examples/ROB033-1.p
@@ -0,0 +1,10 @@
+cnf(commutativity_of_add, axiom, add(X, Y)=add(Y, X)).
+cnf(associativity_of_add, axiom,
+    add(add(X, Y), Z)=add(X, add(Y, Z))).
+cnf(robbins_axiom, axiom,
+    negate(add(negate(add(X, Y)), negate(add(X, negate(Y)))))=X).
+cnf(sos04, axiom, g(A)=negate(add(A, negate(A)))).
+cnf(sos05, axiom, h(A)=add(A, add(A, add(A, g(A))))).
+cnf(goals, negated_conjecture,
+    add(negate(add(x0, negate(x1))),
+        negate(add(negate(x0), negate(x1))))!=x1).
diff --git a/examples/aim.p b/examples/aim.p
new file mode 100644
--- /dev/null
+++ b/examples/aim.p
@@ -0,0 +1,54 @@
+cnf(left_ident, axiom,
+  '1' * X = X).
+cnf(right_ident, axiom,
+  X * '1' = X).
+cnf(left_division_1, axiom,
+  X \ (X * Y) = Y).
+cnf(left_division_2, axiom,
+  X * (X \ Y) = Y).
+cnf(right_division_1, axiom,
+  (X * Y) / Y = X).
+cnf(right_division_2, axiom,
+  (X / Y) * Y = X).
+cnf(associator, axiom,
+  (X * (Y * Z)) \ ((X * Y) * Z) = a(X,Y,Z)).
+cnf(commutator, axiom,
+  (X * Y) \ (Y * X) = k(Y,X)).
+cnf(l, axiom,
+  (Y * X) \ (Y * (X * U)) = l(U,X,Y)).
+cnf(r, axiom,
+  ((U * X) * Y) / (X * Y) = r(U,X,Y)).
+cnf(t, axiom,
+  X \ (U * X) = t(U,X)).
+cnf(abelian_inner_mapping_1, axiom,
+  t(t(U,X),Y) = t(t(U,Y),X)).
+cnf(abelian_inner_mapping_2, axiom,
+  t(l(U,X,Y),Z) = l(t(U,Z),X,Y)).
+cnf(abelian_inner_mapping_3, axiom,
+  t(r(U,X,Y),Z) = r(t(U,Z),X,Y)).
+cnf(abelian_inner_mapping_4, axiom,
+  l(r(U,X,Y),Z,W) = r(l(U,Z,W),X,Y)).
+cnf(abelian_inner_mapping_5, axiom,
+  l(l(U,X,Y),Z,W) = l(l(U,Z,W),X,Y)).
+cnf(abelian_inner_mapping_6, axiom,
+  r(r(U,X,Y),Z,W) = r(r(U,Z,W),X,Y)).
+
+% aK (or "single-a") goals
+cnf(ka, conjecture,
+  k(a(x,y,z),u) = '1').
+cnf(aK1, conjecture,
+  a(k(x,y),z,u) = '1').
+cnf(aK2, conjecture,
+  a(x,k(y,z),u) = '1').
+cnf(aK3, conjecture,
+  a(x,y,k(z,u)) = '1').
+
+% aa (or "double-a") goals
+cnf(aa1, conjecture,
+  a(a(x,y,z),u,w) = '1').
+cnf(aa2, conjecture,
+  a(x,a(y,z,u),w) = '1').
+cnf(aa3, conjecture,
+  a(x,y,a(z,u,w)) = '1').
+
+cnf(bonus, axiom, (X * (Y / X)) \ X = Y \ (Y / (Y / X))).
diff --git a/examples/append-rev.p b/examples/append-rev.p
new file mode 100644
--- /dev/null
+++ b/examples/append-rev.p
@@ -0,0 +1,4 @@
+cnf(rev_rev, axiom, rev(rev(X)) = X).
+cnf(app_assoc, axiom, X ++ (Y ++ Z) = (X ++ Y) ++ Z).
+cnf(rev_app, axiom, rev(X) ++ rev(Y) = rev(Y ++ X)).
+fof(conjecture, conjecture, ![A,B]: A ++ rev(B) = rev(B ++ rev(A))).
diff --git a/examples/cm.p b/examples/cm.p
new file mode 100644
--- /dev/null
+++ b/examples/cm.p
@@ -0,0 +1,3 @@
+fof(a, axiom, ![X, Y]: plus(X, Y)=plus(Y, X)).
+fof(a, axiom, ![X, Y, Z]: plus(plus(X, Y), Z)=plus(X, plus(Z, Y))).
+fof(a, axiom, a!=b).
diff --git a/examples/deriv.p b/examples/deriv.p
new file mode 100644
--- /dev/null
+++ b/examples/deriv.p
@@ -0,0 +1,37 @@
+% Axioms about arithmetic.
+
+cnf('commutativity of +', axiom,
+    X + Y = Y + X).
+cnf('associativity of +', axiom,
+    X + (Y + Z) = (X + Y) + Z).
+cnf('commutativity of *', axiom,
+    X * Y = Y * X).
+cnf('associativity of *', axiom,
+    X * (Y * Z) = (X * Y) * Z).
+cnf('plus 0', axiom,
+    '0' + X = X).
+cnf('times 0', axiom,
+    '0' * X = '0').
+cnf('times 1', axiom,
+    '1' * X = X).
+cnf('distributivity', axiom,
+    X * (Y + Z) = (X * Y) + (X * Z)).
+cnf('minus', axiom,
+    X + -X = '0').
+cnf('derivative of 0', axiom,
+    d('0') = '0').
+cnf('derivative of 1', axiom,
+    d('1') = '0').
+cnf('derivative of x', axiom,
+    d(x) = '1').
+cnf('derivative of +', axiom,
+    d(T+U) = d(T) + d(U)).
+cnf('derivative of *', axiom,
+    d(T*U) = (T*d(U)) + (U*d(T))).
+cnf('derivative of sin', axiom,
+    d(sin(T)) = cos(T) * d(T)).
+cnf('derivative of cos', axiom,
+    d(cos(T)) = -(sin(T)*d(T))).
+
+fof(goal, conjecture,
+    ?[T]: d(T) = x*cos(x)).
diff --git a/examples/diff.p b/examples/diff.p
new file mode 100644
--- /dev/null
+++ b/examples/diff.p
@@ -0,0 +1,8 @@
+cnf('x\\(y\\x)=x', axiom,
+    X \ (Y \ X) = X).
+cnf('x\\(x\\y)=y\\(y\\x)', axiom,
+    X \ (X \ Y) = Y \ (Y \ X)).
+cnf('(x\\y)\\z=(x\\z)\\(y\\z)', axiom,
+    (X \ Y) \ Z = (X \ Z) \ (Y \ Z)).
+cnf(conjecture, conjecture,
+    (a \ c) \ b = (a \ b) \ c).
diff --git a/examples/diff2.p b/examples/diff2.p
new file mode 100644
--- /dev/null
+++ b/examples/diff2.p
@@ -0,0 +1,34 @@
+cnf('x\\(y\\x)=x', axiom,
+    X \ (Y \ X) = X).
+cnf('x\\(x\\y)=y\\(y\\x)', axiom,
+    X \ (X \ Y) = Y \ (Y \ X)).
+cnf('(x\\y)\\z=(x\\z)\\(y\\z)', axiom,
+    (X \ Y) \ Z = (X \ Z) \ (Y \ Z)).
+
+cnf(empty, axiom,
+    X \ empty = X).
+
+cnf(equals, conjecture,
+    (X \ Y = empty & Y \ X = empty) => X = Y).
+
+cnf(union, axiom,
+    X \ union(Y, Z) = (X \ Y) \ Z).
+
+cnf(union, conjecture,
+    union(a,b) = union(b,a)).
+cnf(union, conjecture,
+    union(a,a) = a).
+cnf(union, conjecture,
+    union(a,union(b,c)) = union(union(a,b),c)).
+
+cnf(intersection, axiom,
+    intersection(X, Y) = X \ (X \ Y)).
+
+cnf(intersection, conjecture,
+    intersection(a,b) = intersection(b,a)).
+cnf(intersection, conjecture,
+    intersection(a,a) = a).
+cnf(intersection, conjecture,
+    intersection(a,intersection(b,c)) = intersection(intersection(a,b),c)).
+cnf(intersection, conjecture,
+    intersection(X, Y) = union(X,Y) \ union(X \ Y, Y \ X)).
diff --git a/examples/distributive_groupoid.p b/examples/distributive_groupoid.p
new file mode 100644
--- /dev/null
+++ b/examples/distributive_groupoid.p
@@ -0,0 +1,12 @@
+% Mitschke, "Every distributive groupoid is trimedial".
+% Twee's proof of this is much uglier than the paper's proof.
+
+cnf(distributivity, axiom,
+    X . (Y . Z) = (X . Y) . (X . Z)).
+cnf(distributivity, axiom,
+    (X . Y) . Z = (X . Z) . (Y . Z)).
+fof(conjecture, conjecture,
+    (a . b) . (c . a) = (a . c) . (b . a)). 
+
+%fof(lemma6, conjecture, ![X, Y, Z]: ((X . Y) . (Z . X)) . ((X . Z) . (Y . X)) = (X . Y) . (Z . X)).
+
diff --git a/examples/factor.p b/examples/factor.p
new file mode 100644
--- /dev/null
+++ b/examples/factor.p
@@ -0,0 +1,44 @@
+% Axioms about arithmetic.
+
+cnf('commutativity_of_plus', axiom,
+    X + Y = Y + X).
+cnf('associativity_of_plus', axiom,
+    X + (Y + Z) = (X + Y) + Z).
+cnf('commutativity_of_times', axiom,
+    X * Y = Y * X).
+cnf('associativity_of_times', axiom,
+    X * (Y * Z) = (X * Y) * Z).
+cnf('plus_zero', axiom,
+    '0' + X = X).
+cnf('times_zero', axiom,
+    '0' * X = '0').
+cnf('times_one', axiom,
+    '1' * X = X).
+cnf('distributivity', axiom,
+    X * (Y + Z) = (X * Y) + (X * Z)).
+cnf('minus', axiom,
+    X + -X = '0').
+
+cnf(two, axiom, two = '1'+'1').
+cnf(three, axiom, three = '1'+two).
+cnf(four, axiom, four = '1'+three).
+cnf(five, axiom, five = '1'+four).
+cnf(six, axiom, six = '1'+five).
+cnf(seven, axiom, seven = '1'+six).
+cnf(eight, axiom, eight = '1'+seven).
+cnf(nine, axiom, nine = '1'+eight).
+cnf(minus_six, axiom, minus_four = -four).
+cnf(minus_six, axiom, minus_six = -six).
+
+fof(factoring, conjecture,
+    ?[A,B,C]: ![X]:
+      (X*(X*X)) + ((minus_six*(X*X)) + ((nine*X) + minus_four)) = ((X +
+      -'1')*((X + -'1') * (X + -four)))).
+
+fof(factoring, conjecture,
+    ?[A,B,C]: ![X]:
+    (X*(X*X)) +
+    (-(('1'+('1'+('1'+('1'+('1'+'1')))))*(X*X)) +
+     ((('1'+('1'+('1'+('1'+('1'+('1'+('1'+('1'+'1'))))))))*X) +
+     -('1'+('1'+('1'+'1'))))) =
+    (X + -A)*((X + -B)*(X + -C))).
diff --git a/examples/filter.p b/examples/filter.p
new file mode 100644
--- /dev/null
+++ b/examples/filter.p
@@ -0,0 +1,59 @@
+fof('associativity of ∘', axiom,
+    ![F, G, H]:
+    F ∘ (G ∘ H) = (F ∘ G) ∘ H).
+
+fof('∘ identity', axiom,
+    ![F]:
+    id ∘ F = F).
+
+fof('∘ identity', axiom,
+    ![F]:
+    F ∘ id = F).
+
+fof('map functor', axiom,
+    ![F, G]:
+    map(F) ∘ map(G) = map(F ∘ G)).
+
+fof('map functor', axiom,
+    map(id) = id).
+
+fof('naturality of concat', axiom,
+    ![F]:
+    map(F) ∘ concat = concat ∘ map(map(F))).
+
+fof('defn filter', axiom,
+    ![P]:
+    filter(P) = concat ∘ map(test(P))).
+
+% test(P) = \x -> if P(x) then [x] else []
+
+%fof('test property', axiom,
+%    ![P, F]:
+%    test(P) ∘ F =
+%    map(F) ∘ test(P ∘ F)).
+
+fof('map/filter', conjecture,
+    ![P, F]:
+    filter(P) ∘ map(F) = map(F) ∘ filter(P ∘ F)).
+
+
+% cond(P, F, G) = \x -> if P(x) then F(x) else G(x)
+
+fof('test defn', axiom,
+    ![P]:
+    test(P) = cond(P, unit, nil)).
+fof('cond ∘', axiom,
+    ![F, P, G, H]:
+    F ∘ cond(P, G, H) = cond(P, F ∘ G, F ∘ H)).
+fof('cond ∘', axiom,
+    ![F, P, G, H]:
+    cond(P, G, H) ∘ F = cond(P ∘ F, G ∘ F, H ∘ F)).
+fof('nil', axiom,
+    ![F]:
+    nil ∘ F = nil).
+fof('nil', axiom,
+    ![F]:
+    map(F) ∘ nil = nil).
+fof('unit', axiom,
+    ![F]:
+    map(F) ∘ unit = unit ∘ F).
diff --git a/examples/gmv.p b/examples/gmv.p
new file mode 100644
--- /dev/null
+++ b/examples/gmv.p
@@ -0,0 +1,74 @@
+cnf('Associativity-∧', axiom,
+    (X ∧ Y) ∧ Z = X ∧ (Y ∧ Z)).   
+cnf('Associativity-∨', axiom,
+    (X ∨ Y) ∨ Z = X ∨ (Y ∨ Z)).
+cnf('Idempotence-∧', axiom,
+    X ∧ X = X).
+cnf('Idempotence-∨', axiom,
+    X ∨ X = X).
+cnf('Commutativity-∧', axiom,
+    X ∧ Y = Y ∧ X).
+cnf('Commutativity-∨', axiom,
+    X ∨ Y = Y ∨ X).
+cnf('Absorption a', axiom,
+    (X ∧ Y) ∨ X = X).
+cnf('Absorption b', axiom,
+    (X ∨ Y) ∧ X = X).
+
+cnf('Residual a', axiom,
+    (X * ((X \ Z) ∧ Y)) ∨ Z = Z).
+cnf('Residual b', axiom,
+    ((Y ∧ (Z / X)) * X) ∨ Z = Z).
+cnf('Residual c', axiom,
+    (X \ ((X * Y) ∨ Z)) ∧ Y = Y).
+cnf('Residual d', axiom,
+    (((Y * X) ∨ Z) / X) ∧ Y = Y).
+
+cnf('Associativity-* (fusion)', axiom,
+    (X * Y) * Z = X * (Y * Z)).
+cnf('Left monoid unit', axiom,
+    '1' * X = X).
+cnf('Right monoid unit', axiom,
+    X * '1' = X).
+
+cnf('GMV a', axiom,
+    X ∨ Y = X / ((X ∨ Y) \ X)).
+cnf('GMV b', axiom,
+    X ∨ Y = (X / (X ∨ Y)) \ X).
+
+cnf('Definition-@', axiom,
+    X @ Y = (X * (X \ '1')) * ((Y \ '1') \ '1')).
+
+cnf('Goal 1', conjecture,
+    x @ x = x).
+cnf('Goal 2', conjecture,
+    (x @ y) @ z = x @ z).
+cnf('Goal 3', conjecture,
+    x @ (y @ z) = x @ z).
+  
+cnf('Goal 4', conjecture,
+    (x ∧ y) @ (z ∧ u) = (x @ z) ∧ (y @ u)).
+cnf('Goal 5', conjecture,
+    (x ∨ y) @ (z ∨ u) = (x @ z) ∨ (y @ u)).
+cnf('Goal 6', conjecture,
+    (x \ y) @ (z \ u) = (x @ z) \ (y @ u)).
+cnf('Goal 7', conjecture,
+    (x / y) @ (z / u) = (x @ z) / (y @ u)).
+  
+cnf('Goal 8', conjecture,
+    (x * (x \ '1')) @ '1' = x * (x \ '1')).
+cnf('Goal 9', conjecture,
+    '1' @ (x * (x \ '1')) = '1').
+cnf('Goal 10', conjecture,
+    (x \ '1') @ '1' = '1').
+cnf('Goal 11', conjecture,
+    '1' @ (x \ '1') = x \ '1').
+  
+cnf('Goal 12', conjecture,
+    (x / (y \ x)) @ (x ∨ y) = x ∨ y).
+cnf('Goal 13', conjecture,
+    ((x / y) \ x) @ (x ∨ y) = x ∨ y).
+cnf('Goal 14', conjecture,
+    (x ∨ y) @ (x / (y \ x)) = x / (y \ x)).
+cnf('Goal 15', conjecture,
+    (x ∨ y) @ ((x / y) \ x) = (x / y) \ x).
diff --git a/examples/group.p b/examples/group.p
new file mode 100644
--- /dev/null
+++ b/examples/group.p
@@ -0,0 +1,14 @@
+cnf(associativity, axiom,
+    X + (Y + Z) = (X + Y) + Z).
+cnf(plus_zero, axiom,
+    '0' + X = X).
+cnf(plus_zero, axiom,
+    X + '0' = X).
+cnf(minus_left, axiom,
+    (-X) + X = '0').
+cnf(minus_right, axiom,
+    X + (-X) = '0').
+cnf(assumption, assumption,
+    a + b = a).
+cnf(goal, conjecture,
+    b = '0').
diff --git a/examples/haken.p b/examples/haken.p
new file mode 100644
--- /dev/null
+++ b/examples/haken.p
@@ -0,0 +1,170 @@
+cnf(a, conjecture, a1 = a2 & a2 = a3 & a3 = a4 & a4 = a5 & a5 = a6 &
+a6 = a7 & a7 = a8 & a8 = a9 & a9 = a10 & a10 = a11 & a11 = a12 & a12 =
+a13 & a13 = a14 & a14 = a15 & a15 = a16 & a16 = a17 & a17 = a18 & a18
+= a19 & a19 = a20 & a20 = a21 & a20 = a22 & a21 = a23 & a23 = a24 &
+a24 = a25 & a25 = a26 & a26 = a27 & a27 = a28 & a28 = a29 & a29 = a30
+& a30 = a31 & a31 = a32 & a32 = a33 & a33 = a34 & a34 = a35 & a35 =
+a36 & a36 = a37 & a37 = a38 & a38 = a39 & a39 = a40 & a40 = a41 & a41
+= a42 & a42 = a43 & a43 = a44 & a44 = a45 & a45 = a46 & a46 = a47 &
+a47 = a48 & a48 = a49 & a49 = a50 & a50 = a51 & a51 = a52 & a52 = a53
+& a53 = a54 & a54 = a55 & a55 = a56 & a56 = a57 & a57 = a58 & a58 =
+a59 & a59 = a60 & a60 = a61 & a61 = a62 & a62 = a63 & a63 = a64 & a64
+= a65 & a65 = a66 & a66 = a67 & a67 = a68 & a68 = a69 & a69 = a70 &
+a70 = a71 & a71 = a72 & a72 = a73 & a73 = a74 & a74 = a75 & a75 = a76
+& a76 = a77 & a77 = a78 & a78 = a79 & a79 = a80 & a80 = a81 & a81 =
+a82 & a82 = a83 & a83 = a84 & a84 = a85 & a85 = a86 & a86 = a87 & a87
+= a88 & a88 = a89 & a89 = a90 & a90 = a91 & a91 = a92 & a92 = a93 &
+a93 = a94 & a94 = a95 & a95 = a96 & a96 = a97 & a97 = a98 & a98 = a99
+& a99 = a100 & a100 = a101 & a101 = a102 & a102 = a103 & a103 = a104 &
+a104 = a105 & a105 = a106 & a106 = a107 & a107 = a108 & a108 = a109 &
+a109 = a110 & a110 = a111 & a111 = a112 & a112 = a113 & a113 = a114 &
+a114 = a115 & a115 = a116 & a116 = a117 & a117 = a118 & a118 = a119 &
+a119 = a120 & a120 = a121 & a121 = a122 & a122 = a123 & a123 = a124 &
+a124 = a125 & a125 = a126 & a126 = a127 & a127 = a128 & a128 = a129 &
+a129 = a130 & a130 = a131 & a131 = a132 & a132 = a133 & a133 = a134 &
+a134 = a135 & a135 = a136 & a136 = a137 & a137 = a138 & a138 = a139 &
+a139 = a140 & a140 = a141).
+cnf(a, axiom, '*'(X, X) = X).
+cnf(a, axiom, '*'('*'(X,Y),Y) = X).
+cnf(a, axiom, '*'('*'(X,Y),Z) = '*'('*'(X, Z), '*'(Y, Z))).
+cnf(a, axiom, a2 = '*'(a1, a42)).
+cnf(a, axiom, a3 = '*'(a2, a41)).
+cnf(a, axiom, a4 = '*'(a3, a14)).
+cnf(a, axiom, a5 = '*'(a4, a39)).
+cnf(a, axiom, a6 = '*'(a5, a136)).
+cnf(a, axiom, a7 = '*'(a6, a52)).
+cnf(a, axiom, a8 = '*'(a7, a17)).
+cnf(a, axiom, a9 = '*'(a8, a56)).
+cnf(a, axiom, a10 = '*'(a9, a134)).
+cnf(a, axiom, a11 = '*'(a10, a37)).
+cnf(a, axiom, a12 = '*'(a11, a21)).
+cnf(a, axiom, a13 = '*'(a12, a23)).
+cnf(a, axiom, a14 = '*'(a13, a32)).
+cnf(a, axiom, a15 = '*'(a14, a53)).
+cnf(a, axiom, a16 = '*'(a15, a136)).
+cnf(a, axiom, a17 = '*'(a16, a29)).
+cnf(a, axiom, a18 = '*'(a17, a133)).
+cnf(a, axiom, a19 = '*'(a18, a58)).
+cnf(a, axiom, a20 = '*'(a19, a26)).
+cnf(a, axiom, a21 = '*'(a20, a35)).
+cnf(a, axiom, a22 = '*'(a21, a141)).
+cnf(a, axiom, a23 = '*'(a22, a45)).
+cnf(a, axiom, a24 = '*'(a23, a35)).
+cnf(a, axiom, a25 = '*'(a24, a49)).
+cnf(a, axiom, a26 = '*'(a25, a138)).
+cnf(a, axiom, a27 = '*'(a26, a8)).
+cnf(a, axiom, a28 = '*'(a27, a37)).
+cnf(a, axiom, a29 = '*'(a28, a17)).
+cnf(a, axiom, a30 = '*'(a29, a14)).
+cnf(a, axiom, a31 = '*'(a30, a5)).
+cnf(a, axiom, a32 = '*'(a31, a39)).
+cnf(a, axiom, a33 = '*'(a32, a13)).
+cnf(a, axiom, a34 = '*'(a33, a131)).
+cnf(a, axiom, a35 = '*'(a34, a60)).
+cnf(a, axiom, a36 = '*'(a35, a139)).
+cnf(a, axiom, a37 = '*'(a36, a47)).
+cnf(a, axiom, a38 = '*'(a37, a17)).
+cnf(a, axiom, a39 = '*'(a38, a7)).
+cnf(a, axiom, a40 = '*'(a39, a4)).
+cnf(a, axiom, a41 = '*'(a40, a14)).
+cnf(a, axiom, a42 = '*'(a41, a2)).
+cnf(a, axiom, a43 = '*'(a42, a62)).
+cnf(a, axiom, a44 = '*'(a43, a128)).
+cnf(a, axiom, a45 = '*'(a44, a23)).
+cnf(a, axiom, a46 = '*'(a45, a141)).
+cnf(a, axiom, a47 = '*'(a46, a11)).
+cnf(a, axiom, a48 = '*'(a47, a20)).
+cnf(a, axiom, a49 = '*'(a48, a138)).
+cnf(a, axiom, a50 = '*'(a49, a131)).
+cnf(a, axiom, a51 = '*'(a50, a59)).
+cnf(a, axiom, a52 = '*'(a51, a39)).
+cnf(a, axiom, a53 = '*'(a52, a136)).
+cnf(a, axiom, a54 = '*'(a53, a29)).
+cnf(a, axiom, a55 = '*'(a54, a135)).
+cnf(a, axiom, a56 = '*'(a55, a37)).
+cnf(a, axiom, a57 = '*'(a56, a134)).
+cnf(a, axiom, a58 = '*'(a57, a26)).
+cnf(a, axiom, a59 = '*'(a58, a138)).
+cnf(a, axiom, a60 = '*'(a59, a131)).
+cnf(a, axiom, a61 = '*'(a60, a13)).
+cnf(a, axiom, a62 = '*'(a61, a1)).
+cnf(a, axiom, a63 = '*'(a62, a96)).
+cnf(a, axiom, a64 = '*'(a63, a127)).
+cnf(a, axiom, a65 = '*'(a64, a41)).
+cnf(a, axiom, a66 = '*'(a65, a2)).
+cnf(a, axiom, a67 = '*'(a66, a92)).
+cnf(a, axiom, a68 = '*'(a67, a98)).
+cnf(a, axiom, a69 = '*'(a68, a32)).
+cnf(a, axiom, a70 = '*'(a69, a13)).
+cnf(a, axiom, a71 = '*'(a70, a118)).
+cnf(a, axiom, a72 = '*'(a71, a109)).
+cnf(a, axiom, a73 = '*'(a72, a82)).
+cnf(a, axiom, a74 = '*'(a73, a32)).
+cnf(a, axiom, a75 = '*'(a74, a14)).
+cnf(a, axiom, a76 = '*'(a75, a68)).
+cnf(a, axiom, a77 = '*'(a76, a114)).
+cnf(a, axiom, a78 = '*'(a77, a13)).
+cnf(a, axiom, a79 = '*'(a78, a33)).
+cnf(a, axiom, a80 = '*'(a79, a119)).
+cnf(a, axiom, a81 = '*'(a80, a70)).
+cnf(a, axiom, a82 = '*'(a81, a109)).
+cnf(a, axiom, a83 = '*'(a82, a118)).
+cnf(a, axiom, a84 = '*'(a83, a39)).
+cnf(a, axiom, a85 = '*'(a84, a5)).
+cnf(a, axiom, a86 = '*'(a85, a30)).
+cnf(a, axiom, a87 = '*'(a86, a104)).
+cnf(a, axiom, a88 = '*'(a87, a4)).
+cnf(a, axiom, a89 = '*'(a88, a14)).
+cnf(a, axiom, a90 = '*'(a89, a41)).
+cnf(a, axiom, a91 = '*'(a90, a100)).
+cnf(a, axiom, a92 = '*'(a91, a124)).
+cnf(a, axiom, a93 = '*'(a92, a2)).
+cnf(a, axiom, a94 = '*'(a93, a41)).
+cnf(a, axiom, a95 = '*'(a94, a127)).
+cnf(a, axiom, a96 = '*'(a95, a64)).
+cnf(a, axiom, a97 = '*'(a96, a42)).
+cnf(a, axiom, a98 = '*'(a97, a1)).
+cnf(a, axiom, a99 = '*'(a98, a92)).
+cnf(a, axiom, a100 = '*'(a99, a124)).
+cnf(a, axiom, a101 = '*'(a100, a14)).
+cnf(a, axiom, a102 = '*'(a101, a40)).
+cnf(a, axiom, a103 = '*'(a102, a4)).
+cnf(a, axiom, a104 = '*'(a103, a87)).
+cnf(a, axiom, a105 = '*'(a104, a30)).
+cnf(a, axiom, a106 = '*'(a105, a5)).
+cnf(a, axiom, a107 = '*'(a106, a84)).
+cnf(a, axiom, a108 = '*'(a107, a39)).
+cnf(a, axiom, a109 = '*'(a108, a118)).
+cnf(a, axiom, a110 = '*'(a109, a70)).
+cnf(a, axiom, a111 = '*'(a110, a119)).
+cnf(a, axiom, a112 = '*'(a111, a79)).
+cnf(a, axiom, a113 = '*'(a112, a33)).
+cnf(a, axiom, a114 = '*'(a113, a13)).
+cnf(a, axiom, a115 = '*'(a114, a68)).
+cnf(a, axiom, a116 = '*'(a115, a14)).
+cnf(a, axiom, a117 = '*'(a116, a74)).
+cnf(a, axiom, a118 = '*'(a117, a32)).
+cnf(a, axiom, a119 = '*'(a118, a70)).
+cnf(a, axiom, a120 = '*'(a119, a13)).
+cnf(a, axiom, a121 = '*'(a120, a32)).
+cnf(a, axiom, a122 = '*'(a121, a68)).
+cnf(a, axiom, a123 = '*'(a122, a115)).
+cnf(a, axiom, a124 = '*'(a123, a75)).
+cnf(a, axiom, a125 = '*'(a124, a2)).
+cnf(a, axiom, a126 = '*'(a125, a65)).
+cnf(a, axiom, a127 = '*'(a126, a41)).
+cnf(a, axiom, a128 = '*'(a127, a96)).
+cnf(a, axiom, a129 = '*'(a128, a62)).
+cnf(a, axiom, a130 = '*'(a129, a1)).
+cnf(a, axiom, a131 = '*'(a130, a13)).
+cnf(a, axiom, a132 = '*'(a131, a138)).
+cnf(a, axiom, a133 = '*'(a132, a58)).
+cnf(a, axiom, a134 = '*'(a133, a26)).
+cnf(a, axiom, a135 = '*'(a134, a37)).
+cnf(a, axiom, a136 = '*'(a135, a29)).
+cnf(a, axiom, a137 = '*'(a136, a39)).
+cnf(a, axiom, a138 = '*'(a137, a51)).
+cnf(a, axiom, a139 = '*'(a138, a20)).
+cnf(a, axiom, a140 = '*'(a139, a47)).
+cnf(a, axiom, a141 = '*'(a140, a11)).
+cnf(a, axiom, a1 = '*'(a141, a23)).
diff --git a/examples/loop.p b/examples/loop.p
new file mode 100644
--- /dev/null
+++ b/examples/loop.p
@@ -0,0 +1,6 @@
+cnf(mult_ld, axiom, X * (X \ Y) = Y).
+cnf(ld_mult, axiom, X \ (X * Y) = Y).
+cnf(mult_rd, axiom, (X / Y) * Y = X).
+cnf(rd_mult, axiom, (X * Y) / Y = X).
+cnf(moufang, axiom, X * (Y * (X * Z)) = ((X * Y) * X) * Z).
+cnf(conjecture, conjecture, a \ a = a / a).
diff --git a/examples/loop2.p b/examples/loop2.p
new file mode 100644
--- /dev/null
+++ b/examples/loop2.p
@@ -0,0 +1,6 @@
+cnf('*-\\', axiom, X * (X \ Y) = Y).
+cnf('\\-*', axiom, X \ (X * Y) = Y).
+cnf('*-/', axiom, (X / Y) * Y = X).
+cnf('/-*', axiom, (X * Y) / Y = X).
+cnf(moufang, axiom, X * (Y * (X * Z)) = ((X * Y) * X) * Z).
+cnf(conjecture, conjecture, a * (b / b) = a).
diff --git a/examples/lukasiewicz.p b/examples/lukasiewicz.p
new file mode 100644
--- /dev/null
+++ b/examples/lukasiewicz.p
@@ -0,0 +1,6 @@
+cnf(imp_true, axiom, implies(true, X) = X).
+cnf(imp_compose, axiom, implies(implies(X, Y), implies(implies(Y, Z), implies(X, Z))) = true).
+cnf(imp_not, axiom, implies(implies(not(X), not(Y)), implies(Y, X)) = true).
+cnf(imp_switch, axiom, implies(implies(X, Y), Y) = implies(implies(Y, X), X)).
+cnf(or_def, axiom, or(X, Y) = implies(not(X), Y)).
+cnf(conjecture, negated_conjecture, or(a,or(b,c)) != or(or(a,b),c)).
diff --git a/examples/minus.p b/examples/minus.p
new file mode 100644
--- /dev/null
+++ b/examples/minus.p
@@ -0,0 +1,10 @@
+cnf(plus_zero, axiom,
+    '0' + X = X).
+cnf(plus_zero, axiom,
+    X + '0' = X).
+cnf(minus_minus, axiom,
+    - -X = X).
+cnf(minus_plus, axiom,
+    -(X + Y) = -X + -Y).
+cnf(goal, conjecture,
+    -'0' = '0').
diff --git a/examples/nicomachus.p b/examples/nicomachus.p
new file mode 100644
--- /dev/null
+++ b/examples/nicomachus.p
@@ -0,0 +1,36 @@
+cnf(plus_comm, axiom,
+    X + Y = Y + X).
+cnf(plus_assoc, axiom,
+    X + (Y + Z) = (X + Y) + Z).
+cnf(times_comm, axiom,
+    X * Y = Y * X).
+cnf(times_assoc, axiom,
+    X * (Y * Z) = (X * Y) * Z).
+cnf(plus_zero, axiom,
+    X + zero = X).
+cnf(times_zero, axiom,
+    X * zero = zero).
+cnf(times_one, axiom,
+    X * one = X).
+cnf(distr, axiom,
+    X * (Y + Z) = (X * Y) + (X * Z)).
+cnf(distr, axiom,
+    (X + Y) * Z = (X * Z) + (Y * Z)).
+cnf(plus_s, axiom,
+    s(X) + Y = s(X+Y)).
+cnf(times_s, axiom,
+    s(X)*Y = Y + (X*Y)).
+cnf(sum_zero, axiom,
+    sum(zero) = zero).
+cnf(sum_s, axiom,
+    sum(s(N)) = s(N) + sum(N)).
+cnf(cubes_zero, axiom,
+    cubes(zero) = zero).
+cnf(cubes_s, axiom,
+    cubes(s(N)) = (s(N) * (s(N) * s(N))) + cubes(N)).
+cnf(plus_sum, axiom,
+    sum(N) + sum(N) = N * s(N)).
+cnf(ih, axiom,
+    sum(a) * sum(a) = cubes(a)).
+cnf(conjecture, conjecture,
+    sum(s(a)) * sum(s(a)) = cubes(s(a))).
diff --git a/examples/regexp.p b/examples/regexp.p
new file mode 100644
--- /dev/null
+++ b/examples/regexp.p
@@ -0,0 +1,54 @@
+%% and, or
+cnf(def, axiom, and(true,B) = B).
+cnf(def, axiom, and(false,B) = false).
+cnf(def, axiom, and(X,Y) = and(Y,X)).
+
+cnf(def, axiom, or(true,B) = true).
+cnf(def, axiom, or(false,B) = B).
+cnf(def, axiom, or(X,Y) = or(Y,X)).
+
+%% eq
+cnf(def, axiom, eq(X,X) = true).
+cnf(def, axiom, eq(X,Y) = eq(Y,X)).
+cnf(def, axiom, eq(a,b) = false).
+cnf(def, axiom, eq(a,c) = false).
+cnf(def, axiom, eq(b,c) = false).
+
+%% haseps
+cnf(def, axiom, haseps(atom(A)) = false).
+cnf(def, axiom, haseps(zero) = false).
+cnf(def, axiom, haseps(eps) = true).
+cnf(def, axiom, haseps(plus(P,Q)) = or(haseps(P),haseps(Q))).
+cnf(def, axiom, haseps(seq(P,Q)) = and(haseps(P),haseps(Q))).
+cnf(def, axiom, haseps(star(P)) = true).
+
+%% step
+cnf(def, axiom, step(atom(A),A) = eps).
+cnf(def, axiom, eq(A,B) = false => step(atom(A),B) = zero).
+cnf(def, axiom, step(zero,B) = zero).
+cnf(def, axiom, step(eps,B) = zero).
+cnf(def, axiom, step(plus(P,Q),B) = plus(step(P,B),step(Q,B))).
+cnf(def, axiom, haseps(P) = true => step(seq(P,Q),B) = plus(seq(step(P,B),Q),step(Q,B))).
+cnf(def, axiom, haseps(P) = false => step(seq(P,Q),B) = plus(seq(step(P,B),Q),zero)).
+cnf(def, axiom, step(star(P),B) = seq(step(P,B),star(P))).
+
+%% rec
+cnf(def, axiom, rec(P,nil) = haseps(P)).
+cnf(def, axiom, rec(P,cons(A,As)) = rec(step(P,A),As)).
+
+%% question
+cnf(hypothesis, axiom, rec(seq(P,Q), As) = rec(seq(Q,P), As)).
+cnf(goal, axiom, true != false).
+
+%cnf(a, axiom, atom(A) != zero & atom(A) != eps & atom(A) != plus(P, Q) & atom(A) != seq(P, Q) & atom(A) != star(P)).
+%cnf(a, axiom, zero != eps & zero != plus(P, Q) & zero != seq(P, Q) & zero != star(P)).
+%cnf(a, axiom, eps != plus(P, Q) & eps != seq(P, Q) & eps != star(P)).
+%cnf(a, axiom, plus(P, Q) != seq(P, Q) & plus(P, Q) != star(P)).
+%cnf(a, axiom, seq(P, Q) != star(P)).
+%cnf(a, axiom, un_atom(atom(A)) = A).
+%cnf(a, axiom, un_plus_1(plus(P, Q)) = P).
+%cnf(a, axiom, un_plus_2(plus(P, Q)) = Q).
+%cnf(a, axiom, un_seq_1(seq(P, Q)) = P).
+%cnf(a, axiom, un_seq_2(seq(P, Q)) = Q).
+%cnf(a, axiom, un_star(star(P)) = P).
+%cnf(a, axiom, a != b & b != c & a != c).
diff --git a/examples/rel.p b/examples/rel.p
new file mode 100644
--- /dev/null
+++ b/examples/rel.p
@@ -0,0 +1,32 @@
+tff(type, type, '_⁻¹' : $i > $i).
+tff(type, type, '_⁻' : $i > $i).
+
+cnf('commutativity of ∨', axiom,
+    A ∨ B = B ∨ A).
+cnf('associativity of ∨', axiom,
+    A ∨ (B ∨ C) = (A ∨ B) ∨ C).
+cnf('a kind of de Morgan', axiom,
+    (A⁻ ∨ B⁻)⁻ ∨ (A⁻ ∨ B)⁻ = A).
+cnf('definition of ∧', axiom,
+    A ∧ B = (A⁻ ∨ B⁻)⁻).
+cnf('associativity of ;', axiom,
+    A ; (B ; C) = (A ; B) ; C).
+cnf('identity for ;', axiom,
+    A ; '1' = A).
+cnf('distributivity of ; over ∨', axiom,
+    (A ∨ B) ; C = (A ; C) ∨ (B ; C)).
+cnf('involution of ⁻¹', axiom,
+    A⁻¹ ⁻¹ = A).
+cnf('additivity of ⁻¹', axiom,
+    (A ∨ B)⁻¹ = A⁻¹ ∨ B⁻¹).
+cnf('multiplicativity of ⁻¹', axiom,
+    (A ; B)⁻¹ = B⁻¹ ; A⁻¹).
+cnf('cancellativity of ⁻', axiom,
+    (A⁻¹ ; (A ; B)⁻) ∨ B⁻ = B⁻).
+cnf('definition of top', axiom,
+    top = A ∨ A⁻).
+cnf('definition of zero', axiom,
+    zero = A ∧ A⁻).
+cnf(goal, conjecture,
+    (r1 ; (r2 ∧ r3)) ∨ ((r1 ; r2) ∧ (r1 ; r3)) =
+    (r1 ; r2) ∧ (r1 ; r3)).
diff --git a/examples/rel2.p b/examples/rel2.p
new file mode 100644
--- /dev/null
+++ b/examples/rel2.p
@@ -0,0 +1,32 @@
+tff(type, type, '_⁻¹' : $i > $i).
+tff(type, type, '_⁻' : $i > $i).
+
+cnf('commutativity of ∨', axiom,
+    A ∨ B = B ∨ A).
+cnf('associativity of ∨', axiom,
+    A ∨ (B ∨ C) = (A ∨ B) ∨ C).
+cnf('a kind of de Morgan', axiom,
+    (A⁻ ∨ B⁻)⁻ ∨ (A⁻ ∨ B)⁻ = A).
+cnf('definition of ∧', axiom,
+    A ∧ B = (A⁻ ∨ B⁻)⁻).
+cnf('associativity of ;', axiom,
+    A ; (B ; C) = (A ; B) ; C).
+cnf('identity for ;', axiom,
+    A ; '1' = A).
+cnf('distributivity of ; over ∨', axiom,
+    (A ∨ B) ; C = (A ; C) ∨ (B ; C)).
+cnf('involution of ⁻¹', axiom,
+    A⁻¹ ⁻¹ = A).
+cnf('additivity of ⁻¹', axiom,
+    (A ∨ B)⁻¹ = A⁻¹ ∨ B⁻¹).
+cnf('multiplicativity of ⁻¹', axiom,
+    (A ; B)⁻¹ = B⁻¹ ; A⁻¹).
+cnf('cancellativity of ⁻', axiom,
+    (A⁻¹ ; (A ; B)⁻) ∨ B⁻ = B⁻).
+cnf('definition of top', axiom,
+    top = A ∨ A⁻).
+cnf('definition of zero', axiom,
+    zero = A ∧ A⁻).
+cnf(goal, conjecture,
+    ((r1 ; r2) ∧ r3) ∨ ((r1; (r2 ∧ (r1⁻¹ ; r3))) ∧ r3) =
+    (r1 ; (r2 ∧ (r1⁻¹ ; r3))) ∧ r3).
diff --git a/examples/rellat_appendixa.p b/examples/rellat_appendixa.p
new file mode 100644
--- /dev/null
+++ b/examples/rellat_appendixa.p
@@ -0,0 +1,27 @@
+% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
+% appendix a. theorem 3.4, clause 7.
+cnf(commutativity, axiom,
+    X ∧ Y = Y ∧ X).
+cnf(associativity, axiom,
+    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
+cnf(commutativity, axiom,
+    X ∨ Y = Y ∨ X).
+cnf(associativity, axiom,
+    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
+cnf(absorption, axiom,
+    X ∨ (X ∧ Y) = X).
+cnf(absorption, axiom,
+    X ∧ (X ∨ Y) = X).
+cnf(definition_of_upme, axiom,
+    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
+cnf(definition_of_lome, axiom,
+    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
+cnf(definition_of_upjo, axiom,
+    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
+cnf(definition_of_lojo, axiom,
+    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
+
+fof(conjecture, conjecture,
+    (![X1, Y1, W]:
+    upme(a ∧ X1,Y1,W) ∨ (Y1 ∧ W) = (((a ∧ X1) ∧ Y1) ∨ W) ∧ (((a ∧ X1) ∧ W) ∨ Y1)) =>
+    upme(a ∧ z1,z2,z3) = lome(a ∧ z1,z2,z3)).
diff --git a/examples/rellat_appendixb.p b/examples/rellat_appendixb.p
new file mode 100644
--- /dev/null
+++ b/examples/rellat_appendixb.p
@@ -0,0 +1,28 @@
+% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
+% appendix b. theorem 3.4, clause 8.
+cnf(commutativity, axiom,
+    X ∧ Y = Y ∧ X).
+cnf(associativity, axiom,
+    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
+cnf(commutativity, axiom,
+    X ∨ Y = Y ∨ X).
+cnf(associativity, axiom,
+    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
+cnf(absorption, axiom,
+    X ∨ (X ∧ Y) = X).
+cnf(absorption, axiom,
+    X ∧ (X ∨ Y) = X).
+cnf(definition_of_upme, axiom,
+    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
+cnf(definition_of_lome, axiom,
+    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
+cnf(definition_of_upjo, axiom,
+    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
+cnf(definition_of_lojo, axiom,
+    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
+cnf(rh1, axiom,
+    upme(a ∧ X1,Y1,Z1) ∨ (Y1 ∧ Z1) = (((a ∧ X1) ∧ Y1) ∨ Z1) ∧ (((a ∧ X1) ∧ Z1) ∨ Y1)).
+cnf(rh2, axiom,
+    upme(X,Y,Z) = upme(X,Y,a ∧ Z) ∨ upme(X,Z,a ∧ Y)).
+fof(conjecture, conjecture,
+    upme(a,x2,y2) = upme(a,x2,z2) => upme(x2,y2,z2) = lome(x2,y2,z2)).
diff --git a/examples/rellat_appendixb_easier.p b/examples/rellat_appendixb_easier.p
new file mode 100644
--- /dev/null
+++ b/examples/rellat_appendixb_easier.p
@@ -0,0 +1,30 @@
+% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
+% appendix b. theorem 3.4, clause 8, assuming axiom rl1.
+cnf(commutativity, axiom,
+    X ∧ Y = Y ∧ X).
+cnf(associativity, axiom,
+    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
+cnf(commutativity, axiom,
+    X ∨ Y = Y ∨ X).
+cnf(associativity, axiom,
+    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
+cnf(absorption, axiom,
+    X ∨ (X ∧ Y) = X).
+cnf(absorption, axiom,
+    X ∧ (X ∨ Y) = X).
+cnf(definition_of_upme, axiom,
+    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
+cnf(definition_of_lome, axiom,
+    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
+cnf(definition_of_upjo, axiom,
+    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
+cnf(definition_of_lojo, axiom,
+    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
+cnf(rh1, axiom,
+    upme(a ∧ X1,Y1,Z1) ∨ (Y1 ∧ Z1) = (((a ∧ X1) ∧ Y1) ∨ Z1) ∧ (((a ∧ X1) ∧ Z1) ∨ Y1)).
+cnf(rh2, axiom,
+    upme(X,Y,Z) = upme(X,Y,a ∧ Z) ∨ upme(X,Z,a ∧ Y)).
+cnf(rl1, axiom,
+    lome(X,Y,Z) = upme(X,upme(Y,X,Z),upme(Z,X,Y))).
+fof(conjecture, conjecture,
+    upme(a,x2,y2) = upme(a,x2,z2) => upme(x2,y2,z2) = lome(x2,y2,z2)).
diff --git a/examples/rellat_appendixc.p b/examples/rellat_appendixc.p
new file mode 100644
--- /dev/null
+++ b/examples/rellat_appendixc.p
@@ -0,0 +1,30 @@
+% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
+% appendix c. theorem 3.4, clause 9.
+cnf(commutativity, axiom,
+    X ∧ Y = Y ∧ X).
+cnf(associativity, axiom,
+    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
+cnf(commutativity, axiom,
+    X ∨ Y = Y ∨ X).
+cnf(associativity, axiom,
+    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
+cnf(absorption, axiom,
+    X ∨ (X ∧ Y) = X).
+cnf(absorption, axiom,
+    X ∧ (X ∨ Y) = X).
+cnf(definition_of_upme, axiom,
+    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
+cnf(definition_of_lome, axiom,
+    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
+cnf(definition_of_upjo, axiom,
+    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
+cnf(definition_of_lojo, axiom,
+    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
+cnf(upme_property_1, axiom,
+    upme(a ∧ X1,Y1,Z1) ∨ (Y1 ∧ Z1) = (((a ∧ X1) ∧ Y1) ∨ Z1) ∧ (((a ∧ X1) ∧ Z1) ∨ Y1)).
+cnf(upme_property_2, axiom,
+    upme(X,Y,Z) = upme(X,Y,a ∧ Z) ∨ upme(X,Z,a ∧ Y)).
+fof(conjecture, conjecture,
+    (upme(a,x2,y2) = upme(a,x2,z2) &
+     upme(a,x2,y2) = upme(a,y2,z2)) =>
+    upjo(x2,y2,z2) = lojo(x2,y2,z2)).
diff --git a/examples/rellat_theorem34_6.p b/examples/rellat_theorem34_6.p
new file mode 100644
--- /dev/null
+++ b/examples/rellat_theorem34_6.p
@@ -0,0 +1,32 @@
+% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
+% theorem 3.4, clause 6.
+cnf(commutativity, axiom,
+    X ∧ Y = Y ∧ X).
+cnf(associativity, axiom,
+    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
+cnf(commutativity, axiom,
+    X ∨ Y = Y ∨ X).
+cnf(associativity, axiom,
+    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
+cnf(absorption, axiom,
+    X ∨ (X ∧ Y) = X).
+cnf(absorption, axiom,
+    X ∧ (X ∨ Y) = X).
+cnf(definition_of_upme, axiom,
+    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
+cnf(definition_of_lome, axiom,
+    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
+cnf(definition_of_upjo, axiom,
+    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
+cnf(definition_of_lojo, axiom,
+    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
+cnf(eq1, axiom,
+    upme(a ∧ Z1,Z2,Z3) = lome(a ∧ Z1,Z2,Z3)).
+cnf(qu2, axiom,
+    upme(a,X2,Y2) = upme(a,X2,Z2) => upme(X2,Y2,Z2) = lome(X2,Y2,Z2)).
+fof(rl1, conjecture,
+    lome(x,y,z) =
+    (x∧(y∧(x∨z)))∨(z∧(x∨y))).
+%fof(rl2, conjecture,
+%    t∧(((x∨y)∧(x∨z))∨((u∨w)∧(u∨v))) =
+%    (t∧(((x∨y)∧(x∨z))∨(u∨(w∧v))))∨(t∧(((u∨w)∧(u∨v))∨(x∨(y∧z))))).
diff --git a/examples/rellat_theorem34_6a.p b/examples/rellat_theorem34_6a.p
new file mode 100644
--- /dev/null
+++ b/examples/rellat_theorem34_6a.p
@@ -0,0 +1,29 @@
+% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
+% theorem 3.4, clause 6.
+cnf(commutativity, axiom,
+    X ∧ Y = Y ∧ X).
+cnf(associativity, axiom,
+    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
+cnf(commutativity, axiom,
+    X ∨ Y = Y ∨ X).
+cnf(associativity, axiom,
+    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
+cnf(absorption, axiom,
+    X ∨ (X ∧ Y) = X).
+cnf(absorption, axiom,
+    X ∧ (X ∨ Y) = X).
+cnf(definition_of_upme, axiom,
+    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
+cnf(definition_of_lome, axiom,
+    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
+cnf(definition_of_upjo, axiom,
+    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
+cnf(definition_of_lojo, axiom,
+    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
+cnf(eq1, axiom,
+    upme(a ∧ Z1,Z2,Z3) = lome(a ∧ Z1,Z2,Z3)).
+cnf(qu2, axiom,
+    upme(a,X2,Y2) = upme(a,X2,Z2) => upme(X2,Y2,Z2) = lome(X2,Y2,Z2)).
+fof(rl1, conjecture,
+    lome(x,y,z) =
+    x∧((y∧(x∨z))∨(z∧(x∨y)))).
diff --git a/examples/rellat_theorem34_6b.p b/examples/rellat_theorem34_6b.p
new file mode 100644
--- /dev/null
+++ b/examples/rellat_theorem34_6b.p
@@ -0,0 +1,29 @@
+% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
+% theorem 3.4, clause 6.
+cnf(commutativity, axiom,
+    X ∧ Y = Y ∧ X).
+cnf(associativity, axiom,
+    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
+cnf(commutativity, axiom,
+    X ∨ Y = Y ∨ X).
+cnf(associativity, axiom,
+    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
+cnf(absorption, axiom,
+    X ∨ (X ∧ Y) = X).
+cnf(absorption, axiom,
+    X ∧ (X ∨ Y) = X).
+cnf(definition_of_upme, axiom,
+    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
+cnf(definition_of_lome, axiom,
+    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
+cnf(definition_of_upjo, axiom,
+    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
+cnf(definition_of_lojo, axiom,
+    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
+cnf(eq1, axiom,
+    upme(a ∧ Z1,Z2,Z3) = lome(a ∧ Z1,Z2,Z3)).
+cnf(qu2, axiom,
+    upme(a,X2,Y2) = upme(a,X2,Z2) => upme(X2,Y2,Z2) = lome(X2,Y2,Z2)).
+fof(rl2, conjecture,
+    t∧(((x∨y)∧(x∨z))∨((u∨w)∧(u∨v))) =
+    (t∧(((x∨y)∧(x∨z))∨(u∨(w∧v))))∨(t∧(((u∨w)∧(u∨v))∨(x∨(y∧z))))).
diff --git a/examples/ring.p b/examples/ring.p
new file mode 100644
--- /dev/null
+++ b/examples/ring.p
@@ -0,0 +1,9 @@
+cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(plus_zero, axiom, '+'('0', X) = X).
+cnf(plus_inv, axiom, '+'(X, '-'(X)) = '0').
+cnf(times_assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
+cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
+cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
+cnf(cube, axiom, X = '*'(X, '*'(X, X))).
+cnf(conjecture, negated_conjecture, '*'(a, b) != '*'(b, a)).
diff --git a/examples/ring2-cancel.p b/examples/ring2-cancel.p
new file mode 100644
--- /dev/null
+++ b/examples/ring2-cancel.p
@@ -0,0 +1,9 @@
+cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(plus_zero, axiom, '+'('0', X) = X).
+cnf(plus_inv, axiom, '+'(X, '-'(X)) = '0').
+cnf(times_assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
+cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
+cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
+cnf(power_six, axiom, X = '*'(X, '*'(X, '*'(X, '*'(X, '*'(X, X)))))).
+cnf(conjecture, negated_conjecture, '+'(x, x) != '0').
diff --git a/examples/ring2.p b/examples/ring2.p
new file mode 100644
--- /dev/null
+++ b/examples/ring2.p
@@ -0,0 +1,9 @@
+cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(plus_zero, axiom, '+'('0', X) = X).
+cnf(plus_inv, axiom, '+'(X, '-'(X)) = '0').
+cnf(times_assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
+cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
+cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
+cnf(power_six, axiom, X = '*'(X, '*'(X, '*'(X, '*'(X, '*'(X, X)))))).
+cnf(conjecture, negated_conjecture, '*'(a, b) != '*'(b, a)).
diff --git a/examples/ring3.p b/examples/ring3.p
new file mode 100644
--- /dev/null
+++ b/examples/ring3.p
@@ -0,0 +1,9 @@
+cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(plus_zero, axiom, '+'('0', X) = X).
+cnf(plus_neg, axiom, '+'(X, '-'(X)) = '0').
+cnf(times_assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
+cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
+cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
+cnf(power_four, axiom, X = '*'(X, '*'(X, '*'(X, X)))).
+cnf(conjecture, negated_conjecture, '*'(a, b) != '*'(b, a)).
diff --git a/examples/ring4.p b/examples/ring4.p
new file mode 100644
--- /dev/null
+++ b/examples/ring4.p
@@ -0,0 +1,9 @@
+cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(plus_zero, axiom, '+'('0', X) = X).
+cnf(plus_inv, axiom, '+'(X, '-'(X)) = '0').
+cnf(times_ssoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
+cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
+cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
+cnf(power_five, axiom, X = '*'(X, '*'(X, '*'(X, '*'(X, X))))).
+cnf(conjecture, negated_conjecture, '*'(a, b) != '*'(b, a)).
diff --git a/examples/robbins-easy.p b/examples/robbins-easy.p
new file mode 100644
--- /dev/null
+++ b/examples/robbins-easy.p
@@ -0,0 +1,4 @@
+cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(funny, axiom, '+'('-'('+'('-'(X), Y)), '-'('+'('-'(X), '-'(Y)))) = X).
+cnf(conjecture, negated_conjecture, '-'('+'('-'('+'(a, b)), '-'('+'(a, '-'(b))))) != a).
diff --git a/examples/robbins-hints.p b/examples/robbins-hints.p
new file mode 100644
--- /dev/null
+++ b/examples/robbins-hints.p
@@ -0,0 +1,39 @@
+%------------------------------------------------------------------------------
+% File     : ROB001-1 : TPTP v9.3.0. Released v1.0.0.
+% Domain   : Robbins Algebra
+% Problem  : Is every Robbins algebra Boolean?
+% Version  : [Win90] (equality) axioms.
+% English  :
+
+% Refs     : [HMT71] Henkin et al. (1971), Cylindrical Algebras
+%          : [Win90] Winker (1990), Robbins Algebra: Conditions that make a
+% Source   : [TPTP]
+% Names    :
+
+% Status   : Unsatisfiable
+% Rating   : 1.00 v2.0.0
+% Syntax   : Number of clauses     :    4 (   4 unt;   0 nHn;   1 RR)
+%            Number of literals    :    4 (   4 equ;   1 neg)
+%            Maximal clause size   :    1 (   1 avg)
+%            Maximal term depth    :    6 (   2 avg)
+%            Number of predicates  :    1 (   0 usr;   0 prp; 2-2 aty)
+%            Number of functors    :    4 (   4 usr;   2 con; 0-2 aty)
+%            Number of variables   :    7 (   0 sgn)
+% SPC      : CNF_UNS_RFO_PEQ_UEQ
+
+% Comments : Commutativity, associativity, and Huntington's axiom axiomatize 
+%            Boolean algebra.
+%------------------------------------------------------------------------------
+%----Include axioms for Robbins algebra
+include('Axioms/ROB001-0.ax').
+%------------------------------------------------------------------------------
+cnf(prove_huntingtons_axiom,negated_conjecture,
+    add(negate(add(a,negate(b))),negate(add(negate(a),negate(b)))) != b ).
+
+%----Definition of g
+cnf(sos04,axiom,(
+    $hint(negate(add(A,negate(A)))) )).
+
+%----Definition of h
+cnf(sos05,axiom,(
+    h(A) = add(A,add(A,add(A,negate(add(A,negate(A)))))))).
diff --git a/examples/robbins.p b/examples/robbins.p
new file mode 100644
--- /dev/null
+++ b/examples/robbins.p
@@ -0,0 +1,4 @@
+cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(funny, axiom, '-'('+'('-'('+'(X, Y)), '-'('+'(X, '-'(Y))))) = X).
+cnf(conjecture, negated_conjecture, '-'('-'(a)) != a).
diff --git a/examples/sam.p b/examples/sam.p
new file mode 100644
--- /dev/null
+++ b/examples/sam.p
@@ -0,0 +1,38 @@
+cnf(f_assoc, axiom,
+    meet(X,meet(Y,Z)) = meet(meet(X,Y),Z)).
+cnf(f_comm, axiom,
+    meet(X,Y) = meet(Y,X)).
+cnf(f_idem, axiom,
+    meet(X,X) = X).
+cnf(g_assoc, axiom,
+    join(X,join(Y,Z)) = join(join(X,Y),Z)).
+cnf(g_comm, axiom,
+    join(X,Y) = join(Y,X)).
+cnf(g_idem, axiom,
+    join(X,X) = X).
+
+cnf(ax31, axiom,
+    meet(X, join(X,Y)) = X).
+cnf(ax32, axiom,
+    meet(zero, X) = zero).
+cnf(ax33, axiom,
+    join(zero, X) = X).
+cnf(ax34, axiom,
+    join(X, meet(X, Y)) = X).
+cnf(ax35, axiom,
+    meet(one, X) = X).
+cnf(ax36, axiom,
+    join(one, X) = one).
+cnf(ax37, axiom,
+    meet(X,Z) = X =>
+    meet(join(X,Y),Z) = join(X,meet(Y,Z))).
+
+cnf(comp, definition,
+    comp(X,Y) <=> (meet(X,Y) = zero & join(X,Y) = one)).
+
+cnf(premise1, assumption,
+    comp(a, join(c,d))).
+cnf(premise2, assumption,
+    comp(b, join(c,d))).
+cnf(goal, conjecture,
+    meet(join(a,meet(b,c)),join(a,meet(b,d)))=a).
diff --git a/examples/semigroup.p b/examples/semigroup.p
new file mode 100644
--- /dev/null
+++ b/examples/semigroup.p
@@ -0,0 +1,4 @@
+cnf(assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
+cnf(two_three, axiom, '*'(X, X) = '*'(X, '*'(X, X))).
+cnf(twiddle, axiom, '*'('*'(X, X), Y) = '*'(Y, '*'(X, X))).
+cnf(conjecture, negated_conjecture, '*'('*'(a, b), '*'(a, b)) != '*'('*'(a, a), '*'(b, b))).
diff --git a/examples/sudoku.p b/examples/sudoku.p
new file mode 100644
--- /dev/null
+++ b/examples/sudoku.p
@@ -0,0 +1,39 @@
+cnf('associativity of ∘', axiom,
+    F ∘ (G ∘ H) = (F ∘ G) ∘ H).
+
+cnf('∘ identity', axiom,
+    id ∘ F = F).
+
+cnf('∘ identity', axiom,
+    F ∘ id = F).
+
+cnf('map functor', axiom,
+    map(F) ∘ map(G) = map(F ∘ G)).
+
+cnf('map functor', axiom,
+    map(id) = id).
+
+cnf('defn pruneBy', axiom,
+    pruneBy(F) = F ∘ (map(pruneRow) ∘ F)).
+
+cnf('defn expand', axiom,
+    expand = product ∘ map(product)).
+
+cnf('expand after boxs', axiom,
+    expand ∘ boxs = map(boxs) ∘ expand).
+
+cnf('filter with boxs', axiom,
+    filter (P ∘ boxs) = map(boxs) ∘ (filter(P) ∘ map(boxs))).
+
+cnf('boxs involution', axiom,
+    boxs ∘ boxs = id).
+
+cnf('filter after product', axiom,
+    filter(all(P)) ∘ product = product ∘ map(filter(P))).
+
+cnf('law of pruneRow', axiom,
+    filter(nodups) ∘ (product ∘ pruneRow) = filter(nodups) ∘ product).
+
+cnf('conjecture', conjecture,
+    filter(all(nodups) ∘ boxs) ∘ (expand ∘ pruneBy(boxs)) =
+    filter(all(nodups) ∘ boxs) ∘ expand).
diff --git a/examples/sum.p b/examples/sum.p
new file mode 100644
--- /dev/null
+++ b/examples/sum.p
@@ -0,0 +1,30 @@
+cnf(plus_comm, axiom,
+    X + Y = Y + X).
+cnf(plus_assoc, axiom,
+    X + (Y + Z) = (X + Y) + Z).
+cnf(times_comm, axiom,
+    X * Y = Y * X).
+cnf(times_assoc, axiom,
+    X * (Y * Z) = (X * Y) * Z).
+cnf(plus_zero, axiom,
+    X + zero = X).
+cnf(times_zero, axiom,
+    X * zero = zero).
+cnf(times_one, axiom,
+    X * one = X).
+cnf(distr, axiom,
+    X * (Y + Z) = (X * Y) + (X * Z)).
+cnf(distr, axiom,
+    (X + Y) * Z = (X * Z) + (Y * Z)).
+cnf(plus_s, axiom,
+    s(X) + Y = s(X+Y)).
+cnf(times_s, axiom,
+    s(X)*Y = Y + (X*Y)).
+cnf(sum_zero, axiom,
+    sum(zero) = zero).
+cnf(sum_s, axiom,
+    sum(s(N)) = s(N) + sum(N)).
+cnf(ih, axiom,
+    sum(a) + sum(a) = a * s(a)).
+cnf(conjecture, conjecture,
+    sum(s(a)) + sum(s(a)) = s(a) * s(s(a))).
diff --git a/examples/vbool.p b/examples/vbool.p
new file mode 100644
--- /dev/null
+++ b/examples/vbool.p
@@ -0,0 +1,18 @@
+fof(associativity, axiom,
+    ![X, Y, Z]:
+    X ⊕ (Y ⊕ Z) = (X ⊕ Y) ⊕ Z).
+
+fof(commutativity, axiom,
+    ![X, Y]:
+    X ⊕ Y = Y ⊕ X).
+
+fof(idempotence, axiom,
+    ![X]:
+    X ⊕ X = X).
+
+fof(non_injectivity, conjecture,
+    ![A, B]: ?[X]: A ⊕ X = B ⊕ X).
+
+% Examples:
+% plus is commutative, associative, and injective, but not idempotent
+% max is idempotent, commutative, and associativity, but not injective
diff --git a/examples/veroff-short.p b/examples/veroff-short.p
new file mode 100644
--- /dev/null
+++ b/examples/veroff-short.p
@@ -0,0 +1,11 @@
+cnf(majority, axiom,
+    f(X,X,Y) = X).
+cnf('2a', axiom,
+    f(X,Y,Z) = f(Z,X,Y)).
+cnf('2b', axiom,
+    f(X,Y,Z) = f(X,Z,Y)).
+cnf(associativity, axiom,
+    f(f(X,W,Y),W,Z) = f(X,W,f(Y,W,Z))).
+
+cnf(dist_long, conjecture,
+    f(f(x,y,z),u,w) = f(x,f(y,u,w),f(z,u,w))).
diff --git a/examples/veroff.p b/examples/veroff.p
new file mode 100644
--- /dev/null
+++ b/examples/veroff.p
@@ -0,0 +1,11 @@
+cnf(majority, axiom,
+    f(X,X,Y) = X).
+cnf('2a', axiom,
+    f(X,Y,Z) = f(Z,X,Y)).
+cnf('2b', axiom,
+    f(X,Y,Z) = f(X,Z,Y)).
+cnf(associativity, axiom,
+    f(f(X,W,Y),W,Z) = f(X,W,f(Y,W,Z))).
+
+cnf(dist_long, conjecture,
+    f(f(x,y,z),u,w) = f(f(x,u,w),f(y,u,w),f(z,u,w))).
diff --git a/examples/winker-easy.p b/examples/winker-easy.p
new file mode 100644
--- /dev/null
+++ b/examples/winker-easy.p
@@ -0,0 +1,6 @@
+% Needs case split on X < c.
+cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(idem, axiom, '+'(X, X) = X).
+cnf(funny, axiom, '-'('+'('-'('+'(X, Y)), '-'('+'(X, '-'(Y))))) = X).
+cnf(conjecture, negated_conjecture, '+'('-'('+'('-'(a), b)), '-'('+'('-'(a), '-'(b)))) != a).
diff --git a/examples/winker.p b/examples/winker.p
new file mode 100644
--- /dev/null
+++ b/examples/winker.p
@@ -0,0 +1,6 @@
+% Needs case split on X < c.
+cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(idem_c, axiom, '+'(c, c) = c).
+cnf(funny, axiom, '-'('+'('-'('+'(X, Y)), '-'('+'(X, '-'(Y))))) = X).
+cnf(conjecture, negated_conjecture, '+'('-'('+'('-'(a), b)), '-'('+'('-'(a), '-'(b)))) != a).
diff --git a/examples/winker2.p b/examples/winker2.p
new file mode 100644
--- /dev/null
+++ b/examples/winker2.p
@@ -0,0 +1,6 @@
+% Needs case split on X < c.
+cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
+cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
+cnf(plus_c_d, axiom, '+'(c, d) = c).
+cnf(funny, axiom, '-'('+'('-'('+'(X, Y)), '-'('+'(X, '-'(Y))))) = X).
+cnf(conjecture, negated_conjecture, '+'('-'('+'('-'(a), b)), '-'('+'('-'(a), '-'(b)))) != a).
diff --git a/examples/y-easy.p b/examples/y-easy.p
new file mode 100644
--- /dev/null
+++ b/examples/y-easy.p
@@ -0,0 +1,4 @@
+fof(k_def, axiom, ![X, Y]: (k @ X) @ Y = X).
+fof(s_def, axiom, ![X, Y, Z]: ((s @ X) @ Y) @ Z = (X @ Z) @ (Y @ Z)).
+fof(i_def, axiom, ![X]: i @ X = X).
+fof(conjecture, conjecture, ?[Y]: ![F]: Y @ F = F @ (Y @ F)).
diff --git a/examples/y-encoded.p b/examples/y-encoded.p
new file mode 100644
--- /dev/null
+++ b/examples/y-encoded.p
@@ -0,0 +1,5 @@
+cnf(ifeq_axiom, axiom, ifeq(A, A, B, C)=B).
+cnf(k_def, axiom, '@'('@'(k, X), Y)=X).
+cnf(s_def, axiom, '@'('@'('@'(s, X), Y), Z)='@'('@'(X, Z), '@'(Y, Z))).
+cnf(conjecture, negated_conjecture, ifeq('@'(Y, f(Y)), '@'(f(Y), '@'(Y, f(Y))), a, b)=b).
+cnf(goal, negated_conjecture, a!=b).
diff --git a/examples/y.p b/examples/y.p
new file mode 100644
--- /dev/null
+++ b/examples/y.p
@@ -0,0 +1,3 @@
+fof(k_def, axiom, ![X, Y]: (k @ X) @ Y = X).
+fof(s_def, axiom, ![X, Y, Z]: ((s @ X) @ Y) @ Z = (X @ Z) @ (Y @ Z)).
+fof(conjecture, conjecture, ?[Y]: ![F]: Y @ F = F @ (Y @ F)).
diff --git a/executable/ParallelMain.hs b/executable/ParallelMain.hs
new file mode 100644
--- /dev/null
+++ b/executable/ParallelMain.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+import System.IO
+import Control.Concurrent.Async hiding (link)
+import System.Posix
+import System.Environment
+import qualified SequentialMain
+import Control.Monad
+
+foreign import ccall "link_to_parent" link :: CPid -> IO ()
+
+raceMany :: [IO a] -> IO a
+raceMany [x] = x
+raceMany (x:xs) = do
+  result <- race x (raceMany xs)
+  case result of
+    Left res  -> return res
+    Right res -> return res
+
+raceStdout :: [(String, IO ())] -> IO ()
+raceStdout xs = do
+  action <- raceMany (map waitForStdout xs)
+  action
+  where
+    end = "*** END OF OUTPUT"
+    waitForStdout (args, p) = do
+      (fdIn, fdOut) <- createPipe
+      pid <- getProcessID
+      forkProcess $ do
+        link (fromIntegral pid)
+        dupTo fdOut stdOutput
+        hSetBuffering stdout LineBuffering
+        p
+        putStrLn end
+
+      hIn <- fdToHandle fdIn
+      hSetBuffering hIn LineBuffering
+      line <- hGetLine hIn
+      return $ do
+        putStrLn ("Command-line arguments: " ++ args)
+        putStrLn ""
+        putStrLn line
+        let
+          loop = do
+            line <- hGetLine hIn
+            unless (line == end) $ do
+              putStrLn line
+              loop
+        loop
+
+variants :: FilePath -> [[String]]
+{-
+variants =
+  map words
+  ["--lhs-weight 1 --flip-ordering --normalise-queue-percent 10 --cp-renormalise-threshold 10 --complete-subsets --ground-joining-incomplete-limit 15",
+   "--no-flatten-goal --ground-joining-incomplete-limit 15 --ground-connectedness --normalise-queue-percent 10 --cp-renormalise-threshold 10",
+   "--flatten --complete-subsets",
+   "--lhs-weight 9 --flip-ordering --complete-subsets --normalise-queue-percent 10 --cp-renormalise-threshold 10",
+   "--ground-connectedness --complete-subsets",
+   "--flip-ordering --lhs-weight 1 --depth-weight 60 --distributivity-heuristic --ground-joining-limit 15",
+   "--set-join --lhs-weight 1 --no-flatten-goal --complete-subsets --goal-heuristic",
+   "--no-kbo-weight0-unary --kbo-weight0 --no-flatten-goal"]
+  -- "--random-mode --random-mode-goal-directed --no-flatten-goal --no-connectedness --no-ground-joining"]
+-}
+variants stitch =
+  map words
+  ["--lhs-weight 1 --flip-ordering --normalise-queue-percent 10 --cp-renormalise-threshold 10 --complete-subsets --ground-joining-incomplete-limit 15 --flatten-every 2",
+   "--no-flatten-goal",
+   "--stitch " ++ stitch ++ " --hint-skel-cost 0 --hint-skel-factor 0.5",
+   "--lhs-weight 9 --flip-ordering --complete-subsets --normalise-queue-percent 10 --cp-renormalise-threshold 10",
+   "--flatten --complete-subsets",
+   "--flatten-regeneralise",
+   "--stitch " ++ stitch ++ " --hint-skel-cost 0 --hint-skel-factor 0.5 --no-flatten-goal",
+   "--lhs-weight 1 --flip-ordering --normalise-queue-percent 10 --cp-renormalise-threshold 10 --complete-subsets --ground-joining-incomplete-limit 15 --flatten-regeneralise"]
+
+main = do
+  hSetBuffering stdout LineBuffering
+  (n:stitch:args) <- getArgs
+  raceStdout [(unwords variant, withArgs (args ++ variant) SequentialMain.main) | variant <- take (read n) (variants stitch)]
diff --git a/executable/SequentialMain.hs b/executable/SequentialMain.hs
--- a/executable/SequentialMain.hs
+++ b/executable/SequentialMain.hs
@@ -1,12 +1,13 @@
-{-# LANGUAGE CPP, RecordWildCards, FlexibleInstances, PatternGuards, DeriveAnyClass, RankNTypes, ApplicativeDo #-}
+{-# LANGUAGE CPP, RecordWildCards, FlexibleInstances, PatternGuards, DeriveAnyClass, RankNTypes, ApplicativeDo, DeriveGeneric #-}
 {-# OPTIONS_GHC -flate-specialise #-}
-module SequentialMain(main) where
+module SequentialMain(main, Constant(..)) where
 
 import Control.Monad
 import Data.Char
 import Data.Either
 import Twee hiding (message)
 import Twee.Base hiding (char, lookup, vars, ground)
+--import qualified Twee.Base as Twee
 import Twee.Rule(lhs, rhs, unorient)
 import Twee.Equation
 import qualified Twee.Proof as Proof
@@ -15,13 +16,18 @@
 import Twee.Utils
 import qualified Twee.CP as CP
 import Data.Ord
+import Data.Map(Map)
 import qualified Data.Map.Strict as Map
 import qualified Twee.KBO as KBO
+#ifdef USE_LPO
+import qualified Twee.LPO as LPO
+#endif
 import Data.List.Split
 import Data.List
 import Data.Maybe
 import Jukebox.Options
 import Jukebox.Toolbox
+import qualified Jukebox.Name as Jukebox
 import Jukebox.Name hiding (lhs, rhs, label)
 import qualified Jukebox.Form as Jukebox
 import Jukebox.Form hiding ((:=:), Var, Symbolic(..), Term, Axiom, size, Subst, subst)
@@ -36,6 +42,13 @@
 import System.Console.ANSI
 import Data.Symbol
 import Twee.Profile
+import GHC.Generics
+import Data.Hashable
+import Data.Binary.Sharing
+import qualified Data.ByteString.Lazy as BS
+import System.Process
+import qualified Jukebox.TPTP.Parse.Core as TPTP
+import qualified Jukebox.TPTP.ParseSnippet as Snippet
 
 data MainFlags =
   MainFlags {
@@ -46,11 +59,13 @@
     flags_explain_encoding :: Bool,
     flags_flip_ordering :: Bool,
     flags_give_up_on_saturation :: Bool,
+    flags_hint_goals :: Bool,
     flags_flatten_goals :: Bool,
     flags_flatten_nonground :: Bool,
     flags_flatten_goals_lightly :: Bool,
     flags_flatten_all :: Bool,
     flags_flatten_regeneralise :: Bool,
+    flags_flatten_every :: Int,
     flags_eliminate :: [String],
     flags_backwards_goal :: Int,
     flags_flatten_backwards_goal :: Int,
@@ -58,7 +73,11 @@
     flags_distributivity_heuristic :: Bool,
     flags_kbo_weight0 :: Bool,
     flags_kbo_weight0_unary :: Bool,
-    flags_goal_heuristic :: Bool }
+    flags_goal_heuristic :: Bool,
+    flags_funweight :: Float,
+    flags_dump_proof :: Maybe FilePath,
+    flags_dump_state :: Maybe FilePath,
+    flags_stitch :: Maybe FilePath }
 
 parseMainFlags :: OptionParser MainFlags
 parseMainFlags = do
@@ -102,6 +121,10 @@
     expert $
     inGroup "Output options" $
     bool "give-up-on-saturation" ["Report SZS status GiveUp rather than Unsatisfiable on saturation (off by default)."] False
+  flags_hint_goals <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "hint-goal" ["Add hints representing goal terms (off by default)."] False
   flags_flatten_goals <-
     expert $
     inGroup "Completion heuristics" $
@@ -118,6 +141,10 @@
     expert $
     inGroup "Completion heuristics" $
     bool "flatten" ["Flatten all clauses by adding new axioms (off by default)."] False
+  flags_flatten_every <-
+    expert $
+    inGroup "Completion heuristics" $
+    flag "flatten-every" ["Flatten only every nth subterm (default = 1)."] 1 argNum
   flags_flatten_regeneralise <-
     expert $
     inGroup "Completion heuristics" $
@@ -151,6 +178,28 @@
        "distinct variables. The term f must not otherwise appear in the problem!",
        "This is not checked."]
       (splitOn "," <$> arg "<axioms>" "expected a list of axiom names" Just)
+  flags_funweight <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    flag "fun-weight" ["Weight given to function symbols"] 1 argNum
+  flags_dump_proof <-
+    expert $
+    inGroup "Debugging options" $
+    flag "dump-proof"
+      ["Dump a binary proof to this file (off by default)."]
+      Nothing (Just <$> argFile)
+  flags_dump_state <-
+    expert $
+    inGroup "Debugging options" $
+    flag "dump-state"
+      ["Dump prover state to this file on termination (off by default)."]
+      Nothing (Just <$> argFile)
+  flags_stitch <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    flag "stitch"
+      ["Path to 'stitch' tool for discovering abstractions (disabled by default)."]
+      Nothing (Just <$> argFile)
 
   return MainFlags{..}
 
@@ -208,7 +257,7 @@
     bool "complete-subsets"
       ["Identify and exploit complete subsets of the axioms in joining (off by default)."]
       False
-  let cfg_score_cp = undefined -- filled in later, in runTwee
+  let cfg_hint_func i x = Intern.intern (Hint i x)
 
   cfg_join <- do
     cfg_ground_join <-
@@ -352,6 +401,7 @@
     expert $
     inGroup "Output options" $
     bool "print-score" ["Print score of each generated rule (off by default)."] False
+  cfg_cp_config <- parseCPConfig
 
   return Config{..}
   where
@@ -371,10 +421,6 @@
     expert $
     inGroup "Critical pair weighting heuristics" $
     defaultFlag "rhs-weight" "Weight given to RHS of critical pair" CP.cfg_rhsweight argNum
-  cfg_funweight <-
-    expert $
-    inGroup "Critical pair weighting heuristics" $
-    defaultFlag "fun-weight" "Weight given to function symbols" CP.cfg_funweight argNum
   cfg_varweight <-
     expert $
     inGroup "Critical pair weighting heuristics" $
@@ -391,10 +437,6 @@
     expert $
     inGroup "Critical pair weighting heuristics" $
     defaultFlag "dup-factor" "Size factor of duplicate subterms" CP.cfg_dupfactor argNum
-  cfg_resonance <-
-    expert $
-    inGroup "Critical pair weighting heuristics" $
-    bool "resonance" ["Interpret hints as resonators by only allowing substitutions which map variables to variables (off by default)."] False
   return CP.Config{..}
   where
     defaultFlag name desc field parser =
@@ -412,31 +454,44 @@
 data Constant =
   Minimal |
   Skolem Int |
+  Hint Int Float |
   Constant {
-    con_prec   :: {-# UNPACK #-} !Precedence,
-    con_id     :: {-# UNPACK #-} !Jukebox.Function,
-    con_arity  :: {-# UNPACK #-} !Int,
-    con_size   :: !Integer,
-    con_weight :: !Integer,
-    con_bonus  :: !Bool }
-  deriving (Eq, Ord)
+    con_prec    :: {-# UNPACK #-} !Precedence,
+    con_id      :: {-# UNPACK #-} !Int,
+    con_name    :: !String,
+    con_arity   :: {-# UNPACK #-} !Int,
+    con_label   :: !(Maybe String),
+    con_size    :: !Integer,
+    con_weight  :: !Integer,
+    con_fweight :: {-# UNPACK #-} !Float,
+    con_bonus   :: !Bool }
+  deriving (Eq, Ord, Generic, Hashable, Binary)
 
 data Precedence = Precedence !Bool !Bool !Bool !(Maybe Int) !Int
-  deriving (Eq, Ord)
+  deriving (Eq, Ord, Generic, Hashable, Binary)
 
 instance KBO.Sized Constant where
   size Minimal = 1
   size Skolem{} = 1
+  size Hint{} = 1
   size Constant{..} = con_size
-instance KBO.Weighted Constant where
+instance KBO.ArgWeighted Constant where
   argWeight Minimal = 1
   argWeight Skolem{} = 1
+  argWeight Hint{} = 1
   argWeight Constant{..} = con_weight
 
+instance Weighted Constant where
+  weight Minimal = 1
+  weight (Skolem _) = 1
+  weight (Hint _ x) = x
+  weight Constant{..} = con_fweight
+
 instance Pretty Constant where
   pPrint Minimal = text "?"
   pPrint (Skolem n) = text ("sk" ++ show n)
-  pPrint Constant{..} = text (removePostfix (base con_id))
+  pPrint (Hint n _) = text ("hint" ++ show n)
+  pPrint Constant{..} = text (removePostfix con_name)
     where
       removePostfix ('_':x:xs) | con_arity == 1 = x:xs
       removePostfix xs = xs
@@ -444,10 +499,11 @@
 instance PrettyTerm Constant where
   termStyle Minimal = uncurried
   termStyle Skolem{} = uncurried
+  termStyle Hint{} = uncurried
   termStyle Constant{..}
-    | hasLabel "type_tag" con_id = invisible
-    | "_" `isPrefixOf` base con_id && con_arity == 1 = postfix
-    | any isAlphaNum (base con_id) = uncurried
+    | con_label == Just "type_tag" = invisible
+    | "_" `isPrefixOf` con_name && con_arity == 1 = postfix
+    | any isAlphaNum con_name = uncurried
     | otherwise =
       case con_arity of
         1 -> prefix
@@ -458,25 +514,31 @@
   minimal = Sym Minimal
   skolem = Sym . Skolem
 
+#ifdef USE_LPO
 instance Ordered Constant where
+  lessEq t u = LPO.lessEq t u
+  lessIn model t u = LPO.lessIn model t u
+  lessEqSkolem t u = LPO.lessEqSkolem t u
+#else
+instance Ordered Constant where
   lessEq t u = KBO.lessEq t u
   lessIn model t u = KBO.lessIn model t u
   lessEqSkolem t u = KBO.lessEqSkolem t u
+#endif
 
 instance EqualsBonus Constant where
   hasEqualsBonus Minimal = False
   hasEqualsBonus Skolem{} = False
+  hasEqualsBonus Hint{} = False
   hasEqualsBonus c = con_bonus c
-  isEquals Minimal = False
-  isEquals Skolem{} = False
-  isEquals c = SequentialMain.isEquals (con_id c)
-  isTrue Minimal = False
-  isTrue Skolem{} = False
-  isTrue c = SequentialMain.isTrue (con_id c)
-  isFalse Minimal = False
-  isFalse Skolem{} = False
-  isFalse c = SequentialMain.isFalse (con_id c)
 
+  isEquals Constant{..} = con_label == Just "equals" && con_arity == 2
+  isEquals _ = False
+  isTrue Constant{..} = con_label == Just "true" && con_arity == 0
+  isTrue _ = False
+  isFalse Constant{..} = con_label == Just "false" && con_arity == 0
+  isFalse _ = False
+
 data TweeContext =
   TweeContext {
     ctx_var     :: Jukebox.Variable,
@@ -484,7 +546,9 @@
     ctx_true    :: Jukebox.Function,
     ctx_false   :: Jukebox.Function,
     ctx_equals  :: Jukebox.Function,
-    ctx_type    :: Type }
+    ctx_type    :: Type,
+    ctx_funs    :: Map Int Jukebox.Function,
+    ctx_ids     :: Map Jukebox.Function Int }
 
 -- Convert back and forth between Twee and Jukebox.
 tweeConstant :: MainFlags -> HornFlags -> TweeContext -> Precedence -> Jukebox.Function -> Constant
@@ -493,15 +557,18 @@
   | otherwise =
     Constant {
       con_prec = prec,
-      con_id = fun,
+      con_id = Map.findWithDefault (error (show (fun, ctx_ids))) fun ctx_ids,
+      con_name = base (name fun),
+      con_label = Jukebox.label (name fun),
       con_arity = Jukebox.arity fun,
       con_size = if flags_kbo_weight0 && Jukebox.arity fun >= 2 then 0 else if flags_kbo_weight0_unary && isInv then 0 else 1,
       con_weight = 1,
+      con_fweight = flags_funweight,
       con_bonus = bonus fun }
   where
     bonus fun =
       (isIfeq fun && encoding flags /= Asymmetric2) ||
-      SequentialMain.isEquals fun
+      (Jukebox.label (name fun) == Just "equals" && Jukebox.arity fun == 2)
     isInv =
       case prec of
         Precedence _ x _ _ _ -> x
@@ -514,27 +581,15 @@
 isIfeq fun =
   hasLabel "ifeq" (name fun)
 
-isEquals :: Jukebox.Function -> Bool
-isEquals fun =
-  hasLabel "equals" (name fun) && Jukebox.arity fun == 2
-
-isTrue :: Jukebox.Function -> Bool
-isTrue fun =
-  hasLabel "true" (name fun) && Jukebox.arity fun == 0
-
-isFalse :: Jukebox.Function -> Bool
-isFalse fun =
-  hasLabel "false" (name fun) && Jukebox.arity fun == 0
-
 jukeboxFunction :: TweeContext -> Constant -> Jukebox.Function
-jukeboxFunction _ Constant{..} = con_id
+jukeboxFunction TweeContext{..} Constant{..} = Map.findWithDefault undefined con_id ctx_funs
 jukeboxFunction TweeContext{..} Minimal = ctx_minimal
 
-tweeTerm :: MainFlags -> HornFlags -> TweeContext -> (Jukebox.Function -> Precedence) -> Jukebox.Term -> Term Constant
-tweeTerm flags horn ctx prec t = build (tm t)
+tweeTerm :: MainFlags -> HornFlags -> TweeContext -> (Jukebox.Variable -> Int) -> (Jukebox.Function -> Precedence) -> Jukebox.Term -> Term Constant
+tweeTerm flags horn ctx varNum prec t = build (tm t)
   where
-    tm (Jukebox.Var (x ::: _)) =
-      var (V (Intern.symId (Intern.intern x)))
+    tm (Jukebox.Var x) =
+      var (V (varNum x))
     tm (f :@: ts) =
       app (Sym (tweeConstant flags horn ctx (prec f) f)) (map tm ts)
 
@@ -560,18 +615,22 @@
   false   <- newFunction (withLabel "false" (name "false")) [] ty
   equals  <- newFunction (withLabel "equals" (name "equals")) [ty, ty] ty
 
+  let allFuns = usort $ [minimal, true, false, equals] ++ Jukebox.functions (hints, prob)
+
   return TweeContext {
     ctx_var = var,
     ctx_minimal = minimal,
     ctx_true = true,
     ctx_false = false,
     ctx_equals = equals,
-    ctx_type = ty }
+    ctx_type = ty,
+    ctx_funs = Map.fromList (zip [0..] allFuns),
+    ctx_ids = Map.fromList (zip allFuns [0..]) }
 
-flattenGoals :: Int -> Bool -> Bool -> Bool -> [Jukebox.Term] -> Problem Clause -> Problem Clause
-flattenGoals backwardsGoal flattenNonGround flattenAll full hints prob =
+flattenGoals :: Int -> Bool -> Bool -> Bool -> Int -> [Jukebox.Term] -> Problem Clause -> Problem Clause
+flattenGoals backwardsGoal flattenNonGround flattenAll full depthMod hints prob =
   run (hints, prob) $ \(_, prob) -> do
-    let ts = usort $ extraTerms prob
+    let ts = filter depthOk $ usort $ extraTerms prob
     cs <- mapM define ts
     return (prob ++ cs)
   where
@@ -593,6 +652,10 @@
     isVar (Jukebox.Var _) = True
     isVar _ = False
 
+    depthOk t = depthMod == 1 || depth t `mod` depthMod == 0
+    depth (_f :@: ts) = 1 + maximum (0:map depth ts)
+    depth _ = 1
+
     define (f :@: ts) = do
       name <- newName f
       let vs  = Jukebox.vars ts
@@ -613,6 +676,24 @@
         ground u,
         v <- backwards (n-1) cs u ]
 
+hintGoals :: Problem Clause -> Problem Clause
+hintGoals prob =
+  prob ++ map define extraTerms
+  where
+    extraTerms = usort (concatMap input prob)
+    input Input{what = Clause (Bind _ [Neg (x Jukebox.:=: y)])} =
+      term x ++ term y
+    input _ = []
+
+    term t@(_f :@: ts) = t:concatMap term ts
+    term _ = []
+
+    define t =
+      Input{ident = Nothing, tag = "flattening", kind = Jukebox.Ax Definition, what = c, source = Unknown}
+      where
+        c = clause [Pos (Tru (hint :@: [t]))]
+        hint = name "$hint" ::: FunType [Jukebox.typ t] O
+
 addDistributivityHeuristic :: [Jukebox.Term] -> Problem Clause -> Problem Clause
 addDistributivityHeuristic hints prob =
   run (hints, prob) $ \(_, prob) -> do
@@ -739,19 +820,18 @@
       return $ Left (pre inp (Jukebox.Var ctx_var, ctx_minimal :@: []))
     identify inp = Left inp
 
-runTwee :: GlobalFlags -> TSTPFlags -> HornFlags -> [String] -> Config Constant -> CP.Config -> MainFlags -> (IO () -> IO ()) -> [Jukebox.Term] -> Problem Clause -> IO Answer
-runTwee globals (TSTPFlags tstp) horn precedence config0 cpConfig flags@MainFlags{..} later hints obligs = {-# SCC runTwee #-} do
+runTwee :: GlobalFlags -> TSTPFlags -> HornFlags -> [String] -> Config Constant -> MainFlags -> (IO () -> IO ()) -> [Jukebox.Term] -> Problem Clause -> IO Answer
+runTwee globals (TSTPFlags tstp) horn precedence config0 flags@MainFlags{..} later hints obligs = {-# SCC runTwee #-} do
   let
     -- Encode whatever needs encoding in the problem
     obligs1
-      | flags_flatten_goals_lightly = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground False False hints obligs
-      | flags_flatten_all = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground True True hints obligs
-      | flags_flatten_goals = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground False True hints obligs
+      | flags_flatten_goals_lightly = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground False False flags_flatten_every hints obligs
+      | flags_flatten_all = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground True True flags_flatten_every hints obligs
+      | flags_flatten_goals = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground False True flags_flatten_every hints obligs
       | otherwise = obligs
     obligs2
       | flags_distributivity_heuristic = addDistributivityHeuristic hints obligs1
       | otherwise = obligs1
-    ctx = makeContext hints obligs2
     lowercaseSkolem x
       | hasLabel "skolem" x =
         withRenamer x $ \s i ->
@@ -759,7 +839,9 @@
             Renaming xss xs ->
               Renaming (map (map toLower) xss) (map toLower xs)
       | otherwise = x
-    (hints', prob) = prettyNames (mapName lowercaseSkolem (hints, addNarrowing flags_equals_transformation ctx obligs2))
+    (hints', prettyObligs) = prettyNames (mapName lowercaseSkolem (hints, obligs2))
+    ctx = makeContext hints' prettyObligs
+    prob = addNarrowing flags_equals_transformation ctx prettyObligs
 
   (unsortedAxioms0, goals0) <-
     case identifyProblem ctx prob of
@@ -776,20 +858,38 @@
     prec c =
       Precedence
         (isType c)
+#ifdef USE_LPO
+        ((hasLabel "equals" c && Jukebox.arity c == 2) || isIfeq c)
+#else
         (Just c == maxUnary)
-        (isNothing (elemIndex (base c) precedence))
+#endif
+        (isJust (elemIndex (base c) precedence))
         (fmap negate (elemIndex (base c) precedence))
         (maybeNegate (Map.findWithDefault 0 c funOccs))
     maybeNegate = if flags_flip_ordering then negate else id
     funOccs = funsOcc prob
+#ifndef USE_LPO
     maxUnary =
       case filter (\(f, _) -> arity f == 1 && not (isType f)) (Map.toList funOccs) of
         [] -> Nothing
         xs -> Just (fst (maximumBy (comparing snd) xs))
+#endif
 
     -- Translate everything to Twee.
-    toTerm t = tweeTerm flags horn ctx prec t
-    toEquation (t, u) = canonicalise (toTerm t :=: toTerm u)
+    toTerm var t = tweeTerm flags horn ctx var prec t
+    varNums :: Jukebox.Symbolic a => a -> Jukebox.Variable -> Int
+    varNums t = \x -> Map.findWithDefault undefined x ids
+      where
+        xs = usort (vars t)
+        ids = Map.fromList (zip xs [0..])
+    toEquation (t, u) =
+      toTerm var t :=: toTerm var u
+      where
+        var = varNums (t, u)
+    equationVars (t, u) =
+      Map.fromList [(V n, base (name x)) | x <- vars (t, u), let n = var x]
+      where
+        var = varNums (t, u)
 
     axiomCompare ax1 ax2
       | isEquality ax1' && not (isEquality ax2') = GT
@@ -807,7 +907,7 @@
       [ goal n pre_name (toEquation pre_eqn)
       | (n, PreEquation{..}) <- zip [1..] goals0 ]
     axioms =
-      [ Axiom n pre_name (toEquation pre_eqn)
+      [ Axiom n pre_name (Just (equationVars pre_eqn)) (toEquation pre_eqn)
       | (n, PreEquation{..}) <- zip [1..] axioms0 ]
     defs =
       [ axiom
@@ -818,27 +918,29 @@
 
   -- Compute CP scoring heuristic
   let
+    {-
     goalNests = nests (map goal_eqn goals)
     goalOccs = occs (map goal_eqn goals)
     score depth hints eqn
       | flags_goal_heuristic =
-        CP.score cpConfig depth hints eqn *
+        scoreCP cpConfig depth hints eqn *
         product
           [ pos (IntMap.findWithDefault 0 f eqnNests - IntMap.findWithDefault 0 f goalNests) *
             pos (IntMap.findWithDefault 0 f eqnOccs - IntMap.findWithDefault 0 f goalOccs)
           | f <- IntMap.keys eqnNests ] -- skip constants
       | otherwise = 
-        CP.score cpConfig depth hints eqn
+        scoreCP cpConfig depth hints eqn
       where
         eqnNests = nests eqn
         eqnOccs = occs eqn
 
         pos :: Int -> Float
         pos n = if n <= 0 then 1 else fromIntegral n+1
-    config = config0 { cfg_score_cp = score, cfg_eliminate_axioms = if flags_flatten_regeneralise then defs else [] }
+    -}
+    config = config0 { cfg_eliminate_axioms = if flags_flatten_regeneralise then defs else [] }
 
   let
-    withHints = foldl' (addHint config) (initialState config) (map toTerm hints')
+    withHints = foldl' (addHint config) (initialState config) [toTerm (varNums h) h | h <- hints']
     withGoals = foldl' (addGoal config) withHints goals
     withAxioms = foldl' (addAxiom config) withGoals axioms
     withBackwardsGoal = foldn rewriteGoalsBackwards withAxioms flags_backwards_goal
@@ -908,16 +1010,53 @@
   forM_ axioms $ \Axiom{..} ->
     say $ show $ nest 2 $
       describeEquation "Axiom"
-        (show axiom_number) (Just axiom_name) axiom_eqn
+        (show axiom_number) (Just axiom_name) axiom_vars axiom_eqn
   forM_ goals $ \Goal{..} ->
     say $ show $ nest 2 $
       describeEquation "Goal"
-        (show goal_number) (Just goal_name) goal_eqn
+        (show goal_number) (Just goal_name) Nothing goal_eqn
   line
 
-  state <- complete output config withBackwardsGoal
+  state <-
+    case flags_stitch of
+      Nothing -> do
+        complete output config withBackwardsGoal
+      Just stitch -> do
+        let
+          (timeout, final_timeout) =
+            case cfg_max_time config of
+              Just time -> (time / 5, Just (time * 4 / 5))
+              Nothing -> (30, Nothing)
+        intermediate <- complete output config{cfg_max_time = Just timeout} withBackwardsGoal
+        let
+          score rule =
+            (KBO.size (lhs rule), lhs rule,
+             KBO.size (rhs rule), rhs rule)
+          actives =
+            sortBy (comparing (score . active_rule)) $
+            IntMap.elems (st_active_set intermediate)
+          pres = present (cfg_proof_presentation config){cfg_all_lemmas = True} (map active_proof actives) []
+          proofStr = show (pPrintPresentation (cfg_proof_presentation config){cfg_use_colour = False} pres)
+        line
+        say "Running Stitch..."
+        hintsStrs <- lines <$> readProcess stitch [] proofStr
+        let toTerm' t = toTerm (varNums t) t
+        let parseTerm str = toTerm' (Snippet.giveProblem prob (Snippet.form (TPTP.term TPTP.NoQuantification Map.empty)) str)
+        let hints = map parseTerm hintsStrs
+        mapM_ (say . show . pPrint) hints
+        let config' = config{cfg_max_time = final_timeout}
+        complete output config' $
+          interreduce config' $
+          simplifyQueue config' $
+          foldl' (addHint config') intermediate hints
+
   line
 
+  case flags_dump_state of
+    Nothing -> return ()
+    Just dumpStateFile ->
+      BS.writeFile dumpStateFile (encode state)
+
   when (solved state && flags_proof) $ later $ do
     let
       cfg_present
@@ -927,6 +1066,11 @@
           cfg_proof_presentation config
       pres = present cfg_present [] $ map (eliminateDefinitionsFromGoal defs) $ solutions state
 
+    case flags_dump_proof of
+      Nothing -> return ()
+      Just dumpProofFile ->
+        BS.writeFile dumpProofFile (encode pres)
+
     sayTrace ""
     forM_ (pres_axioms pres) $ \p ->
       sayTrace $ show $
@@ -954,8 +1098,8 @@
             Just inp -> go inp
            where
             go Input{source = Unknown} = []
-            go Input{source = Inference _ _ inps} = concatMap (go . inputValue) inps
-            go inp@Input{source = FromFile _ _} = [inp]
+            go Input{source = Inference _ _ _ inps} = concatMap (go . inputValue) inps
+            go inp@Input{source = FromFile _ _ _} = [inp]
 
       when flags_explain_encoding $ do
         putStrLn "Take the following subset of the input axioms:"
@@ -982,6 +1126,11 @@
       putStrLn ""
   
     when (tstp && flags_formal_proof) $ do
+      forM_ (pres_goals pres) $ \ProvedGoal{..} ->
+        unless (pg_witness_hint == emptySubst) $ do
+          let varName x = fromJust (Map.lookup x (fromJust pg_vars))
+          let answer = intercalate ", " [varName x ++ "->" ++ prettyShow t | (x, t) <- substToList pg_witness_hint]
+          putStrLn $ "% SZS answers Tuple [[" ++ answer ++ "]|_] for " ++ pg_name
       putStrLn "% SZS output start CNFRefutation"
       print $ pPrintProof $
         presentToJukebox ctx (curry toEquation)
@@ -1117,7 +1266,7 @@
           -- Check if this looks like the correct clause;
           -- if not, try its ancestors.
           find inp | ok inp = [inp]
-          find Input{source = Inference _ _ inps} =
+          find Input{source = Inference _ _ _ inps} =
             concatMap (find . inputValue) inps
           find _ = []
 
@@ -1137,9 +1286,9 @@
   stampM (intern "twee") . join . parseCommandLineWithExtraArgs
     ["--no-conjunctive-conjectures", "--no-split"]
 #ifdef VERSION_twee
-    "Twee, an equational theorem prover" . version ("twee version " ++ VERSION_twee) $
+    "Twee, the wonderful equation engine" . version ("twee version " ++ VERSION_twee) $
 #else
-    "Twee, an equational theorem prover" . version "twee development version" $
+    "Twee, the wonderful equation engine" . version "twee development version" $
 #endif
       globalFlags *> parseMainFlags *>
       -- hack: get --quiet and --no-proof options to appear before --tstp
@@ -1150,7 +1299,6 @@
            (combine <$>
              expert hornToUnitBox <*>
              parseConfig <*>
-             parseCPConfig <*>
              parseMainFlags <*>
              (toFormulasBox =>>=
               expert (toFof <$> clausifyBox <*> pure (tags True)) =>>=
@@ -1161,8 +1309,9 @@
     getHint Input{what = Clause (Bind _ [Pos (Tru (hint :@: [t]))])}
       | base (name hint) == "$hint" = Left t
     getHint c = Right c
-    combine horn config cpConfig main encode prove later prob0 = do
-      let (hints, nonHints) = partitionEithers (map getHint prob0)
+    combine horn config main encode prove later prob0 = do
+      let prob1 = if flags_hint_goals main then hintGoals prob0 else prob0
+      let (hints, nonHints) = partitionEithers (map getHint prob1)
       res <- horn nonHints
       case res of
         Left ans -> return ans
@@ -1171,6 +1320,6 @@
             isUnitEquality [Pos (_ Jukebox.:=: _)] = True
             isUnitEquality [Neg (_ Jukebox.:=: _)] = True
             isUnitEquality _ = False
-            isUnit = all isUnitEquality (map (toLiterals . what) prob0)
+            isUnit = all isUnitEquality (map (toLiterals . what) prob1)
             main' = if isUnit then main{flags_explain_encoding = False} else main{flags_formal_proof = False}
-          encode prob >>= prove config cpConfig main' later hints
+          encode prob >>= prove config main' later hints
diff --git a/executable/link.c b/executable/link.c
new file mode 100644
--- /dev/null
+++ b/executable/link.c
@@ -0,0 +1,12 @@
+#include <sys/prctl.h>
+#include <sys/signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+void link_to_parent(pid_t parent) {
+    prctl(PR_SET_PDEATHSIG, SIGTERM);
+
+    pid_t ppid = getppid();
+    if (ppid != parent)
+        exit(1);
+}
diff --git a/misc/BestTwee.hs b/misc/BestTwee.hs
--- a/misc/BestTwee.hs
+++ b/misc/BestTwee.hs
@@ -14,15 +14,6 @@
 import Data.Map(Map)
 import Data.FileEmbed
 
-solvedInTime :: NominalDiffTime -> FilePath -> String -> IO Bool
-solvedInTime timeLimit dir prob = do
-  let
-    stdout = dir </> prob ++ ".p.stdout"
-    stderr = dir </> prob ++ ".p.stderr"
-  outTime <- getModificationTime stdout
-  errTime <- getModificationTime stderr
-  return (diffUTCTime outTime errTime <= timeLimit)
-
 notE :: [(String, Double)]
 notE = filter (\(x, _) -> '+' `notElem` x) [
   ("GRP702+1", 0.06), ("GRP715+1", 0.06), ("GRP660+2", 0.12), ("GRP660+3", 0.12),
@@ -54,10 +45,12 @@
 ratings :: Map String Double
 ratings =
   Map.fromList
-    [ (name, read rating)
+    [ (strip ".p" name, read rating)
     | [name, rating] <- map words (lines input)]
   where
     input = $(embedStringFile "ratings")
+    strip suf str
+      | suf `isSuffixOf` str = take (length str - length suf) str
 
 problemBonus :: (Int, Int, Int, Int, Int, Int) -> String -> Int
 problemBonus (b0, b1, b2, b3, b4, b5) p =
@@ -90,15 +83,12 @@
    ("rating 1", (0, 0, 0, 0, 0, 1))]
 
 readResults ok = do
-  filenames <- glob "/home/nick/twee-out/*/times"
+  filenames <- glob "results/*/times"
   fmap (filter (\(x, _) -> x `notElem` banned)) $ forM filenames $ \filename -> do
     let name = takeFileName (takeDirectory filename)
     let unpack xs = (takeBaseName name, read time :: Double) where [name, time] = words xs
     solved <- filter (ok . fst) . map unpack . lines <$> readFile filename
     let solvedInTime t = [name | (name, time) <- solved, time < t]
---    fast <- filterM (solvedInTime 120 directory) solved
---    med  <- filterM (solvedInTime 240 directory) solved
---    slow <- filterM (solvedInTime 600 directory) solved
     let fast = solvedInTime 120
     let med  = solvedInTime 210
     let slow = solvedInTime (1/0)
diff --git a/misc/HornProof.hs b/misc/HornProof.hs
new file mode 100644
--- /dev/null
+++ b/misc/HornProof.hs
@@ -0,0 +1,1038 @@
+-- | Proofs of Horn formulas. Modelled on Twee.Proof.
+{-# LANGUAGE OverloadedStrings, DeriveAnyClass #-}
+module Twee.Proof.Horn(
+  -- * Constructing proofs
+  Proof, Derivation(..), Axiom(..),
+  certify, equation, derivation,
+  -- ** Smart constructors for derivations
+  lemma, autoSubst, simpleLemma, axiom, symm, trans, cong, congPath,
+
+  -- * Analysing proofs
+  simplify, steps, stepTerms, usedLemmas, usedAxioms, usedLemmasAndSubsts, usedAxiomsAndSubsts,
+  groundAxiomsAndSubsts, eliminateDefinitions, eliminateDefinitionsFromGoal,
+  simplifyProof, generaliseProof,
+
+  -- * Pretty-printing proofs
+  Config(..), defaultConfig, Presentation(..),
+  ProvedGoal(..), provedGoal, checkProvedGoal,
+  pPrintPresentation, present, describeEquation) where
+
+import Twee.Base hiding (invisible)
+import Twee.Equation
+import Twee.Utils
+import qualified Twee.Index as Index
+import Control.Monad
+import Data.Maybe
+import Data.List hiding (singleton)
+import Data.Ord
+import qualified Data.Set as Set
+import Data.Set(Set)
+import qualified Data.Map.Strict as Map
+import Data.Map(Map)
+import qualified Data.IntMap.Strict as IntMap
+import Control.Monad.Trans.State.Strict
+import Data.Graph
+import Twee.Profile
+import qualified Data.Binary.Sharing as Binary
+import Data.Binary.Sharing(Binary, Shared(..))
+import GHC.Generics
+import Data.Hashable
+import qualified Twee.Proof as Eq
+
+----------------------------------------------------------------------
+-- Equational proofs. Only valid proofs can be constructed.
+----------------------------------------------------------------------
+
+-- | A checked proof. Construct using 'certify'.
+data Proof f =
+  Proof {
+    context    :: !(Set (Equation f)),
+    equation   :: !(Equation f),
+    derivation :: !(Derivation f) }
+  deriving Show
+
+-- | An unchecked proof.
+data Derivation f =
+    -- | Apply an existing rule (with proof!) to the root of a term
+    UseLemma {-# UNPACK #-} !(Proof f) !(Subst f)
+    -- | Apply an axiom to the root of a term
+  | UseAxiom {-# UNPACK #-} !(Axiom f) !(Subst f)
+    -- Using from the context.
+  | UseContext !(Equation f)
+    -- | Reflexivity. @'Refl' t@ proves @t = t@.
+  | Refl !(Term f)
+    -- | Symmetry
+  | Symm !(Derivation f)
+    -- | Transivitity
+  | Trans !(Derivation f) !(Derivation f)
+    -- | Congruence.
+    -- Parallel, i.e., takes a function symbol and one derivation for each
+    -- argument of that function.
+  | Cong {-# UNPACK #-} !(Sym f) ![Derivation f]
+    -- | Resolution.
+  | Resolve !(Derivation f) !(Derivation f)
+  deriving (Eq, Show, Generic, Hashable)
+
+--  | An axiom, which comes without proof.
+data Axiom f =
+  Axiom {
+    -- | The number of the axiom.
+    -- Has no semantic meaning; for convenience only.
+    axiom_number :: {-# UNPACK #-} !Int,
+    -- | A description of the axiom.
+    -- Has no semantic meaning; for convenience only.
+    axiom_name :: !String,
+    axiom_context :: !(Set (Equation f)),
+    -- | The equation which the axiom asserts.
+    axiom_eqn :: !(Equation f) }
+  deriving (Eq, Ord, Show, Generic, Hashable)
+
+-- | Checks a 'Derivation' and, if it is correct, returns a
+-- certified 'Proof'.
+--
+-- If the 'Derivation' is incorrect, throws an exception.
+
+-- This is the trusted core of the module.
+{-# INLINEABLE certify #-}
+certify :: Derivation f -> Proof f
+certify p =
+  stamp "certify proof" $
+  case check p of
+    Nothing -> error "Invalid proof created!"
+    Just (ctx, eqn) -> Proof ctx eqn p
+  where
+    check (UseLemma proof sub) =
+      return (Set.map (subst sub) (context proof), subst sub (equation proof))
+    check (UseAxiom Axiom{..} sub) =
+      return (Set.map (subst sub) axiom_context, subst sub axiom_eqn)
+    check (UseContext eqn) =
+      return (Set.singleton eqn, eqn)
+    check (Refl t) =
+      return (Set.empty, t :=: t)
+    check (Symm p) = do
+      (ctx, t :=: u) <- check p
+      return (ctx, u :=: t)
+    check (Trans p q) = do
+      (ctx1, t :=: u1) <- check p
+      (ctx2, u2 :=: v) <- check q
+      guard (u1 == u2)
+      return (Set.union ctx1 ctx2, t :=: v)
+    check (Cong f ps) = do
+      (ctxs, eqns) <- unzip <$> mapM check ps
+      return
+        (Set.unions ctxs,
+         build (app f (map eqn_lhs eqns)) :=:
+         build (app f (map eqn_rhs eqns)))
+    check (Resolve p q) = do
+      (ctx1, eqn1) <- check p
+      (ctx2, eqn2) <- check q
+      guard (eqn1 `Set.member` ctx2)
+      return (Set.union ctx1 (Set.delete eqn1 ctx2), eqn2)
+
+----------------------------------------------------------------------
+-- Everything below this point need not be trusted, since all proof
+-- construction goes through the "certify" function.
+--
+-- N.B.: For this reason, the code below must never directly invoke
+-- the Proof constructor!
+----------------------------------------------------------------------
+
+-- Typeclass instances.
+instance Eq (Proof f) where
+  x == y = compare x y == EQ
+instance Ord (Proof f) where
+  -- Don't look at the proof itself, to prevent exponential blowup
+  -- when a proof contains UseLemma
+  compare = comparing (\p -> (context p, equation p))
+instance Hashable (Proof f) where
+  hashWithSalt s p = hashWithSalt s (context p, equation p)
+
+instance Symbolic (Derivation f) where
+  type ConstantOf (Derivation f) = f
+  termsDL (UseLemma _ sub) = termsDL sub
+  termsDL (UseAxiom _ sub) = termsDL sub
+  termsDL (UseContext eq) = termsDL eq
+  termsDL (Refl t) = termsDL t
+  termsDL (Symm p) = termsDL p
+  termsDL (Trans p q) = termsDL p `mplus` termsDL q
+  termsDL (Cong _ ps) = termsDL ps
+  termsDL (Resolve p q) = termsDL p `mplus` termsDL q
+
+  subst_ sub (UseLemma lemma s) = UseLemma lemma (subst_ sub s)
+  subst_ sub (UseAxiom axiom s) = UseAxiom axiom (subst_ sub s)
+  subst_ sub (UseContext eq) = UseContext (subst_ sub eq)
+  subst_ sub (Refl t) = Refl (subst_ sub t)
+  subst_ sub (Symm p) = Symm (subst_ sub p)
+  subst_ sub (Trans p q) = Trans (subst_ sub p) (subst_ sub q)
+  subst_ sub (Cong f ps) = Cong f (subst_ sub ps)
+  subst_ sub (Resolve p q) = Resolve (subst_ sub p) (subst_ sub q)
+
+{-
+instance Function f => Pretty (Proof f) where
+  pPrint = pPrintLemma defaultConfig (prettyShow . axiom_number) (prettyShow . equation)
+instance (Intern f, PrettyTerm f) => Pretty (Derivation f) where
+  pPrint (UseLemma lemma sub) =
+    text "subst" <#> pPrintTuple [text "lemma" <+> pPrint (equation lemma), pPrint sub]
+  pPrint (UseAxiom axiom sub) =
+    text "subst" <#> pPrintTuple [pPrint axiom, pPrint sub]
+  pPrint (Refl t) =
+    text "refl" <#> pPrintTuple [pPrint t]
+  pPrint (Symm p) =
+    text "symm" <#> pPrintTuple [pPrint p]
+  pPrint (Trans p q) =
+    text "trans" <#> pPrintTuple [pPrint p, pPrint q]
+  pPrint (Cong f ps) =
+    text "cong" <#> pPrintTuple (pPrint f:map pPrint ps)
+
+instance (Intern f, PrettyTerm f) => Pretty (Axiom f) where
+  pPrint Axiom{..} =
+    text "axiom" <#>
+    pPrintTuple [pPrint axiom_number, text axiom_name, pPrint axiom_eqn]
+
+instance (Intern f, Binary f) => Binary (Axiom f) where
+  put Axiom{..} = Binary.put (Shared (axiom_number, axiom_name, axiom_eqn))
+  get = do
+    Shared (num, name, eqn) <- Binary.get
+    return (Axiom num name eqn)
+
+instance (Intern f, Binary f) => Binary (Proof f) where
+  put = Binary.put . Shared . derivation
+  get = certify . getShared <$> Binary.get
+
+foldLemmas :: (Intern f, PrettyTerm f) => (Map (Proof f) a -> Derivation f -> a) -> [Derivation f] -> Map (Proof f) a
+foldLemmas op ds =
+  execState (mapM_ foldGoal ds) Map.empty
+  where
+    foldGoal p = mapM_ foldLemma (usedLemmas p)
+    foldLemma p = do
+      m <- get
+      case Map.lookup p m of
+        Just x -> return x
+        Nothing -> do
+          mapM_ foldLemma (usedLemmas (derivation p))
+          m <- get
+          case Map.lookup p m of
+            Just x  -> return x
+            Nothing -> do
+              let x = op m (derivation p)
+              put (Map.insert p x m)
+              return x
+
+mapLemmas :: Function f => (Derivation f -> Derivation f) -> [Derivation f] -> [Derivation f]
+mapLemmas f ds = map (derivation . op lem) ds
+  where
+    op lem = certify . f . unfoldLemmas (\pf -> Just (simpleLemma (lem Map.! pf)))
+    lem = foldLemmas op ds
+
+allLemmas :: Function f => [Derivation f] -> [Proof f]
+allLemmas ds =
+  reverse [p | (_, p, _) <- map vertex (topSort graph)]
+  where
+    used = foldLemmas (\_ p -> usedLemmas p) ds
+    (graph, vertex, _) =
+      graphFromEdges
+        [((), p, ps) | (p, ps) <- Map.toList used]
+
+unfoldLemmas :: Minimal f => (Proof f -> Maybe (Derivation f)) -> Derivation f -> Derivation f
+unfoldLemmas lem p@(UseLemma q sub) =
+  case lem q of
+    Nothing -> p
+    Just r ->
+      -- Get rid of any variables that are not bound by sub
+      -- (e.g., ones which only occur internally in q)
+      subst sub (eraseExcept (substDomain sub) r)
+unfoldLemmas lem (Symm p) = symm (unfoldLemmas lem p)
+unfoldLemmas lem (Trans p q) = trans (unfoldLemmas lem p) (unfoldLemmas lem q)
+unfoldLemmas lem (Cong f ps) = cong f (map (unfoldLemmas lem) ps)
+unfoldLemmas _ p = p
+
+lemma :: Proof f -> Subst f -> Derivation f
+lemma p sub = UseLemma p sub
+
+simpleLemma :: Function f => Proof f -> Derivation f
+simpleLemma p =
+  UseLemma p (autoSubst (equation p))
+
+axiom :: Axiom f -> Derivation f
+axiom ax@Axiom{..} =
+  UseAxiom ax (autoSubst axiom_eqn)
+
+autoSubst :: Equation f -> Subst f
+autoSubst eqn =
+  fromJust $
+  listToSubst [(x, build (var x)) | x <- vars eqn]
+
+symm :: Derivation f -> Derivation f
+symm (Refl t) = Refl t
+symm (Symm p) = p
+symm (Trans p q) = trans (symm q) (symm p)
+symm (Cong f ps) = cong f (map symm ps)
+symm p = Symm p
+
+trans :: Derivation f -> Derivation f -> Derivation f
+trans Refl{} p = p
+trans p Refl{} = p
+trans (Trans p q) r =
+  -- Right-associate uses of transitivity.
+  -- p cannot be a Trans (if it was created with the smart
+  -- constructors) but q could be.
+  Trans p (trans q r)
+trans p q = Trans p q
+
+cong :: Sym f -> [Derivation f] -> Derivation f
+cong f ps =
+  case sequence (map unRefl ps) of
+    Nothing -> Cong f ps
+    Just ts -> Refl (build (app f ts))
+  where
+    unRefl (Refl t) = Just t
+    unRefl _ = Nothing
+
+-- Transform a proof so that each step uses exactly one axiom
+-- or lemma. The proof will have the following form afterwards:
+--   * Trans only occurs at the outermost level and is right-associated
+--   * Each Cong has exactly one non-Refl argument (no parallel rewriting)
+--   * Symm only occurs innermost, i.e., next to UseLemma or UseAxiom
+--   * Refl only occurs as an argument to Cong, or outermost if the
+--     whole proof is a single reflexivity step
+flattenDerivation :: Function f => Derivation f -> Derivation f
+flattenDerivation p =
+  fromSteps (equation (certify p)) (steps p)
+
+-- | Simplify a derivation so that:
+--   * Symm occurs innermost
+--   * Trans is right-associated
+--   * Each Cong has at least one non-Refl argument
+--   * Refl is not used unnecessarily
+simplify :: Function f => Derivation f -> Derivation f
+simplify (Symm p) = symm (simplify p)
+simplify (Trans p q) = trans (simplify p) (simplify q)
+simplify (Cong f ps) = cong f (map simplify ps)
+simplify p
+  | t == u = Refl t
+  | otherwise = p
+  where
+    t :=: u = equation (certify p)
+
+-- | Transform a derivation into a list of single steps.
+--   Each step has the following form:
+--     * Trans does not occur
+--     * Symm only occurs innermost, i.e., next to UseLemma or UseAxiom
+--     * Each Cong has exactly one non-Refl argument (no parallel rewriting)
+--     * Refl only occurs as an argument to Cong
+steps :: Function f => Derivation f -> [Derivation f]
+steps = steps1 . simplify
+  where
+    steps1 p@UseAxiom{} = [p]
+    steps1 p@UseLemma{} = [p]
+    steps1 (Refl _) = []
+    steps1 (Symm p) = map symm (reverse (steps1 p))
+    steps1 (Trans p q) = steps1 p ++ steps1 q
+    steps1 p@(Cong f qs) =
+      concat [ map (inside i) (steps1 q) | (i, q) <- zip [0..] qs ]
+      where
+        App _ ts :=: App _ us = equation (certify p)
+        inside i p =
+          Cong f $
+            map Refl (take i (unpack us)) ++
+            [p] ++
+            map Refl (drop (i+1) (unpack ts))
+
+-- | Convert a list of steps (plus the equation it is proving)
+-- back to a derivation.
+fromSteps :: Equation f -> [Derivation f] -> Derivation f
+fromSteps (t :=: _) [] = Refl t
+fromSteps _ ps = foldr1 Trans ps
+
+-- | Given a derivation, compute which terms it goes through.
+stepTerms :: Function f => Derivation f -> [Term f]
+stepTerms p =
+  case steps p of
+    [] -> [eqn_lhs (equation (certify p))]
+    s:ss ->
+      eqn_lhs (equation (certify s)):
+      map (eqn_rhs . equation . certify) (s:ss)
+
+-- | Find peak terms in a derivation.
+peakTerms :: Function f => Derivation f -> [Term f]
+peakTerms = peaks . stepTerms
+  where
+    peaks [] = []
+    peaks [t] = [t]
+    peaks (t:u:ts)
+      | lessEq t u = peaks (u:ts)
+      | lessEq u t = peaks (t:ts)
+      | otherwise = t:peaks (u:ts)
+      -- TODO do more carefully?
+      -- handle this case t --> v <-- u where e.g. t <= u (should still be counted as a peak perhaps)
+
+-- | Find all lemmas which are used in a derivation.
+usedLemmas :: Derivation f -> [Proof f]
+usedLemmas p = map fst (usedLemmasAndSubsts p)
+
+-- | Find all lemmas which are used in a derivation,
+-- together with the substitutions used.
+usedLemmasAndSubsts :: Derivation f -> [(Proof f, Subst f)]
+usedLemmasAndSubsts p = lem p []
+  where
+    lem (UseLemma p sub) = ((p, sub):)
+    lem (Symm p) = lem p
+    lem (Trans p q) = lem p . lem q
+    lem (Cong _ ps) = foldr (.) id (map lem ps)
+    lem _ = id
+
+-- | Find all axioms which are used in a derivation.
+usedAxioms :: Derivation f -> [Axiom f]
+usedAxioms p = map fst (usedAxiomsAndSubsts p)
+
+-- | Find all axioms which are used in a derivation,
+-- together with the substitutions used.
+usedAxiomsAndSubsts :: Derivation f -> [(Axiom f, Subst f)]
+usedAxiomsAndSubsts p = ax p []
+  where
+    ax (UseAxiom axiom sub) = ((axiom, sub):)
+    ax (Symm p) = ax p
+    ax (Trans p q) = ax p . ax q
+    ax (Cong _ ps) = foldr (.) id (map ax ps)
+    ax _ = id
+
+-- | Find all ground instances of axioms which are used in the
+-- expanded form of a derivation (no lemmas).
+groundAxiomsAndSubsts :: Function f => Derivation f -> Map (Axiom f) (Set (Subst f))
+groundAxiomsAndSubsts p = ax lem p
+  where
+    lem = foldLemmas ax [p]
+
+    ax _ (UseAxiom axiom sub) =
+      Map.singleton axiom (Set.singleton sub)
+    ax lem (UseLemma lemma sub) =
+      Map.map (Set.map substAndErase) (lem Map.! lemma)
+      where
+        substAndErase sub' =
+          eraseExcept (vars sub) (subst sub sub')
+    ax lem (Symm p) = ax lem p
+    ax lem (Trans p q) = Map.unionWith Set.union (ax lem p) (ax lem q)
+    ax lem (Cong _ ps) = Map.unionsWith Set.union (map (ax lem) ps)
+    ax _ _ = Map.empty
+
+eliminateDefinitionsFromGoal :: Function f => [Axiom f] -> ProvedGoal f -> ProvedGoal f
+eliminateDefinitionsFromGoal axioms pg =
+  pg {
+    pg_proof = certify (eliminateDefinitions axioms (derivation (pg_proof pg))) }
+
+eliminateDefinitions :: Function f => [Axiom f] -> Derivation f -> Derivation f
+eliminateDefinitions [] p = p
+eliminateDefinitions axioms p = head (mapLemmas elim [p])
+  where
+    elim (UseAxiom axiom sub)
+      | axiom `Set.member` axSet =
+        Refl (term (subst sub (eqn_rhs (axiom_eqn axiom))))
+      | otherwise = UseAxiom axiom (elimSubst sub)
+    elim (UseLemma lemma sub) =
+      UseLemma lemma (elimSubst sub)
+    elim (Refl t) = Refl (term t)
+    elim (Symm p) = Symm (elim p)
+    elim (Trans p q) = Trans (elim p) (elim q)
+    elim (Cong f ps) =
+      case find (build (app f (map var vs))) of
+        Nothing -> Cong f (map elim ps)
+        Just (rhs, Subst sub) ->
+          let proof (Cons (Var (V x)) Nil) = qs !! x in
+          replace (proof <$> sub) rhs
+      where
+        vs = map V [0..length ps-1]
+        qs = map (simpleLemma . certify . elim) ps -- avoid duplicating proofs of ts
+
+    elimSubst (Subst sub) = Subst (singleton <$> term <$> unsingleton <$> sub)
+      where
+        unsingleton (Cons t Nil) = t
+
+    term = build . term'
+    term' (Var x) = var x
+    term' t@(App f ts) =
+      case find t of
+        Nothing -> app f (map term' (unpack ts))
+        Just (rhs, sub) ->
+          term' (subst sub rhs)
+
+    find t =
+      listToMaybe $ do
+        (_, UseAxiom Axiom{axiom_eqn = l :=: r} _) <- Index.matches t idx
+        let Just sub = match l t
+        return (r, sub)
+
+    replace sub (Var (V x)) =
+      IntMap.findWithDefault undefined x sub
+    replace sub (App f ts) =
+      cong f (map (replace sub) (unpack ts))
+
+    axSet = Set.fromList axioms
+    idx = Index.fromList [(eqn_lhs (axiom_eqn ax), axiom ax) | ax <- axioms]
+
+-- | Applies a derivation at a particular path in a term.
+congPath :: [Int] -> Term f -> Derivation f -> Derivation f
+congPath [] _ p = p
+congPath (n:ns) (App f t) p | n <= length ts =
+  cong f $
+    map Refl (take n ts) ++
+    [congPath ns (ts !! n) p] ++
+    map Refl (drop (n+1) ts)
+  where
+    ts = unpack t
+congPath _ _ _ = error "bad path"
+
+----------------------------------------------------------------------
+-- Pretty-printing of proofs.
+----------------------------------------------------------------------
+
+-- | Options for proof presentation.
+data Config f =
+  Config {
+    -- | Never inline lemmas.
+    cfg_all_lemmas :: !Bool,
+    -- | Inline all lemmas.
+    cfg_no_lemmas :: !Bool,
+    -- | Make the proof ground.
+    cfg_ground_proof :: !Bool,
+    -- | Print out explicit substitutions.
+    cfg_show_instances :: !Bool,
+    -- | Print out proofs in colour.
+    cfg_use_colour :: !Bool,
+    -- | Print out which instances of some axioms were used.
+    cfg_show_uses_of_axioms :: Axiom f -> Bool,
+    -- | Print out peaks of each lemma.
+    cfg_show_peaks :: !Bool,
+    -- | Eliminate $equals from the proofs.
+    cfg_eliminate_existentials_coding :: !Bool,
+    -- | Show which subterm is rewritten.
+    cfg_show_subterms :: !Bool }
+
+-- | The default configuration.
+defaultConfig :: Config f
+defaultConfig =
+  Config {
+    cfg_all_lemmas = False,
+    cfg_no_lemmas = False,
+    cfg_ground_proof = False,
+    cfg_show_instances = False,
+    cfg_use_colour = False,
+    cfg_show_uses_of_axioms = const False,
+    cfg_show_peaks = False,
+    cfg_eliminate_existentials_coding = True,
+    cfg_show_subterms = False }
+
+-- | A proof, with all axioms and lemmas explicitly listed.
+data Presentation f =
+  Presentation {
+    -- | The used axioms.
+    pres_axioms :: [Axiom f],
+    -- | The used lemmas.
+    pres_lemmas :: [Proof f],
+    -- | The goals proved.
+    pres_goals  :: [ProvedGoal f] }
+  deriving (Show, Generic, Binary)
+
+-- Note: only the pg_proof field should be trusted!
+-- The remaining fields are for information only.
+data ProvedGoal f =
+  ProvedGoal {
+    pg_number  :: Int,
+    pg_name    :: String,
+    pg_proof   :: Proof f,
+
+    -- Extra fields for existentially-quantified goals, giving the original goal
+    -- and the existential witness. These fields are not verified. If you want
+    -- to check them, use checkProvedGoal.
+    --
+    -- In general, subst pg_witness_hint pg_goal_hint == equation pg_proof.
+    -- For non-existential goals, pg_goal_hint == equation pg_proof
+    -- and pg_witness_hint is the empty substitution.
+    pg_goal_hint    :: Equation f,
+    pg_witness_hint :: Subst f }
+  deriving (Show, Generic, Binary)
+
+-- | Construct a @ProvedGoal@.
+provedGoal :: Int -> String -> Proof f -> ProvedGoal f
+provedGoal number name proof =
+  ProvedGoal {
+    pg_number = number,
+    pg_name = name,
+    pg_proof = proof,
+    pg_goal_hint = equation proof,
+    pg_witness_hint = emptySubst }
+
+-- | Check that pg_goal/pg_witness match up with pg_proof.
+checkProvedGoal :: Function f => ProvedGoal f -> ProvedGoal f
+checkProvedGoal pg@ProvedGoal{..}
+  | subst pg_witness_hint pg_goal_hint == equation pg_proof =
+    pg
+  | otherwise =
+    error $ show $
+      text "Invalid ProvedGoal!" $$
+      text "Claims to prove" <+> pPrint pg_goal_hint $$
+      text "with witness" <+> pPrint pg_witness_hint <#> text "," $$
+      text "but actually proves" <+> pPrint (equation pg_proof)
+
+instance Function f => Pretty (Presentation f) where
+  pPrint = pPrintPresentation defaultConfig
+
+-- | Simplify and present a proof.
+present :: Function f => Config f -> [Proof f] -> [ProvedGoal f] -> Presentation f
+present config@Config{..} extraLemmas goals =
+  Presentation axioms lemmas goals'
+  where
+    ps =
+      mapLemmas flattenDerivation $
+      simplifyProof config $ map (derivation . pg_proof) goals
+
+    goals' =
+      [ decodeGoal config (goal{pg_proof = certify p})
+      | (goal, p) <- zip goals ps ]
+
+    axioms = usort $
+      concatMap (usedAxioms . derivation . pg_proof) goals' ++
+      concatMap (usedAxioms . derivation) lemmas
+
+    lemmas = allLemmas (map simpleLemma extraLemmas ++ map (derivation . pg_proof) goals')
+
+groundProof :: Function f => [Derivation f] -> [Derivation f]
+groundProof ds
+  | all (isGround . equation) (allLemmas ds) = ds
+  | otherwise = groundProof (mapLemmas f ds)
+  where
+    f (UseLemma lemma sub) =
+      simpleLemma $ certify $
+      eraseExcept (vars sub) $
+      subst sub $
+      derivation lemma
+    f p@UseAxiom{} = p
+    f p@Refl{} = p
+    f (Symm p) = Symm (f p)
+    f (Trans p q) = Trans (f p) (f q)
+    f (Cong fun ps) = Cong fun (map f ps)
+
+simplifyProof :: Function f => Config f -> [Derivation f] -> [Derivation f]
+simplifyProof config@Config{..} goals =
+  canonicaliseLemmas (fixpointOn key simp' (fixpointOn key simp goals))
+  where
+    simpCore =
+      (inlineUsedOnceLemmas `onlyIf` not cfg_all_lemmas) .
+      inlineTrivialLemmas config .
+      tightenProof
+
+    simp = simpCore . generaliseProof True
+    -- generaliseProof undoes the effect of groundProof!
+    -- But we still want to run generaliseProof first, to simplify the proof
+    simp' = (simpCore . groundProof) `onlyIf` cfg_ground_proof
+
+    key ds =
+      (ds, [(equation p, derivation p) | p <- allLemmas ds])
+
+    pass `onlyIf` True = pass
+    _    `onlyIf` False = id
+
+simplificationPass ::
+  Function f =>
+  -- A transformation on lemmas
+  (Map (Proof f) (Derivation f) -> Proof f -> Derivation f) ->
+  -- A transformation on goals
+  (Map (Proof f) (Derivation f) -> Derivation f -> Derivation f) ->
+  [Derivation f] -> [Derivation f]
+simplificationPass lemma goal p = map (op goal lem) p
+  where
+    lem = foldLemmas (op (\lem -> lemma lem . certify)) p
+    op f lem p =
+      f lem (unfoldLemmas (\lemma -> Just (lem Map.! lemma)) p)
+
+inlineTrivialLemmas :: Function f => Config f -> [Derivation f] -> [Derivation f]
+inlineTrivialLemmas Config{..} =
+  -- A lemma is trivial if one of the following holds:
+  --   * It only has one step
+  --   * It is subsumed by an earlier lemma
+  --   * It has to do with $equals (for printing of the goal proof)
+  --   * The option cfg_no_lemmas is true
+  simplificationPass inlineTrivial (const id)
+  where
+    inlineTrivial lem p
+      | shouldInline p = derivation p
+      | (q:_) <- subsuming lem (equation p) = q
+      | otherwise = simpleLemma p
+
+    shouldInline p =
+      cfg_no_lemmas ||
+      length (filter (not . invisible) (map (equation . certify) (steps (derivation p)))) <= 1 ||
+      (cfg_eliminate_existentials_coding &&
+        (any (isJust . decodeEquality) [eqn_lhs (equation p), eqn_rhs (equation p)] ||
+         any isFalseTerm [eqn_lhs (equation p), eqn_rhs (equation p)] ||
+         any isTrueTerm [eqn_lhs (equation p), eqn_rhs (equation p)]))
+
+    subsuming lem (t :=: u) =
+      subsuming1 lem (t :=: u) ++
+      map symm (subsuming1 lem (u :=: t))
+    subsuming1 lem eq =
+      [ subst sub d
+      | (q, d) <- Map.toList lem,
+        sub <- maybeToList (matchEquation (equation q) eq) ]
+
+inlineUsedOnceLemmas :: Function f => [Derivation f] -> [Derivation f]
+inlineUsedOnceLemmas ds =
+  -- Inline any lemma that's only used once in the proof
+  simplificationPass (const inlineOnce) (const id) ds
+  where
+    uses = Map.unionsWith (+) $
+      map countUses ds ++ Map.elems (foldLemmas (const countUses) ds)
+
+    countUses p =
+      Map.fromListWith (+) (zip (usedLemmas p) (repeat (1 :: Int)))
+
+    inlineOnce p
+      | usedOnce p = derivation p
+      | otherwise = simpleLemma p
+      where
+        usedOnce p =
+          case Map.lookup p uses of
+            Just 1 -> True
+            _ -> False
+
+tightenProof :: Function f => [Derivation f] -> [Derivation f]
+tightenProof = mapLemmas tightenLemma
+  where
+    tightenLemma p =
+      fromSteps eq (map fst (fixpointOn length (tightenSteps eq) (zip ps eqs)))
+      where
+        eq = equation (certify p)
+        ps = steps p
+        eqs = map (equation . certify) ps
+
+    tightenSteps eq steps = head (cands ++ [steps])
+      where
+        -- Look for a segment of ps which can be removed, in the
+        -- sense that the terms at both ends of the segment are
+        -- unifiable without altering eq.
+        cands =
+          [ subst sub (before ++ after)
+          | (before, mid1) <- splits steps,
+            -- 'reverse' means we start with big segments.
+            (mid@(_:_), after) <- reverse (splits mid1),
+            let t :=: _ = snd (head mid)
+                _ :=: u = snd (last mid),
+            sub <- maybeToList (unify t u),
+            subst sub eq == eq ] ++
+          [ subst sub before
+          | (before, after@(_:_)) <- splits steps,
+            let t :=: _ = snd (head after)
+                _ :=: u = snd (last after),
+            sub <- maybeToList (match t u),
+            subst sub (eqn_lhs eq) == eqn_lhs eq ] ++
+          [ subst sub after
+          | (before@(_:_), after) <- reverse (splits steps),
+            let t :=: _ = snd (head before)
+                _ :=: u = snd (last before),
+            sub <- maybeToList (match u t),
+            subst sub (eqn_rhs eq) == eqn_rhs eq ]
+
+generaliseProof :: Function f => Bool -> [Derivation f] -> [Derivation f]
+generaliseProof instGoal =
+  simplificationPass (const generaliseLemma) (const generaliseGoal)
+  where
+    generaliseLemma p = lemma (certify q) sub
+      where
+        (q, sub) = generalise p
+    generaliseGoal p = if instGoal then subst sub q else q
+      where
+        (q, sub) = generalise (certify p)
+
+    generalise p = (q, sub)
+      where
+        eq = equation p
+        n = freshVar eq
+        qs = evalState (mapM generaliseStep (steps (derivation p))) n
+        Just sub1 = unifyMany (stepsConstraints qs)
+        q = canonicalise (fromSteps eq (subst sub1 qs))
+        Just sub = matchEquation (equation (certify q)) eq
+
+    generaliseStep (UseAxiom axiom _) =
+      freshen (vars (axiom_eqn axiom)) (UseAxiom axiom)
+    generaliseStep (UseLemma lemma _) =
+      freshen (vars (equation lemma)) (UseLemma lemma)
+    generaliseStep (Refl _) = do
+      n <- get
+      put (n+1)
+      return (Refl (build (var (V n))))
+    generaliseStep (Symm p) =
+      Symm <$> generaliseStep p
+    generaliseStep (Trans p q) =
+      liftM2 Trans (generaliseStep p) (generaliseStep q)
+    generaliseStep (Cong f ps) = do
+      q <- cong f <$> mapM generaliseStep ps
+      case q of
+        Refl{} -> generaliseStep q
+        _ -> return q
+
+    freshen xs f = do
+      n <- get
+      put (n + length xs)
+      let Just sub = listToSubst [(x, build (var (V i))) | (x, i) <- zip (usort xs) [n..]]
+      return (f sub)
+
+    stepsConstraints ps = zipWith combine eqs (tail eqs)
+      where
+        eqs = map (equation . certify) ps
+        combine (_ :=: t) (u :=: _) = (t, u)
+
+canonicaliseLemmas :: Function f => [Derivation f] -> [Derivation f]
+canonicaliseLemmas =
+  simplificationPass (const canonicaliseLemma) (const canonicalise)
+  where
+    -- Present the equation left-to-right, and with variables
+    -- named canonically
+    canonicaliseLemma p
+      | u `lessEqSkolem` t = canon (derivation p)
+      | otherwise = symm (canon (symm (derivation p)))
+      where
+        t :=: u = equation p
+        -- This ensures that we also renumber variables in the derivation that
+        -- do not occur in the equation, but that variables in the equation
+        -- get priority.
+        symbolic p = (equation p, derivation p)
+        before = symbolic p
+        after = canonicalise (symbolic p)
+        Just sub1 = matchManyList (terms before) (terms after)
+        Just sub2 = matchManyList (terms after) (terms before)
+        canon p = subst sub2 (simpleLemma (certify (subst sub1 p)))
+
+invisible :: Function f => Equation f -> Bool
+invisible (t :=: u) = show (pPrint t) == show (pPrint u)
+
+-- Pretty-print the proof of a single lemma.
+pPrintLemma :: Function f => Config f -> (Axiom f -> String) -> (Proof f -> String) -> Proof f -> Doc
+pPrintLemma Config{..} axiomNum lemmaNum p
+  | null qs = text "Reflexivity."
+  | equation (certify (fromSteps (equation p) qs)) == equation p =
+    vcat (zipWith pp hl qs) $$ ppTerm (HighlightedTerm [] Nothing) (eqn_rhs (equation p))
+  | otherwise = error "lemma changed by pretty-printing!"
+  where
+    qs = steps (derivation p)
+    hl = map highlightStep qs
+    peaks = Set.fromList (peakTerms (derivation p))
+
+    pp _ p | invisible (equation (certify p)) = pPrintEmpty
+    pp h p =
+      ppTerm (HighlightedTerm [green | cfg_use_colour] (Just h)) (eqn_lhs (equation (certify p))) $$
+      text "=" <+> highlight [bold | cfg_use_colour] (text "{" <+> ((text "by" <+> ppStep p) $$ if cfg_show_subterms then subtermInfo else pPrintEmpty) <+> text "}")
+      where
+        subtermInfo =
+          (text "from" <+> pPrint t) $$
+          (text "to" <+> pPrint u)
+        t :=: u = rewrittenSubterms p
+
+    highlightStep UseAxiom{} = []
+    highlightStep UseLemma{} = []
+    highlightStep (Symm p) = highlightStep p
+    highlightStep (Cong _ ps) = i:highlightStep p
+      where
+        [(i, p)] = filter (not . isRefl . snd) (zip [0..] ps)
+
+    rewrittenSubterms (Symm p) = u :=: t
+      where
+        t :=: u = rewrittenSubterms p
+    rewrittenSubterms (Cong _ ps) = rewrittenSubterms p
+      where
+        [p] = filter (not . isRefl) ps
+    rewrittenSubterms p = equation (certify p)
+
+    ppTerm decorate t = text "  " <#> pPrint (decorate t) <+> (if cfg_show_peaks && t `Set.member` peaks then text "(peak)" else pPrintEmpty)
+
+    ppStep = pp True
+      where
+        pp dir (UseAxiom axiom@Axiom{..} sub) =
+          text "axiom" <+> text (axiomNum axiom) <+> parens (text axiom_name) <+> ppDir dir <#> showSubst sub
+        pp dir (UseLemma lemma sub) =
+          text "lemma" <+> text (lemmaNum lemma) <+> ppDir dir <#> showSubst sub
+        pp dir (Symm p) =
+          pp (not dir) p
+        pp dir (Cong _ ps) = pp dir p
+          where
+            [p] = filter (not . isRefl) ps
+
+    ppDir True = pPrintEmpty
+    ppDir False = text "R->L"
+
+    showSubst sub
+      | cfg_show_instances && not (null (substToList sub)) =
+        text " with " <#> pPrintSubst sub
+      | otherwise = pPrintEmpty
+
+    isRefl Refl{} = True
+    isRefl _ = False
+
+-- Pretty-print a substitution.
+pPrintSubst :: Function f => Subst f -> Doc
+pPrintSubst sub =
+  fsep (punctuate comma
+    [ pPrint x <+> text "->" <+> pPrint t
+    | (x, t) <- substToList sub ])
+
+-- | Print a presented proof.
+pPrintPresentation :: forall f. Function f => Config f -> Presentation f -> Doc
+pPrintPresentation config (Presentation axioms lemmas goals) =
+  vcat $ intersperse (text "") $
+    vcat [ describeEquation "Axiom" (axiomNum axiom) (Just name) eqn $$
+           ppAxiomUses axiom
+         | axiom@(Axiom _ name eqn) <- axioms,
+           not (invisible eqn) ]:
+    [ pp "Lemma" (lemmaNum p) Nothing (equation p) emptySubst p
+    | p <- lemmas,
+      not (invisible (equation p)) ] ++
+    [ pp "Goal" (show num) (Just pg_name) pg_goal_hint pg_witness_hint pg_proof
+    | (num, ProvedGoal{..}) <- zip [1..] goals ]
+  where
+    pp kind n mname eqn witness p =
+      describeEquation kind n mname eqn $$
+      ppWitness witness $$
+      text "Proof:" $$
+      pPrintLemma config axiomNum lemmaNum p
+
+    axiomNums = Map.fromList (zip axioms [1..])
+    lemmaNums = Map.fromList (zip lemmas [length axioms+1..])
+    axiomNum x = show (fromJust (Map.lookup x axiomNums))
+    lemmaNum x = show (fromJust (Map.lookup x lemmaNums))
+
+    ppWitness sub
+      | sub == emptySubst = pPrintEmpty
+      | otherwise =
+          vcat [
+            text "The goal is true when:",
+            nest 2 $ vcat
+              [ pPrint x <+> text "=" <+> pPrint t
+              | (x, t) <- substToList sub ],
+            if minimal `elem` funs sub then
+              text "where" <+> doubleQuotes (pPrint (minimal :: Sym f)) <+>
+              text "stands for an arbitrary term of your choice."
+            else pPrintEmpty,
+            text ""]
+
+    ppAxiomUses axiom
+      | cfg_show_uses_of_axioms config axiom && not (null uses) =
+        text "Used with:" $$
+        nest 2 (vcat
+          [ pPrint i <#> text "." <+> pPrintSubst sub
+          | (i, sub) <- zip [1 :: Int ..] uses ])
+      | otherwise = pPrintEmpty
+      where
+        uses = Set.toList (axiomUses axiom)
+
+    axiomUses axiom = Map.findWithDefault Set.empty axiom usesMap
+    usesMap =
+      Map.unionsWith Set.union
+        [ Map.map (Set.delete emptySubst . Set.map ground)
+            (groundAxiomsAndSubsts p)
+        | goal <- goals,
+          let p = derivation (pg_proof goal) ]
+
+-- | Format an equation nicely.
+--
+-- Used both here and in the main file.
+describeEquation ::
+  Function f =>
+  String -> String -> Maybe String -> Equation f -> Doc
+describeEquation kind num mname eqn =
+  text kind <+> text num <#>
+  (case mname of
+     Nothing -> text ""
+     Just name -> text (" (" ++ name ++ ")")) <#>
+  text ":" <+> pPrint eqn <#> text "."
+
+----------------------------------------------------------------------
+-- Making proofs of existential goals more readable.
+----------------------------------------------------------------------
+
+-- The idea: the only axioms which mention $equals, $true and $false
+-- are:
+--   * $equals(x,x) = $true  (reflexivity)
+--   * $equals(t,u) = $false (conjecture)
+-- This implies that a proof $true = $false must have the following
+-- structure, if we expand out all lemmas:
+--   $true = $equals(s,s) = ... = $equals(t,u) = $false.
+--
+-- The substitution in the last step $equals(t,u) = $false is in fact the
+-- witness to the existential.
+--
+-- Furthermore, we can make it so that the inner "..." doesn't use the $equals
+-- axioms. If it does, one of the "..." steps results in either $true or $false,
+-- and we can chop off everything before the $true or after the $false.
+--
+-- Once we have done that, every proof step in the "..." must be a congruence
+-- step of the shape
+--   $equals(t, u) = $equals(v, w).
+-- This is because there are no other axioms which mention $equals. Hence we can
+-- split the proof of $equals(s,s) = $equals(t,u) into separate proofs of s=t
+-- and s=u.
+--
+-- What we have got out is:
+--   * the witness to the existential
+--   * a proof that both sides of the conjecture are equal
+-- and we can present that to the user.
+
+-- Tries to transform a proof of $true = $false into a proof of
+-- the original existentially-quantified formula.
+decodeGoal :: Function f => Config f -> ProvedGoal f -> ProvedGoal f
+decodeGoal config pg =
+  case maybeDecodeGoal config pg of
+    Nothing -> pg
+    Just (name, witness, goal, deriv) ->
+      checkProvedGoal $
+      pg {
+        pg_name = name,
+        pg_proof = certify deriv,
+        pg_goal_hint = goal,
+        pg_witness_hint = witness }
+
+maybeDecodeGoal :: forall f. Function f =>
+  Config f -> ProvedGoal f -> Maybe (String, Subst f, Equation f, Derivation f)
+maybeDecodeGoal Config{..} ProvedGoal{..}
+  | not cfg_eliminate_existentials_coding = Nothing
+  --  N.B. presentWithGoals takes care of expanding any lemma which mentions
+  --  $equals, and flattening the proof.
+  | isFalseTerm u = extract (steps deriv)
+    -- Orient the equation so that $false is the RHS.
+  | isFalseTerm t = extract (steps (symm deriv))
+  | otherwise = Nothing
+  where
+    t :=: u = equation pg_proof
+    deriv = derivation pg_proof
+
+    -- Detect $true = $equals(t, t).
+    decodeReflexivity :: Derivation f -> Maybe (Term f)
+    decodeReflexivity (Symm (UseAxiom Axiom{..} sub)) = do
+      guard (isTrueTerm (eqn_rhs axiom_eqn))
+      (t, u) <- decodeEquality (eqn_lhs axiom_eqn)
+      guard (t == u)
+      return (subst sub t)
+    decodeReflexivity _ = Nothing
+
+    -- Detect $equals(t, u) = $false.
+    decodeConjecture :: Derivation f -> Maybe (String, Equation f, Subst f)
+    decodeConjecture (UseAxiom Axiom{..} sub) = do
+      guard (isFalseTerm (eqn_rhs axiom_eqn))
+      (t, u) <- decodeEquality (eqn_lhs axiom_eqn)
+      return (axiom_name, t :=: u, sub)
+    decodeConjecture _ = Nothing
+
+    extract (p:ps) = do
+      -- Start by finding $true = $equals(t,u).
+      t <- decodeReflexivity p
+      cont (Refl t) (Refl t) ps
+    extract [] = Nothing
+
+    cont p1 p2 (p:ps)
+      | Just t <- decodeReflexivity p =
+        cont (Refl t) (Refl t) ps
+      | Just (name, eqn, sub) <- decodeConjecture p =
+        -- If p1: s=t and p2: s=u
+        -- then symm p1 `trans` p2: t=u.
+        return (name, sub, eqn, symm p1 `trans` p2)
+      | Cong eq [p1', p2'] <- p, isEquals eq =
+        cont (p1 `trans` p1') (p2 `trans` p2') ps
+    cont _ _ _ = Nothing
+-}
diff --git a/misc/Nested.hs b/misc/Nested.hs
new file mode 100644
--- /dev/null
+++ b/misc/Nested.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE TypeFamilies, BangPatterns, PatternSynonyms, ViewPatterns #-}
+module Twee.Term.Nested where
+
+import qualified Twee.Term as Flat
+import qualified Twee.Term.Core as Flat
+import Twee.Term(Var, Fun, Build(..))
+
+data Term f =
+    Flat {-# UNPACK #-} !(Flat.Term f)
+  | VarTerm {-# UNPACK #-} !Var
+  | AppTerm {-# UNPACK #-} !(Fun f) ![Term f]
+
+instance Build (Term f) where
+  type BuildFun (Term f) = f
+  builder (Flat t) = builder t
+  builder (VarTerm x) = Flat.var x
+  builder (AppTerm f ts) = Flat.app f (builder ts)
+
+len :: Term f -> Int
+len t = aux 0 [t] []
+  where
+    aux !_ !_ !_ | False = undefined
+    aux n [] [] = n
+    aux n [] (ts:tss) = aux n ts tss
+    aux n (Flat t:ts) tss = aux (n+Flat.len t) ts tss
+    aux n (VarTerm _:ts) tss = aux (n+1) ts tss
+    aux n (AppTerm _ ts:us) tss = aux (n+1) ts (us:tss)
+
+flatten :: Term f -> Flat.Term f
+flatten t =
+  case Flat.buildTermList (len t) (builder t) of
+    Flat.Cons u Flat.Nil -> u
+
+pattern Var :: Var -> Term f
+pattern Var x <- (patVar -> Just x)
+  where
+    Var x = VarTerm x
+
+pattern App :: Fun f -> [Term f] -> Term f
+pattern App f ts <- (patApp -> Just (f, ts))
+  where
+    App f ts = AppTerm f ts
+
+patVar :: Term f -> Maybe Var
+patVar (VarTerm x) = Just x
+patVar (Flat (Flat.Var x)) = Just x
+patVar _ = Nothing
+
+patApp :: Term f -> Maybe (Fun f, [Term f])
+patApp (AppTerm f ts) = Just (f, ts)
+patApp (Flat (Flat.App f ts)) = Just (f, map Flat (Flat.unpack ts))
+patApp _ = Nothing
diff --git a/misc/NestedOrig.hs b/misc/NestedOrig.hs
new file mode 100644
--- /dev/null
+++ b/misc/NestedOrig.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE TypeFamilies, BangPatterns, PatternSynonyms, ViewPatterns #-}
+module Twee.Term.Nested where
+
+import qualified Twee.Term as Flat
+import qualified Twee.Term.Core as Flat
+import Twee.Term(Var, Fun, Build(..))
+
+data TermList f =
+    Nil
+  | AppendTerm (Term f) (TermList f)
+  | AppendFlatList {-# UNPACK #-} !(Flat.TermList f) (TermList f) -- first argument must be non-empty
+
+flatList :: Flat.TermList f -> TermList f
+flatList Flat.Nil = Nil
+flatList t = AppendFlatList t Nil
+
+(+++) :: TermList f -> TermList f -> TermList f
+Nil +++ ts = ts
+AppendTerm t ts +++ us = AppendTerm t (ts +++ us)
+AppendFlatList t ts +++ us = AppendFlatList t (ts +++ us)
+
+data Term f =
+    Flat {-# UNPACK #-} !(Flat.Term f)
+  | VarTerm {-# UNPACK #-} !Var
+  | AppTerm {-# UNPACK #-} !(Fun f) (TermList f)
+
+singleton :: Term f -> TermList f
+singleton t = AppendTerm t Nil
+
+instance Build (TermList f) where
+  type BuildFun (TermList f) = f
+  builder Nil = mempty
+  builder (AppendTerm t us) = builder t `mappend` builder us
+  builder (AppendFlatList ts us) = builder ts `mappend` builder us
+
+instance Build (Term f) where
+  type BuildFun (Term f) = f
+  builder (Flat t) = builder t
+  builder (VarTerm x) = Flat.var x
+  builder (AppTerm f ts) = Flat.app f (builder ts)
+
+lenList :: TermList f -> Int
+lenList t = aux 0 [t]
+  where
+    aux !_ !_ | False = undefined
+    aux n [] = n
+    aux n (Nil:ts) = aux n ts
+    aux n (AppendFlatList t u:ts) = aux (n+Flat.lenList t) (u:ts)
+    aux n (AppendTerm (Flat t) u:ts) = aux (n+Flat.len t) (u:ts)
+    aux n (AppendTerm VarTerm{} u:ts) = aux (n+1) (u:ts)
+    aux n (AppendTerm (AppTerm f t) u:ts) = aux (n+1) (t:u:ts)
+
+len :: Term f -> Int
+len t = lenList (singleton t)
+
+flattenList :: TermList f -> Flat.TermList f
+flattenList t = Flat.buildTermList (lenList t) (builder t)
+
+flatten :: Term f -> Flat.Term f
+flatten t =
+  case Flat.buildTermList (len t) (builder (singleton t)) of
+    Flat.Cons u Flat.Nil -> u
+
+toTerm :: TermList f -> Term f
+toTerm (AppendFlatList t Nil)
+  | Flat.Cons u Flat.Nil <- t = Flat u
+toTerm (AppendTerm t Nil) = t
+toTerm _ = error "toTerm: not a singleton term"
+
+patHead :: TermList f -> Maybe (Term f, TermList f, TermList f)
+patHead Nil = Nothing
+patHead (AppendFlatList t ts) =
+  let (t, us, vs) = Flat.unsafePatHead (Flat.singleton t) in
+  Just (Flat t, AppendFlatList us ts, AppendFlatList vs ts) 
+patHead (AppendTerm t@VarTerm{} ts) =
+  Just (t, ts, ts)
+patHead (AppendTerm t@(AppTerm f ts) us) =
+  Just (t, us, ts +++ us)
+
+pattern ConsSym :: Term f -> TermList f -> TermList f -> TermList f
+pattern ConsSym{hd, tl, rest} <- (patHead -> Just (hd, tl, rest))
+
+pattern Var :: Var -> Term f
+pattern Var x <- (patVar -> Just x)
+  where
+    Var x = VarTerm x
+
+patVar :: Term f -> Maybe Var
+patVar (VarTerm x) = Just x
+patVar (Flat (Flat.Var x)) = Just x
+patVar _ = Nothing
+
+patApp :: Term f -> Maybe (Fun f, TermList f)
+patApp (AppTerm f ts) = Just (f, ts)
+patApp (Flat (Flat.App f ts)) = Just (f, flatList ts)
+patApp _ = Nothing
+
+pattern App :: Fun f -> TermList f -> Term f
+pattern App f ts <- (patApp -> Just (f, ts))
+  where
+    App f ts = AppTerm f ts
diff --git a/misc/Test.hs b/misc/Test.hs
deleted file mode 100644
--- a/misc/Test.hs
+++ /dev/null
@@ -1,334 +0,0 @@
-{-# LANGUAGE TemplateHaskell, FlexibleInstances, FlexibleContexts, UndecidableInstances, StandaloneDeriving, ScopedTypeVariables, TupleSections, DeriveGeneric, DerivingVia, DeriveAnyClass #-}
-module Main where
-
-import Twee.Constraints
-import Twee.Term hiding (subst, canonicalise, F)
-import Twee.Term.Core hiding (F)
-import Test.QuickCheck hiding (Function, Fun)
-import Test.QuickCheck.All
-import Twee.Pretty
-import Twee.CP
-import Twee.Proof
-import qualified Twee.KBO as Ord
-import Text.PrettyPrint
-import Twee.Base hiding (F)
-import Twee.Rule
-import Twee.Equation
-import Control.Monad
-import qualified Data.Map as Map
-import Data.Maybe
-import Data.Ord
-import Data.List hiding (singleton)
-import Data.Typeable
-import qualified Twee.Index as Index
-import Data.Int
-import GHC.Generics
-import Twee.Utils
-import qualified Data.IntMap as M
-import qualified Twee.Index as Index
-
-data Func = F Int Integer deriving (Eq, Ord, Show, Labelled)
-
-instance Pretty Func where
-  pPrint (F 3 _) = text "a"
-  pPrint (F 4 _) = text "b"
-  pPrint (F 5 _) = text "zero"
-  pPrint (F 6 _) = text "plus"
-  pPrint (F 7 _) = text "times"
-  pPrint (F f _) = text "f" <#> int f
-instance PrettyTerm Func
-instance Arbitrary (Subst Func) where
-  arbitrary = fmap fromJust (fmap listToSubst (liftM2 zip (fmap nub arbitrary) (infiniteListOf arbitrary)))
-instance Arbitrary Func where
-  arbitrary = F <$> choose (0, 2) <*> choose (1, 3)
-instance Minimal Func where
-  minimal = fun (F 0 1)
-instance Ord.Sized Func where size (F _ n) = n
-instance Ord.Weighted Func where argWeight _ = 1
-class Arity f where
-  arity :: f -> Int
-instance Arity Func where
-  arity (F 0 _) = 0
-  arity (F 1 _) = 1
-  arity (F 2 _) = 2
-  arity (F 3 _) = 0 -- a
-  arity (F 4 _) = 0 -- b
-  arity (F 5 _) = 0 -- zero
-  arity (F 6 _) = 2 -- plus
-  arity (F 7 _) = 2 -- times
-instance EqualsBonus Func
-
-instance Arbitrary Var where arbitrary = fmap V (choose (0, 3))
-instance (Labelled f, Ord f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Fun f) where
-  arbitrary = fmap fun arbitrary
-
-instance (Labelled f, Ord f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Term f) where
-  arbitrary =
-    sized $ \n ->
-      oneof $
-        [ build <$> var <$> arbitrary ] ++
-        [ do { f <- arbitrary; build <$> app (fun f) <$> vectorOf (arity f) (resize ((n-1) `div` arity f) arbitrary :: Gen (Term f)) } | n > 0 ]
-  shrink (App f ts0) =
-    ts ++ (build <$> app f <$> shrinkOne ts)
-    where
-      ts = unpack ts0
-      shrinkOne [] = []
-      shrinkOne (x:xs) =
-        [ y:xs | y <- shrink x ] ++
-        [ x:ys | ys <- shrinkOne xs ]
-  shrink _ = []
-
-instance (Labelled f, Ord f, Typeable f, Arbitrary f, Arity f) => Arbitrary (TermList f) where
-  arbitrary = buildList <$> listOf (arbitrary :: Gen (Term f))
-  shrink = map buildList . shrink . unpack
-
-data Pair f = Pair (Term f) (Term f) deriving Show
-
-instance (Labelled f, Ord f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Pair f) where
-  arbitrary = liftM2 Pair arbitrary arbitrary
-  shrink (Pair x y) =
-    [ Pair x' y  | x' <- shrink x ] ++
-    [ Pair x y'  | y' <- shrink y ] ++
-    [ Pair x' y' | x' <- shrink x, y' <- shrink y ]
-
-instance (Labelled f, Ord f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Equation f) where
-  arbitrary = do
-    Pair t u <- arbitrary
-    return (t :=: u)
-  shrink (t :=: u) = [t' :=: u' | Pair t' u' <- shrink (Pair t u)]
-
-instance Ordered Func where
-  lessIn = Ord.lessIn
-  lessEq = Ord.lessEq
-  lessEqSkolem = Ord.lessEqSkolem
-
-instance Function f => Arbitrary (Model f) where
-  arbitrary = fmap (modelFromOrder . map Variable . nub) arbitrary
-  shrink = weakenModel
-
-{-
-prop_1 :: Model Func -> Pair Func -> Subst Func -> Property
-prop_1 model (Pair t u) sub =
-  counterexample ("Model: " ++ prettyShow model) $
-  counterexample ("Subst: " ++ prettyShow sub) $
-  conjoin $ do
-    let cp = CriticalPair (t :=: u) 0 Nothing (axiom (Axiom 0 "dummy" (t :=: u)))
-    r@(Rule _ t' u') <- map orient (map cp_eqn (split cp))
-    return $
-      counterexample ("LHS:   " ++ prettyShow t') $
-      counterexample ("RHS:   " ++ prettyShow u') $
-      counterexample ("Rule:  " ++ prettyShow r) $
-      counterexample ("Inst:  " ++ prettyShow (Rule Oriented (subst sub t') (subst sub u'))) $
-      counterexample ("Res:   " ++ show (lessIn model (subst sub u') (subst sub t'))) $
-      not (reducesInModel model r sub) || isJust (lessIn model (subst sub u') (subst sub t'))
--}
-
-prop_2 :: Model Func -> Pair Func -> Bool
-prop_2 model (Pair t u) =
-  not (lessIn model t u == Just Strict && isJust (lessIn model u t))
-
-prop_3 :: Pair Func -> Bool
-prop_3 (Pair t u) =
-  not (lessThan t u && lessEq u t)
-
-prop_4 :: Pair Func -> Property
-prop_4 (Pair t u) =
-  t /= u ==> 
-  not (lessEq t u && lessEq u t)
-
-prop_5 :: Term Func -> Property
-prop_5 t =
-  lessEq t t .&&. not (lessThan t t)
-
-prop_paths :: Term Func -> Property
-prop_paths t =
-  forAllShrink (choose (0, len t-1)) shrink $ \n ->
-    counterexample (show (positionToPath t n)) $
-    pathToPosition t (positionToPath t n) === n
-
-prop_index :: [Term Func] -> Term Func -> Property
-prop_index ts u =
-  counterexample (show ts') $
-  counterexample (show idx) $
-  sort (catMaybes [fmap (,t) (match t u) | t <- ts']) ===
-  sort (Index.matches u idx)
-  where
-    idx = foldr (\t -> Index.insert t t) Index.empty ts
-    ts' = map canonicalise ts
-
-newtype Terms f = Terms [Term f] deriving Show
-instance (Labelled f, Ord f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Terms f) where
-  arbitrary = Terms <$> arbitrary
-  shrink (Terms ts) =
-    map Terms $
-      filter (/= ts) $
-      shrink ts ++ [canonicalise ts] ++ shrinkList (return . canonicalise) ts
-
-newtype IndexOps f = IndexOps [IndexOp f] deriving Show
-data IndexOp f = Add (Term f) | Delete (Term f) deriving Show
-
-instance (Labelled f, Ord f, Typeable f, Arbitrary f, Arity f) => Arbitrary (IndexOps f) where
-  arbitrary =
-    sized $ \n -> IndexOps <$> take n <$> arbOps []
-    where
-      arbOps ts =
-        frequency $
-          [(2, do { t <- arbitrary; ops <- arbOps (t:ts); return (Add t:ops) })] ++
-          [(1, do { t <- elements ts; ops <- arbOps (delete t ts); return (Delete t:ops) }) | not (null ts)]
-  shrink (IndexOps ops) =
-    IndexOps <$> shrinkList shr ops
-    where
-      shr (Add t) = Add <$> shrink t
-      shr (Delete t) = Delete <$> shrink t
-
-
-prop_index_invariant :: IndexOps Func -> Property
-prop_index_invariant (IndexOps ops) =
-  flip (foldr (counterexample . show)) idxs $
-  property $ Index.invariant (last idxs)
-  where
-    idxs = scanl (\idx op -> applyIndex op idx) Index.empty ops
-    applyIndex (Add t) = Index.insert t t
-    applyIndex (Delete t) = Index.delete t t
-
-deriving instance Eq Symbol
-deriving instance Generic Symbol
-
-instance Arbitrary Symbol where
-  arbitrary =
-    Symbol <$>
-      arbitrary <*>
-      fmap getLarge arbitrary <*>
-      (fmap (fromIntegral . getLarge) (arbitrary :: Gen (Large Int32)) `suchThat` (> 0) `suchThat` (< 2^31))
-  shrink s =
-    filter ok (genericShrink s)
-    where
-      ok s = Twee.Term.Core.size s > 0
-
-prop_symbol_1 :: Symbol -> Property
-prop_symbol_1 s =
-  withMaxSuccess 100000 $
-  counterexample ("fun/index/size = " ++ show (isFun s, index s, Twee.Term.Core.size s)) $
-  counterexample ("n = " ++ show (fromSymbol s)) $
-  toSymbol (fromSymbol s) === twiddle s
-  where
-    twiddle s =
-      s { index = fromIntegral (fromIntegral (index s) :: Int32) }
-
-prop_symbol_2 :: Int64 -> Property
-prop_symbol_2 n =
-  withMaxSuccess 100000 $
-  fromSymbol (toSymbol n) === n
-
-prop_canonorder :: Equation Func -> Property
-prop_canonorder eqn@(t :=: u) =
-  let vs = usort (vars eqn) in
-  forAll (shuffle vs) $ \ws swap (NonNegative n) ->
-    let
-      Just sub = listToSubst (zip vs [build (var (V (w + n))) | V w <- ws])
-      eqn' = subst sub (if swap then u :=: t else t :=: u)
-    in
-      canonicalise (order eqn) === canonicalise (order eqn')
-
-prop_canonorder2 :: Equation Func -> Equation Func -> Bool
-prop_canonorder2 eqn1 eqn2 =
-  eqn1 `simplerThan` eqn2 || eqn2 `simplerThan` eqn1 || order eqn1 == order eqn2
-
-prop_canonorder3 :: Equation Func -> Property
-prop_canonorder3 eq =
-  let eq' = order eq in
-  counterexample (show eq) $
-  Ord.size (eqn_lhs eq') >= Ord.size (eqn_rhs eq')
-
---t :: Term Func
---t = build (app (fun (F 0)) [app (fun (F 1)) [var (V 0), var (V 1)], var (V 2)])
-
--- Define 'nest' from Fuchs "The application of goal-oriented heuristics...",
--- then refine it to a more efficient version
-nestf :: Func -> Term Func -> Int
-nestf f _ | arity f == 0 = 0
-nestf f t = hnest (fun f) t 0 0
-  where
-    hnest _ (Var _) c a = max c a
-    hnest _ (App _ Empty) c a = max c a
-    hnest f (App g ts) c a
-      | f == g = maximum [hnest f t (c+1) a | t <- unpack ts]
-      | otherwise = maximum [hnest f t 0 (max c a) | t <- unpack ts]
-
--- a simpler version, to illustrate the meaning
-nestf1 :: Func -> Term Func -> Int
-nestf1 f t = hnest (fun f) t 0
-  where
-    hnest _ (Var _) c = c
-    hnest _ (App _ Empty) c = c
-    hnest f (App g ts) c
-      | f == g = maximum [hnest f t (c+1) | t <- unpack ts]
-      | otherwise = max c (maximum [hnest f t 0 | t <- unpack ts])
-
--- a more efficient version
-nestf2 :: Func -> Term Func -> Int
-nestf2 f t = hnest (fun f) (singleton t) 0 0
-  where
-    hnest _ Empty c a = max c a
-    hnest f (Cons (Var _) ts) c a = hnest f ts c a
-    hnest f (Cons (App _ Empty) ts) c a = hnest f ts c a
-    hnest f (Cons (App g ts) us) c a
-      | f == g = 
-        let a' = hnest f ts (c+1) a
-        in hnest f us c a'
-      | otherwise =
-        let a' = hnest f ts 0 a
-        in hnest f us c a'
-
--- a version that does all function symbols at once
-nestf3 :: Term Func -> M.IntMap Int
-nestf3 t = hnest 0 0 M.empty (singleton t)
-  where
-    hnest f c as Empty = M.insertWith max f c as
-    hnest f c as (Cons (Var _) ts) = hnest f c as ts
-    hnest f c as (Cons (App _ Empty) ts) = hnest f c as ts
-    hnest f c as (Cons (App g ts) us) =
-      let as' = hnest (fun_id g) (if f == fun_id g then c+1 else 1) as ts
-      in hnest f c as' us
-
-prop_nest_1 :: Func -> Term Func -> Property
-prop_nest_1 f t = withMaxSuccess 1000000 $ nestf f t === nestf1 f t
-
-prop_nest_2 :: Func -> Term Func -> Property
-prop_nest_2 f t = withMaxSuccess 1000000 $ nestf f t === nestf2 f t
-
-prop_nest_3 :: Func -> Term Func -> Property
-prop_nest_3 f t =
-  withMaxSuccess 1000000 $
-    nestf f t === M.findWithDefault 0 (fun_id (fun f)) (nestf3 t)
-
-prop_nests :: Func -> TermList Func -> Property
-prop_nests f ts =
-  withMaxSuccess 1000000 $
-    maximum (0:map (nestf f) (unpack ts)) ===
-    M.findWithDefault 0 (fun_id (fun f)) (nests ts)
-
-return []
-main = $forAllProperties (quickCheckWithResult stdArgs { maxSuccess = 1000000 })
-
-a = con (fun (F 3 1))
-b = con (fun (F 4 2))
-zero = con (fun (F 5 1))
-plus t u = app (fun (F 6 1)) [t, u]
-times t u = app (fun (F 7 1)) [t, u]
-x = var (V 0)
-y = var (V 1)
-
-axioms = [
-  build (plus x y) ==== plus y x,
-  times zero x ==== zero,
-  plus x zero ==== x ]
-  where
-    t ==== u = build t :=: build u
-
-rules = [orient eq (certify (axiom (Axiom 0 "axiom" eq))) | eq <- axioms]
-
-theIndex = Index.fromList [(lhs r, r) | r <- rules]
-
-term = build (plus (times zero a) b)
-strat = anywhere1 (basic (rewrite reduces theIndex))
diff --git a/misc/WhyDoesThisLoopWithHornElimination.hs b/misc/WhyDoesThisLoopWithHornElimination.hs
new file mode 100644
--- /dev/null
+++ b/misc/WhyDoesThisLoopWithHornElimination.hs
@@ -0,0 +1,1463 @@
+{-# LANGUAGE CPP, RecordWildCards, FlexibleInstances, PatternGuards, DeriveAnyClass, RankNTypes, ApplicativeDo, DeriveGeneric #-}
+{-# OPTIONS_GHC -flate-specialise #-}
+module SequentialMain(main, Constant(..)) where
+
+import Control.Monad
+import Data.Char
+import Data.Either
+import Twee hiding (message)
+import Twee.Base hiding (char, lookup, vars, ground)
+--import qualified Twee.Base as Twee
+import Twee.Rule(lhs, rhs, unorient)
+import Twee.Equation
+import qualified Twee.Proof as Proof
+import Twee.Proof hiding (Config, defaultConfig)
+import qualified Twee.Join as Join
+import Twee.Utils
+import qualified Twee.CP as CP
+import Data.Ord
+import Data.Map(Map)
+import qualified Data.Map as Map
+import qualified Twee.KBO as KBO
+#ifdef USE_LPO
+import qualified Twee.LPO as LPO
+#endif
+import Data.List.Split
+import Data.List
+import Data.Maybe
+import Jukebox.Options
+import Jukebox.Toolbox
+import qualified Jukebox.Name as Jukebox
+import Jukebox.Name hiding (lhs, rhs, label)
+import qualified Jukebox.Form as Jukebox
+import Jukebox.Form hiding ((:=:), Var, Symbolic(..), Term, Axiom, size, Subst, subst)
+import Jukebox.Tools.EncodeTypes
+import Jukebox.TPTP.Print
+import Jukebox.Tools.HornToUnit
+import qualified Data.IntMap.Strict as IntMap
+import System.IO
+import System.Exit
+import qualified Data.Set as Set
+import qualified Data.Intern as Intern
+import System.Console.ANSI
+import Data.Symbol
+import Twee.Profile
+import GHC.Generics
+import Data.Hashable
+import Data.Binary.Sharing
+import qualified Data.ByteString.Lazy as BS
+import System.Process
+import qualified Jukebox.TPTP.Parse.Core as TPTP
+import qualified Jukebox.TPTP.ParseSnippet as Snippet
+import Debug.Trace
+
+data MainFlags =
+  MainFlags {
+    flags_proof :: Bool,
+    flags_proof_on_saturation :: Bool,
+    flags_trace :: Maybe (String, String),
+    flags_formal_proof :: Bool,
+    flags_explain_encoding :: Bool,
+    flags_flip_ordering :: Bool,
+    flags_give_up_on_saturation :: Bool,
+    flags_hint_goals :: Bool,
+    flags_flatten_goals :: Bool,
+    flags_flatten_nonground :: Bool,
+    flags_flatten_goals_lightly :: Bool,
+    flags_flatten_all :: Bool,
+    flags_flatten_regeneralise :: Bool,
+    flags_flatten_every :: Int,
+    flags_eliminate :: [String],
+    flags_backwards_goal :: Int,
+    flags_flatten_backwards_goal :: Int,
+    flags_equals_transformation :: Bool,
+    flags_distributivity_heuristic :: Bool,
+    flags_kbo_weight0 :: Bool,
+    flags_kbo_weight0_unary :: Bool,
+    flags_goal_heuristic :: Bool,
+    flags_funweight :: Float,
+    flags_dump_proof :: Maybe FilePath,
+    flags_dump_state :: Maybe FilePath,
+    flags_stitch :: Maybe FilePath }
+
+parseMainFlags :: OptionParser MainFlags
+parseMainFlags = do
+  let argModule = arg "<module>" "expected a Prolog module name" Just
+  flags_proof <-
+    inGroup "Output options" $
+    bool "proof" ["Produce proofs (on by default)."]
+    True
+  flags_proof_on_saturation <-
+    expert $
+    inGroup "Output options" $
+    bool "proof-on-saturation" ["Produce proofs of all rewrite rules on saturation (off by default)."]
+    False
+  flags_trace <-
+    expert $
+    inGroup "Output options" $
+    flag "trace"
+      ["Write a Prolog-format execution trace to this file (off by default)."]
+      Nothing ((\x y -> Just (x, y)) <$> argFile <*> argModule)
+  flags_formal_proof <-
+    expert $
+    inGroup "Output options" $
+    bool "formal-proof" ["Print proof as formal TSTP derivation (requires --tstp; off by default)."] False
+  flags_explain_encoding <-
+    expert $
+    inGroup "Output options" $
+    bool "explain-encoding" ["In CASC mode, explain the conditional encoding (off by default)."] False
+  flags_flip_ordering <-
+    expert $
+    inGroup "Term order options" $
+    bool "flip-ordering" ["Make more common function symbols smaller (off by default)."] False
+  flags_kbo_weight0 <-
+    expert $
+    inGroup "Term order options" $
+    bool "kbo-weight0" ["Give functions of arity >= 2 a weight of 0."] False
+  flags_kbo_weight0_unary <-
+    expert $
+    inGroup "Term order options" $
+    bool "kbo-weight0-unary" ["Give one function of arity 1 a weight of 0."] True
+  flags_give_up_on_saturation <-
+    expert $
+    inGroup "Output options" $
+    bool "give-up-on-saturation" ["Report SZS status GiveUp rather than Unsatisfiable on saturation (off by default)."] False
+  flags_hint_goals <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "hint-goal" ["Add hints representing goal terms (off by default)."] False
+  flags_flatten_goals <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "flatten-goal" ["Flatten goal by adding new axioms (on by default)."] True
+  flags_flatten_nonground <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "flatten-nonground" ["Flatten even non-ground clauses (off by default)."] False
+  flags_flatten_goals_lightly <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "flatten-goal-lightly" ["Flatten goal non-recursively by adding new axioms (off by default)."] False
+  flags_flatten_all <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "flatten" ["Flatten all clauses by adding new axioms (off by default)."] False
+  flags_flatten_every <-
+    expert $
+    inGroup "Completion heuristics" $
+    flag "flatten-every" ["Flatten only every nth subterm (default = 1)."] 1 argNum
+  flags_flatten_regeneralise <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "flatten-regeneralise" ["Regeneralise rules involving flattened goal terms (off by default)."] False
+  flags_backwards_goal <-
+    expert $
+    inGroup "Completion heuristics" $
+    flag "backwards-goal" ["Try rewriting backwards from the goal this many times (0 by default)."] 0 argNum
+  flags_flatten_backwards_goal <-
+    expert $
+    inGroup "Completion heuristics" $
+    flag "flatten-backwards-goal" ["Try rewriting backwards from the goal this many times when flattening (0 by default)."] 0 argNum
+  flags_equals_transformation <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "equals-transformation" ["Apply the 'equals transformation' even to ground goals (off by default)."] False
+  flags_distributivity_heuristic <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "distributivity-heuristic" ["Treat distributive operators specially (off by default)."] False
+  flags_goal_heuristic <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "goal-heuristic" ["Use the CP weighting heuristic from Anantharaman and Andrianarievelo (off by default)."] False
+  flags_eliminate <-
+    inGroup "Proof presentation" $
+    concat <$>
+    manyFlags "eliminate"
+      ["Treat these axioms as definitions and eliminate them from the proof.",
+       "The axiom must have the shape f(x1...xn) = t, where x1...xn are",
+       "distinct variables. The term f must not otherwise appear in the problem!",
+       "This is not checked."]
+      (splitOn "," <$> arg "<axioms>" "expected a list of axiom names" Just)
+  flags_funweight <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    flag "fun-weight" ["Weight given to function symbols"] 1 argNum
+  flags_dump_proof <-
+    expert $
+    inGroup "Debugging options" $
+    flag "dump-proof"
+      ["Dump a binary proof to this file (off by default)."]
+      Nothing (Just <$> argFile)
+  flags_dump_state <-
+    expert $
+    inGroup "Debugging options" $
+    flag "dump-state"
+      ["Dump prover state to this file on termination (off by default)."]
+      Nothing (Just <$> argFile)
+  flags_stitch <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    flag "stitch"
+      ["Path to 'stitch' tool for discovering abstractions (disabled by default)."]
+      Nothing (Just <$> argFile)
+
+  return MainFlags{..}
+
+parseConfig :: OptionParser (Config Constant)
+parseConfig = do
+  cfg_accept_term <-
+    let checkSize n t = KBO.size (t :: Term Constant) <= n in
+    inGroup "Resource limits" $
+    flag "max-term-size" ["Discard rewrite rules whose left-hand side is bigger than this limit (unlimited by default)."] Nothing (Just <$> checkSize <$> argNum)
+  cfg_max_critical_pairs <-
+    inGroup "Resource limits" $
+    flag "max-cps" ["Give up after considering this many critical pairs (unlimited by default)."] maxBound argNum
+  cfg_max_cp_depth <-
+    inGroup "Resource limits" $
+    flag "max-cp-depth" ["Only consider critical pairs up to this depth (unlimited by default)."] maxBound argNum
+  cfg_max_rules <-
+    inGroup "Resource limits" $
+    flag "max-rules" ["Give up after generating this many rules (unlimited by default)."] maxBound argNum
+  cfg_max_time <-
+    inGroup "Resource limits" $
+    flag "max-time" ["Give up after running for this long in seconds (unlimited by default)."] Nothing (Just <$> argNum)
+  cfg_simplify <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "simplify"
+      ["Simplify rewrite rules with respect to one another (on by default)."]
+      True
+  cfg_renormalise_percent <-
+    expert $
+    inGroup "Completion heuristics" $
+    defaultFlag "normalise-queue-percent" "Percent of time spent renormalising queued critical pairs" cfg_renormalise_percent argNum
+  cfg_cp_sample_size <-
+    expert $
+    inGroup "Completion heuristics" $
+    defaultFlag "cp-sample-size" "Size of random CP sample used to trigger renormalisation" cfg_cp_sample_size argNum
+  cfg_renormalise_threshold <-
+    expert $
+    inGroup "Completion heuristics" $
+    defaultFlag "cp-renormalise-threshold" "Trigger renormalisation when this percentage of CPs can be simplified" cfg_renormalise_threshold argNum
+  cfg_set_join_goals <-
+    expert $
+    inGroup "Critical pair joining heuristics" $
+    bool "set-join-goals"
+      ["Compute all normal forms when joining goal terms (on by default)."]
+      True
+  cfg_always_simplify <-
+    expert $
+    inGroup "Debugging options" $
+    bool "always-simplify"
+      ["Interreduce rules after every step."]
+      False
+  cfg_complete_subsets <-
+    expert $
+    inGroup "Critical pair joining heuristics" $
+    bool "complete-subsets"
+      ["Identify and exploit complete subsets of the axioms in joining (off by default)."]
+      False
+  let cfg_hint_func i x = Intern.intern (Hint i x)
+
+  cfg_join <- do
+    cfg_ground_join <-
+      expert $
+      inGroup "Critical pair joining heuristics" $
+      bool "ground-joining"
+        ["Test terms for ground joinability (on by default)."]
+        True
+    cfg_use_connectedness_standalone <-
+      expert $
+      inGroup "Critical pair joining heuristics" $
+      bool "connectedness"
+        ["Test terms for subconnectedness, as a separate check (on by default)."]
+        True
+    cfg_use_connectedness_in_ground_joining <-
+      expert $
+      inGroup "Critical pair joining heuristics" $
+      bool "ground-connectedness"
+        ["Test terms for subconnectedness, as part of ground joinability testing (off by default)."]
+        False
+    cfg_set_join <-
+      expert $
+      inGroup "Critical pair joining heuristics" $
+      bool "set-join"
+        ["Compute all normal forms when joining critical pairs (off by default)."]
+        False
+    cfg_ground_join_limit <-
+      inGroup "Critical pair joining heuristics" $
+      flag "ground-joining-limit" ["Assume not ground joinable after considering this many orderings (unlimited by default)."] maxBound argNum
+    cfg_ground_join_incomplete_limit <-
+      inGroup "Critical pair joining heuristics" $
+      flag "ground-joining-incomplete-limit" ["Assume ground joinable after considering this many orderings (unlimited by default)."] maxBound argNum
+    return Join.Config{..}
+
+  cfg_proof_presentation <- do
+    cfg_all_lemmas <-
+      inGroup "Proof presentation" $
+      bool "all-lemmas"
+        ["Produce a proof with one lemma for each critical pair (off by default)."]
+        False
+    cfg_no_lemmas <-
+      inGroup "Proof presentation" $
+      bool "no-lemmas"
+        ["Produce a proof with no lemmas (off by default).",
+         "May lead to exponentially large proofs."]
+        False
+    cfg_ground_proof <-
+      inGroup "Proof presentation" $
+      bool "ground-proof"
+        ["Produce a ground proof (off by default).",
+         "May lead to exponentially large proofs."]
+        False
+    cfg_show_instances <-
+      inGroup "Proof presentation" $
+      bool "show-instances"
+        ["Show which instance of a lemma or axiom each rewrite step uses (off by default)."]
+        False
+    cfg_use_colour <-
+      let
+        colourFlag =
+          inGroup "Proof presentation" $
+          primFlag "(no-)colour"
+            ["Produce output in colour (on by default if writing output to a terminal)."]
+            (`elem` map fst colourFlags)
+            (\_ y -> return y)
+            Nothing
+            (pure (`lookup` colourFlags))
+        colourFlags = [("--colour", True), ("--no-colour", False),
+                       ("--color", True), ("--no-color", False)]
+        colourSupported =
+          liftM2 (&&) (hSupportsANSIColor stdout)
+            (return (setSGRCode [] /= "")) -- Check for Windows terminal not supporting ANSI
+      in fromMaybe <$> io colourSupported <*> colourFlag
+
+    cfg_show_uses_of_axioms <-
+      let interpret xss ax = axiom_name ax `elem` xss || "all" `elem` xss in
+      inGroup "Proof presentation" $
+      interpret <$>
+      concat <$>
+      manyFlags "show-uses-of"
+        ["Show which instances of the given axioms were needed (none by default).",
+         "Separate multiple axiom names with commas.",
+         "Use --show-uses-of all to show uses of all axioms."]
+        (splitOn "," <$> arg "<axioms>" "expected a list of axiom names" Just)
+
+    cfg_show_peaks <-
+      inGroup "Proof presentation" $
+      bool "show-peaks"
+        ["Show peak terms in a proof (off by default)."]
+        False
+    cfg_eliminate_existentials_coding <-
+      inGroup "Proof presentation" $
+      bool "eliminate-existentials-coding"
+        ["Eliminate $equals from proofs (on by default)."]
+        True
+    cfg_show_subterms <-
+      inGroup "Proof presentation" $
+      bool "show-subterms"
+        ["Show which subterm is rewritten at each step (off by default)."]
+        False
+
+    return Proof.Config{..}
+
+  let cfg_eliminate_axioms = [] -- filled in later
+
+  cfg_random_mode <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "random-mode"
+      ["Use random testing to find suitable CPs (doesn't work yet!) (off by default)."]
+      False
+  cfg_random_mode_goal_directed <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "random-mode-goal-directed"
+      ["Use goal-direction in --random-mode (off by default)."]
+      False
+  cfg_random_mode_simple <-
+    expert $
+    inGroup "Completion heuristics" $
+    bool "random-mode-simple"
+      ["Use simple version of --random-mode (off by default)."]
+      False
+  cfg_random_mode_best_of <-
+    inGroup "Completion heuristics" $
+    defaultFlag "random-mode-best-of" "Generate this many critical pairs at a time and pick the best one" cfg_random_mode_best_of argNum
+  cfg_always_complete <-
+    inGroup "Input and clausifier options" $
+    bool "complete"
+      ["Don't stop until the rewrite system is confluent"]
+      False
+  cfg_hint_skel_cost <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    defaultFlag "hint-skel-cost" "Size of hint skeletons" cfg_hint_skel_cost argNum
+  cfg_hint_skel_factor <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    defaultFlag "hint-skel-factor" "Size factor of hint skeletons" cfg_hint_skel_factor argNum
+  cfg_print_score <-
+    expert $
+    inGroup "Output options" $
+    bool "print-score" ["Print score of each generated rule (off by default)."] False
+  cfg_cp_config <- parseCPConfig
+
+  return Config{..}
+  where
+    defaultFlag :: Show a => String -> String -> (Config Constant -> a) -> ArgParser a -> OptionParser a
+    defaultFlag name desc field parser =
+      flag name [desc ++ " (" ++ show def ++ " by default)."] def parser
+      where
+        def = field defaultConfig
+
+parseCPConfig :: OptionParser CP.Config
+parseCPConfig = do
+  cfg_lhsweight <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    defaultFlag "lhs-weight" "Weight given to LHS of critical pair" CP.cfg_lhsweight argNum
+  cfg_rhsweight <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    defaultFlag "rhs-weight" "Weight given to RHS of critical pair" CP.cfg_rhsweight argNum
+  cfg_varweight <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    defaultFlag "var-weight" "Weight given to variable symbols" CP.cfg_varweight argNum
+  cfg_depthweight <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    defaultFlag "depth-weight" "Weight given to critical pair depth" CP.cfg_depthweight argNum
+  cfg_dupcost <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    defaultFlag "dup-cost" "Cost of duplicate subterms" CP.cfg_dupcost argNum
+  cfg_dupfactor <-
+    expert $
+    inGroup "Critical pair weighting heuristics" $
+    defaultFlag "dup-factor" "Size factor of duplicate subterms" CP.cfg_dupfactor argNum
+  return CP.Config{..}
+  where
+    defaultFlag name desc field parser =
+      flag name [desc ++ " (" ++ show def ++ " by default)."] def parser
+      where
+        def = field CP.defaultConfig
+
+parsePrecedence :: OptionParser [String]
+parsePrecedence =
+  expert $
+  inGroup "Term order options" $
+  fmap (splitOn ",")
+  (flag "precedence" ["List of functions in descending order of precedence."] [] (arg "<function>" "expected a function name" Just))
+
+data Constant =
+  Minimal |
+  Skolem Int |
+  Hint Int Float |
+  Constant {
+    con_prec    :: {-# UNPACK #-} !Precedence,
+    con_id      :: {-# UNPACK #-} !Int,
+    con_name    :: !String,
+    con_arity   :: {-# UNPACK #-} !Int,
+    con_label   :: !(Maybe String),
+    con_size    :: !Integer,
+    con_weight  :: !Integer,
+    con_fweight :: {-# UNPACK #-} !Float,
+    con_bonus   :: !Bool }
+  deriving (Eq, Ord, Generic, Hashable, Binary)
+
+data Precedence = Precedence !Bool !Bool !Bool !(Maybe Int) !Int
+  deriving (Eq, Ord, Generic, Hashable, Binary)
+
+instance KBO.Sized Constant where
+  size Minimal = 1
+  size Skolem{} = 1
+  size Hint{} = 1
+  size Constant{..} = con_size
+instance KBO.ArgWeighted Constant where
+  argWeight Minimal = 1
+  argWeight Skolem{} = 1
+  argWeight Hint{} = 1
+  argWeight Constant{..} = con_weight
+
+instance Weighted Constant where
+  weight Minimal = 1
+  weight (Skolem _) = 1
+  weight (Hint _ x) = x
+  weight Constant{..} = con_fweight
+
+instance Pretty Constant where
+  pPrint Minimal = text "?"
+  pPrint (Skolem n) = text ("sk" ++ show n)
+  pPrint (Hint n _) = text ("hint" ++ show n)
+  pPrint Constant{..} = text (removePostfix con_name)
+    where
+      removePostfix ('_':x:xs) | con_arity == 1 = x:xs
+      removePostfix xs = xs
+
+instance PrettyTerm Constant where
+  termStyle Minimal = uncurried
+  termStyle Skolem{} = uncurried
+  termStyle Hint{} = uncurried
+  termStyle Constant{..}
+    | con_label == Just "type_tag" = invisible
+    | "_" `isPrefixOf` con_name && con_arity == 1 = postfix
+    | any isAlphaNum con_name = uncurried
+    | otherwise =
+      case con_arity of
+        1 -> prefix
+        2 -> infixStyle 5
+        _ -> uncurried
+
+instance Minimal Constant where
+  minimal = Sym Minimal
+  skolem = Sym . Skolem
+
+#ifdef USE_LPO
+instance Ordered Constant where
+  lessEq t u = LPO.lessEq t u
+  lessIn model t u = LPO.lessIn model t u
+  lessEqSkolem t u = LPO.lessEqSkolem t u
+#else
+instance Ordered Constant where
+  lessEq t u = KBO.lessEq t u
+  lessIn model t u = KBO.lessIn model t u
+  lessEqSkolem t u = KBO.lessEqSkolem t u
+#endif
+
+instance EqualsBonus Constant where
+  hasEqualsBonus Minimal = False
+  hasEqualsBonus Skolem{} = False
+  hasEqualsBonus Hint{} = False
+  hasEqualsBonus c = con_bonus c
+
+  isEquals Constant{..} = con_label == Just "equals" && con_arity == 2
+  isEquals _ = False
+  isTrue Constant{..} = con_label == Just "true" && con_arity == 0
+  isTrue _ = False
+  isFalse Constant{..} = con_label == Just "false" && con_arity == 0
+  isFalse _ = False
+
+data TweeContext =
+  TweeContext {
+    ctx_var     :: Jukebox.Variable,
+    ctx_minimal :: Jukebox.Function,
+    ctx_true    :: Jukebox.Function,
+    ctx_false   :: Jukebox.Function,
+    ctx_equals  :: Jukebox.Function,
+    ctx_type    :: Type,
+    ctx_funs    :: Map Int Jukebox.Function,
+    ctx_ids     :: Map Jukebox.Function Int }
+
+-- Convert back and forth between Twee and Jukebox.
+tweeConstant :: MainFlags -> HornFlags -> TweeContext -> Precedence -> Jukebox.Function -> Constant
+tweeConstant MainFlags{..} flags TweeContext{..} prec fun
+  | fun == ctx_minimal = Minimal
+  | otherwise =
+    Constant {
+      con_prec = prec,
+      con_id = Map.findWithDefault (error (show (fun, ctx_ids))) fun ctx_ids,
+      con_name = base (name fun),
+      con_label = Jukebox.label (name fun),
+      con_arity = Jukebox.arity fun,
+      con_size = if flags_kbo_weight0 && Jukebox.arity fun >= 2 then 0 else if flags_kbo_weight0_unary && isInv then 0 else 1,
+      con_weight = 1,
+      con_fweight = flags_funweight,
+      con_bonus = bonus fun }
+  where
+    bonus fun =
+      (isIfeq fun && encoding flags /= Asymmetric2) ||
+      (Jukebox.label (name fun) == Just "equals" && Jukebox.arity fun == 2)
+    isInv =
+      case prec of
+        Precedence _ x _ _ _ -> x
+
+isType :: Jukebox.Function -> Bool
+isType fun =
+  hasLabel "type_tag" (name fun) && Jukebox.arity fun == 1
+
+isIfeq :: Jukebox.Function -> Bool
+isIfeq fun =
+  hasLabel "ifeq" (name fun)
+
+jukeboxFunction :: TweeContext -> Constant -> Jukebox.Function
+jukeboxFunction TweeContext{..} Constant{..} = Map.findWithDefault undefined con_id ctx_funs
+jukeboxFunction TweeContext{..} Minimal = ctx_minimal
+
+tweeTerm :: MainFlags -> HornFlags -> TweeContext -> (Jukebox.Variable -> Int) -> (Jukebox.Function -> Precedence) -> Jukebox.Term -> Term Constant
+tweeTerm flags horn ctx varNum prec t = build (tm t)
+  where
+    tm (Jukebox.Var x) =
+      var (V (varNum x))
+    tm (f :@: ts) =
+      app (Sym (tweeConstant flags horn ctx (prec f) f)) (map tm ts)
+
+jukeboxTerm :: TweeContext -> Term Constant -> Jukebox.Term
+jukeboxTerm TweeContext{..} (Var (V x)) =
+  Jukebox.Var (Unique (fromIntegral x) (intern "X") Nothing defaultRenamer ::: ctx_type)
+jukeboxTerm ctx@TweeContext{..} (App (Sym f) t) =
+  jukeboxFunction ctx f :@: map (jukeboxTerm ctx) ts
+  where
+    ts = unpack t
+
+makeContext :: [Jukebox.Term] -> Problem Clause -> TweeContext
+makeContext hints prob = run (hints, prob) $ \(_, prob) -> do
+  let
+    ty =
+      case types' prob of
+        []   -> indType
+        [ty] -> ty
+
+  var     <- newSymbol "X" ty
+  minimal <- newFunction (withLabel "minimal" (name "constant")) [] ty
+  true    <- newFunction (withLabel "true" (name "true")) [] ty
+  false   <- newFunction (withLabel "false" (name "false")) [] ty
+  equals  <- newFunction (withLabel "equals" (name "equals")) [ty, ty] ty
+
+  let allFuns = usort $ [minimal, true, false, equals] ++ Jukebox.functions (hints, prob)
+
+  return TweeContext {
+    ctx_var = var,
+    ctx_minimal = minimal,
+    ctx_true = true,
+    ctx_false = false,
+    ctx_equals = equals,
+    ctx_type = ty,
+    ctx_funs = Map.fromList (zip [0..] allFuns),
+    ctx_ids = Map.fromList (zip allFuns [0..]) }
+
+flattenGoals :: Int -> Bool -> Bool -> Bool -> Int -> [Jukebox.Term] -> Problem Clause -> Problem Clause
+flattenGoals backwardsGoal flattenNonGround flattenAll full depthMod hints prob =
+  run (hints, prob) $ \(_, prob) -> do
+    let ts = usort $ extraTerms prob
+    cs <- mapM define ts
+    return (prob ++ cs)
+  where
+    extraTerms prob = concatMap (input prob) prob
+    input prob Input{what = Clause (Bind _ [Neg (x Jukebox.:=: y)])} =
+      concatMap term (backwards backwardsGoal prob x) ++
+      concatMap term (backwards backwardsGoal prob y)
+    input _ Input{what = Clause (Bind _ [Pos (x Jukebox.:=: y)])}
+      | flattenAll = term x ++ term y
+    input _ _ = []
+
+    term t@(_f :@: ts) =
+      [ t
+      | ground t || flattenNonGround,
+        not (all isVar ts) || usort ts /= sort ts ] ++
+      if full then concatMap term ts else []
+    term _ = []
+
+    isVar (Jukebox.Var _) = True
+    isVar _ = False
+
+    depthOk t = depthMod == 1 || depth t `mod` depthMod == 0
+    depth (_f :@: ts) = 1 + maximum (0:map depth ts)
+    depth _ = 1
+
+    define (f :@: ts) = do
+      name <- newName f
+      let vs  = Jukebox.vars ts
+          g = name ::: FunType (map typ vs) (typ f)
+          c = clause [Pos (g :@: map Jukebox.Var vs Jukebox.:=: f :@: ts)]
+      return Input{ident = Nothing, tag = "flattening", kind = Jukebox.Ax Definition,
+                   what = c, source = Unknown }
+
+    backwards 0 _ t = [t]
+    backwards n cs t =
+      t:
+      [ v
+      | Input{what = Clause (Bind _ [Pos (x0 Jukebox.:=: y0)])} <- cs,
+        (x, y) <- [(x0, y0), (y0, x0)],
+        (s, k) <- contexts t,
+        sub <- maybeToList (Jukebox.match x s),
+        let u = k (Jukebox.subst sub y),
+        ground u,
+        v <- backwards (n-1) cs u ]
+
+hintGoals :: Problem Clause -> Problem Clause
+hintGoals prob =
+  prob ++ map define extraTerms
+  where
+    extraTerms = usort (concatMap input prob)
+    input Input{what = Clause (Bind _ [Neg (x Jukebox.:=: y)])} =
+      term x ++ term y
+    input _ = []
+
+    term t@(_f :@: ts) = t:concatMap term ts
+    term _ = []
+
+    define t =
+      Input{ident = Nothing, tag = "flattening", kind = Jukebox.Ax Definition, what = c, source = Unknown}
+      where
+        c = clause [Pos (Tru (hint :@: [t]))]
+        hint = name "$hint" ::: FunType [Jukebox.typ t] O
+
+addDistributivityHeuristic :: [Jukebox.Term] -> Problem Clause -> Problem Clause
+addDistributivityHeuristic hints prob =
+  run (hints, prob) $ \(_, prob) -> do
+    cs <- mapM add prob
+    return (prob ++ catMaybes cs)
+
+  where
+    add Input{what = Clause (Bind _ [Pos (t Jukebox.:=: u)])} =
+      case checkDistributivity t u `mplus` checkDistributivity u t of
+        Just (f, g, ty) -> do
+          name <- newName (base f ++ "_" ++ base g)
+          x <- Jukebox.Var <$> newSymbol "X" ty
+          y <- Jukebox.Var <$> newSymbol "Y" ty
+          z <- Jukebox.Var <$> newSymbol "Z" ty
+          Just <$> define name (g :@: [f :@: [x, y], z])
+        _ -> return Nothing
+    add _ = return Nothing
+
+    checkDistributivity
+      (f1 :@: [Jukebox.Var x1, g1 :@: [Jukebox.Var y1, Jukebox.Var z1]])
+      (g2 :@: [f2 :@: [Jukebox.Var x2, Jukebox.Var y2],
+               f3 :@: [Jukebox.Var x3, Jukebox.Var z2]])
+      | f1 == f2 && f2 == f3 && g1 == g2 &&
+        x1 == x2 && x2 == x3 && y1 == y2 && z1 == z2 =
+        Just (f1, g1, Jukebox.typ x1)
+      
+    checkDistributivity
+      (f1 :@: [g1 :@: [Jukebox.Var x1, Jukebox.Var y1], Jukebox.Var z1])
+      (g2 :@: [f2 :@: [Jukebox.Var x2, Jukebox.Var z2],
+       f3 :@: [Jukebox.Var y2, Jukebox.Var z3]])
+      | f1 == f2 && f2 == f3 && g1 == g2 &&
+        x1 == x2 && y1 == y2 && z1 == z2 && z2 == z3 =
+        Just (f1, g1, Jukebox.typ x1)
+    checkDistributivity _ _ = Nothing
+
+    define name t = do
+      let vs  = Jukebox.vars t
+          g = name ::: FunType (map typ vs) (typ t)
+          c = clause [Pos (g :@: map Jukebox.Var vs Jukebox.:=: t)]
+      return Input{ident = Nothing, tag = "distributivity_heuristic", kind = Jukebox.Ax Definition,
+                   what = c, source = Unknown }
+
+-- Encode existentials so that all goals are ground.
+addNarrowing :: Bool -> TweeContext -> Problem Clause -> Problem Clause
+addNarrowing alwaysNarrow TweeContext{..} prob =
+  unchanged ++ equalityClauses
+  where
+    prob' = [inp { ident = Just (variant "addNarrowing" [i :: Int]) } | (i, inp) <- zip [0..] prob]
+
+    (unchanged, nonGroundGoals) = partitionEithers (map f prob')
+      where
+        f inp@Input{what = Clause (Bind _ [Neg (x Jukebox.:=: y)])}
+          | not (ground x) || not (ground y) || alwaysNarrow =
+            Right (inp, (x, y))
+        f inp = Left inp
+
+    equalityClauses
+      | null nonGroundGoals = []
+      | otherwise =
+        -- Turn a != b & c != d & ...
+        -- into eq(a,b)=false & eq(c,d)=false & eq(X,X)=true & true!=false (esa)
+        -- and then extract the individual components (thm)
+        let
+          equalityLiterals =
+            -- true != false
+            ("true_equals_false", Neg ((ctx_true :@:) [] Jukebox.:=: (ctx_false :@: []))):
+            -- eq(X,X)=true
+            ("reflexivity", Pos (ctx_equals :@: [Jukebox.Var ctx_var, Jukebox.Var ctx_var] Jukebox.:=: (ctx_true :@: []))):
+            -- [eq(a,b)=false, eq(c,d)=false, ...]
+            [ (tag, Pos (ctx_equals :@: [x, y] Jukebox.:=: (ctx_false :@: [])))
+            | (Input{tag = tag}, (x, y)) <- nonGroundGoals ]
+
+          -- Equisatisfiable to the input clauses
+          justification =
+            Input {
+              ident = Just (name "addNarrowing2"),
+              tag  = "new_negated_conjecture",
+              kind = Jukebox.Ax NegatedConjecture,
+              what =
+                let form = And (map (Literal . snd) equalityLiterals) in
+                ForAll (Bind (Set.fromList (vars form)) form),
+              source =
+                inference "encode_existential" "esa"
+                  (map (fmap toForm . fst) nonGroundGoals) }
+
+          input tag form i =
+            Input {
+              ident = Just (variant "addNarrowing3" [i :: Int]),
+              tag = tag,
+              kind = Jukebox.Ax NegatedConjecture,
+              what = clause [form],
+              source =
+                inference "split_conjunct" "thm" [justification] }
+
+        in [input tag form i | ((tag, form), i) <- zip equalityLiterals [0..]]
+
+data PreEquation =
+  PreEquation {
+    pre_name :: String,
+    pre_form :: Input Form,
+    pre_eqn  :: (Jukebox.Term, Jukebox.Term) }
+
+-- Split the problem into axioms and ground goals.
+identifyProblem ::
+  TweeContext -> Problem Clause -> Either (Input Clause) ([PreEquation], [PreEquation])
+identifyProblem TweeContext{..} prob =
+  fmap partitionEithers (mapM identify prob)
+
+  where
+    pre inp x =
+      PreEquation {
+        pre_name = tag inp,
+        pre_form = fmap toForm inp,
+        pre_eqn = x }
+
+    identify inp@Input{what = Clause (Bind _ [Pos (t Jukebox.:=: u)])} =
+      return $ Left (pre inp (t, u))
+    identify inp@Input{what = Clause (Bind _ [Neg (t Jukebox.:=: u)])}
+      | ground t && ground u =
+        return $ Right (pre inp (t, u))
+    identify inp@Input{what = Clause (Bind _ [])} =
+      -- The empty clause can appear after clausification if
+      -- the conjecture was trivial
+      return $ Left (pre inp (Jukebox.Var ctx_var, ctx_minimal :@: []))
+    identify inp = Left inp
+
+runTwee :: GlobalFlags -> TSTPFlags -> HornFlags -> [String] -> Config Constant -> MainFlags -> (IO () -> IO ()) -> [Jukebox.Term] -> Problem Clause -> IO Answer
+runTwee globals (TSTPFlags tstp) horn precedence config0 flags@MainFlags{..} later hints obligs = {-# SCC runTwee #-} do
+  let
+    -- Encode whatever needs encoding in the problem
+    obligs1
+      | flags_flatten_goals_lightly = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground False False flags_flatten_every hints obligs
+      | flags_flatten_all = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground True True flags_flatten_every hints obligs
+      | flags_flatten_goals = flattenGoals flags_flatten_backwards_goal flags_flatten_nonground False True flags_flatten_every hints obligs
+      | otherwise = obligs
+    obligs2
+      | flags_distributivity_heuristic = addDistributivityHeuristic hints obligs1
+      | otherwise = obligs1
+    lowercaseSkolem x
+      | hasLabel "skolem" x =
+        withRenamer x $ \s i ->
+          case defaultRenamer s i of
+            Renaming xss xs ->
+              Renaming (map (map toLower) xss) (map toLower xs)
+      | otherwise = x
+    (hints', prettyObligs) = prettyNames (mapName lowercaseSkolem (hints, obligs2))
+    ctx = makeContext hints' prettyObligs
+    prob = addNarrowing flags_equals_transformation ctx prettyObligs
+
+  (unsortedAxioms0, goals0) <-
+    case identifyProblem ctx prob of
+      Left inp -> do
+        mapM_ (hPutStrLn stderr) [
+          "The problem contains the following clause, which is not a unit equality:",
+          indent (show (pPrintClauses [inp])),
+          "Twee only handles unit equality problems."]
+        exitWith (ExitFailure 1)
+      Right x -> return x
+
+  let
+    -- Work out a precedence for function symbols
+    prec c =
+      Precedence
+        (isType c)
+#ifdef USE_LPO
+        ((hasLabel "equals" c && Jukebox.arity c == 2) || isIfeq c)
+#else
+        (Just c == maxUnary)
+#endif
+        (isJust (elemIndex (base c) precedence))
+        (fmap negate (elemIndex (base c) precedence))
+        (maybeNegate (Map.findWithDefault 0 c funOccs))
+    maybeNegate = if flags_flip_ordering then negate else id
+    funOccs = funsOcc prob
+#ifndef USE_LPO
+    maxUnary =
+      case filter (\(f, _) -> arity f == 1 && not (isType f)) (Map.toList funOccs) of
+        [] -> Nothing
+        xs -> Just (fst (maximumBy (comparing snd) xs))
+#endif
+
+    -- Translate everything to Twee.
+    toTerm var t = tweeTerm flags horn ctx var prec t
+    toTerm' t = toTerm (varNums t) t
+    varNums :: Jukebox.Symbolic a => a -> Jukebox.Variable -> Int
+    varNums t = \x -> Map.findWithDefault undefined x ids
+      where
+        xs = usort (vars t)
+        ids = Map.fromList (zip xs [0..])
+    toEquation (t, u) =
+      canonicalise (toTerm var t :=: toTerm var u)
+      where
+        var = varNums (t, u)
+
+    axiomCompare ax1 ax2
+      | isEquality ax1' && not (isEquality ax2') = GT
+      | isEquality ax2' && not (isEquality ax1') = LT
+      | ax1' `simplerThan` ax2' = LT
+      | ax2' `simplerThan` ax1' = GT
+      | otherwise = EQ
+      where
+        ax1' = toEquation (pre_eqn ax1)
+        ax2' = toEquation (pre_eqn ax2)
+        isEquality ax = isJust (decodeEquality (eqn_lhs ax)) || isJust (decodeEquality (eqn_rhs ax))
+    axioms0 = sortBy axiomCompare unsortedAxioms0
+
+    goals =
+      [ goal n pre_name (toEquation pre_eqn)
+      | (n, PreEquation{..}) <- zip [1..] goals0 ]
+    axioms =
+      [ Axiom n pre_name (toEquation pre_eqn)
+      | (n, PreEquation{..}) <- zip [1..] axioms0 ]
+    defs =
+      [ axiom
+      | (axiom, PreEquation{..}) <- zip axioms axioms0,
+        isDefinition pre_form ]
+    isDefinition Input{source = Unknown} = True
+    isDefinition inp = tag inp `elem` flags_eliminate
+
+  -- Compute CP scoring heuristic
+  let
+    {-
+    goalNests = nests (map goal_eqn goals)
+    goalOccs = occs (map goal_eqn goals)
+    score depth hints eqn
+      | flags_goal_heuristic =
+        scoreCP cpConfig depth hints eqn *
+        product
+          [ pos (IntMap.findWithDefault 0 f eqnNests - IntMap.findWithDefault 0 f goalNests) *
+            pos (IntMap.findWithDefault 0 f eqnOccs - IntMap.findWithDefault 0 f goalOccs)
+          | f <- IntMap.keys eqnNests ] -- skip constants
+      | otherwise = 
+        scoreCP cpConfig depth hints eqn
+      where
+        eqnNests = nests eqn
+        eqnOccs = occs eqn
+
+        pos :: Int -> Float
+        pos n = if n <= 0 then 1 else fromIntegral n+1
+    -}
+    config = config0 { cfg_eliminate_axioms = if flags_flatten_regeneralise then defs else [] }
+
+  let
+    withHints = foldl' (addHint config) (initialState config) [toTerm (varNums h) h | h <- hints']
+    withGoals = foldl' (addGoal config) withHints goals
+    withAxioms = foldl' (addAxiom config) withGoals axioms
+    withBackwardsGoal = foldn rewriteGoalsBackwards withAxioms flags_backwards_goal
+
+  -- Set up tracing.
+  sayTrace <-
+    case flags_trace of
+      Nothing -> return $ \_ -> return ()
+      Just (file, mod) -> do
+        h <- openFile file WriteMode
+        hSetBuffering h LineBuffering
+        let put msg = hPutStrLn h msg
+        put $ ":- module(" ++ mod ++ ", [step/1, lemma/1, axiom/1, goal/1])."
+        put ":- discontiguous(step/1)."
+        put ":- discontiguous(lemma/1)."
+        put ":- discontiguous(axiom/1)."
+        put ":- discontiguous(goal/1)."
+        put ":- style_check(-singleton)."
+        return $ \msg -> hPutStrLn h msg
+  
+  let
+    say msg = unless (quiet globals) (putStrLn msg)
+    line = say ""
+    output = Output {
+      output_message = \msg -> do
+        say (prettyShow msg)
+        sayTrace (show (traceMsg msg)) }
+
+    traceMsg (NewActive _ active) =
+      step "add" [traceActive active]
+    traceMsg (NewEquation eqn) =
+      step "hard" [traceEqn eqn]
+    traceMsg (DeleteActive active) =
+      step "delete" [traceActive active]
+    traceMsg SimplifyQueue =
+      step "simplify_queue" []
+    traceMsg Interreduce =
+      step "interreduce" []
+    traceMsg (Status n) =
+      step "status" [pPrint n]
+
+    traceActive Active{active_top = Nothing, ..} =
+      traceApp "rule" [pPrint active_id, traceEqn (unorient active_rule)]
+    traceActive Active{active_top = Just top, ..} =
+      traceApp "rule" [pPrint active_id, traceEqn (unorient active_rule), traceEqn lemma1, traceEqn lemma2]
+      where
+        (lemma1, lemma2) =
+          find (steps (derivation active_proof))
+        find (s1:s2:_)
+          | eqn_rhs (equation (certify s1)) == top && eqn_lhs (equation (certify s2)) == top =
+            (lemmaOf s1, lemmaOf s2)
+        find (_:xs) = find xs
+        lemmaOf s =
+          case (usedLemmas s, usedAxioms s) of
+            ([p], []) -> equation p
+            ([], [ax]) -> axiom_eqn ax
+
+    traceEqn (t :=: u) =
+      pPrintPrec prettyNormal 6 t <+> text "=" <+> pPrintPrec prettyNormal 6 u
+    traceApp f xs =
+      pPrintTerm uncurried prettyNormal 0 (text f) xs
+
+    step :: String -> [Doc] -> Doc
+    step f xs = traceApp "step" [traceApp f xs] <#> text "."
+
+  say "Here is the input problem:"
+  forM_ axioms $ \Axiom{..} ->
+    say $ show $ nest 2 $
+      describeEquation "Axiom"
+        (show axiom_number) (Just axiom_name) axiom_eqn
+  forM_ goals $ \Goal{..} ->
+    say $ show $ nest 2 $
+      describeEquation "Goal"
+        (show goal_number) (Just goal_name) goal_eqn
+  line
+
+  state <-
+    case flags_stitch of
+      Nothing -> do
+        complete output config withBackwardsGoal
+      Just stitch -> do
+        let
+          (timeout, final_timeout) =
+            case cfg_max_time config of
+              Just time -> (time / 5, Just (time * 4 / 5))
+              Nothing -> (30, Nothing)
+        intermediate <- complete output config{cfg_max_time = Just timeout} withBackwardsGoal
+        let
+          score rule =
+            (KBO.size (lhs rule), lhs rule,
+             KBO.size (rhs rule), rhs rule)
+          actives =
+            sortBy (comparing (score . active_rule)) $
+            IntMap.elems (st_active_set intermediate)
+          pres = present (cfg_proof_presentation config){cfg_all_lemmas = True} (map active_proof actives) []
+          proofStr = show (pPrintPresentation (cfg_proof_presentation config){cfg_use_colour = False} pres)
+        line
+        say "Running Stitch..."
+        hintsStrs <- lines <$> readProcess stitch [] proofStr
+        let parseTerm str = toTerm' (Snippet.giveProblem prob (Snippet.form (TPTP.term TPTP.NoQuantification Map.empty)) str)
+        let hints = map parseTerm hintsStrs
+        mapM_ (say . show . pPrint) hints
+        let config' = config{cfg_max_time = final_timeout}
+        complete output config' $
+          interreduce config' $
+          simplifyQueue config' $
+          foldl' (addHint config') intermediate hints
+
+  line
+
+  case flags_dump_state of
+    Nothing -> return ()
+    Just dumpStateFile ->
+      BS.writeFile dumpStateFile (encode state)
+
+  when (solved state && flags_proof) $ later $ do
+    let
+      cfg_present
+        | tstp && flags_formal_proof =
+          (cfg_proof_presentation config){cfg_all_lemmas = True}
+        | otherwise =
+          cfg_proof_presentation config
+      pres = present cfg_present [] $ map (eliminateDefinitionsFromGoal defs) $ solutions state
+
+    case flags_dump_proof of
+      Nothing -> return ()
+      Just dumpProofFile ->
+        BS.writeFile dumpProofFile (encode pres)
+
+    sayTrace ""
+    forM_ (pres_axioms pres) $ \p ->
+      sayTrace $ show $
+        traceApp "axiom" [traceEqn (axiom_eqn p)] <#> text "."
+    forM_ (pres_lemmas pres) $ \p ->
+      sayTrace $ show $
+        traceApp "lemma" [traceEqn (equation p)] <#> text "."
+    forM_ (pres_goals pres) $ \p ->
+      sayTrace $ show $
+        traceApp "goal" [traceEqn (pg_goal_hint p)] <#> text "."
+
+    when (tstp && not flags_formal_proof) $ do
+      putStrLn "% SZS output start Proof"
+      let
+        axiomForms =
+          Map.fromList
+            (zip (map axiom_number axioms) (map pre_form axioms0))
+        goalForms =
+          Map.fromList
+            (zip (map goal_number goals) (map pre_form goals0))
+
+        findSource forms n =
+          case Map.lookup n forms of
+            Nothing -> []
+            Just inp -> go inp
+           where
+            go Input{source = Unknown} = []
+            go Input{source = Inference _ _ _ inps} = concatMap (go . inputValue) inps
+            go inp@Input{source = FromFile _ _} = [inp]
+
+      when flags_explain_encoding $ do
+        putStrLn "Take the following subset of the input axioms:"
+        mapM_ putStrLn $ map ("  " ++) $ lines $ showProblem $
+          usortBy (comparing show) $
+            (pres_axioms pres >>= findSource axiomForms . axiom_number) ++
+            (pres_goals pres >>= findSource goalForms . pg_number)
+
+        putStrLn ""
+        putStrLn "Now clausify the problem and encode Horn clauses using encoding 3 of"
+        putStrLn "http://www.cse.chalmers.se/~nicsma/papers/horn.pdf."
+        putStrLn "We repeatedly replace C & s=t => u=v by the two clauses:"
+        putStrLn "  fresh(y, y, x1...xn) = u"
+        putStrLn "  C => fresh(s, t, x1...xn) = v"
+        putStrLn "where fresh is a fresh function symbol and x1..xn are the free"
+        putStrLn "variables of u and v."
+        putStrLn "A predicate p(X) is encoded as p(X)=true (this is sound, because the"
+        putStrLn "input problem has no model of domain size 1)."
+        putStrLn ""
+        putStrLn "The encoding turns the above axioms into the following unit equations and goals:"
+        putStrLn ""
+      print $ pPrintPresentation (cfg_proof_presentation config) pres
+      putStrLn "% SZS output end Proof"
+      putStrLn ""
+  
+    when (tstp && flags_formal_proof) $ do
+      putStrLn "% SZS output start CNFRefutation"
+      print $ pPrintProof $
+        presentToJukebox ctx toTerm' (curry toEquation)
+          (zip (map axiom_number axioms) (map pre_form axioms0))
+          (zip (map goal_number goals) (map pre_form goals0))
+          pres
+      putStrLn "% SZS output end CNFRefutation"
+      putStrLn ""
+
+    unless tstp $ do
+      putStrLn "The conjecture is true! Here is a proof."
+      putStrLn ""
+      print $ pPrintPresentation (cfg_proof_presentation config) pres
+      putStrLn ""
+
+  when (not (quiet globals) && not (solved state)) $ later $ do
+    let
+      state' = interreduce config state
+      score rule =
+        (KBO.size (lhs rule), lhs rule,
+         KBO.size (rhs rule), rhs rule)
+      actives =
+        sortBy (comparing (score . active_rule)) $
+        IntMap.elems (st_active_set state')
+
+    when (tstp && configIsComplete config) $ do
+      putStrLn "% SZS output start Saturation"
+      print $ pPrintProof $
+        map pre_form axioms0 ++
+        map pre_form goals0 ++
+        [ Input Nothing "rule" (Jukebox.Ax Jukebox.Axiom) Unknown $
+            toForm $ clause
+              [Pos (jukeboxTerm ctx (lhs rule) Jukebox.:=: jukeboxTerm ctx (rhs rule))]
+        | rule <- rules state ]
+      putStrLn "% SZS output end Saturation"
+      putStrLn ""
+
+    if configIsComplete config then do
+      putStrLn "Ran out of critical pairs. This means the conjecture is not true."
+    else do
+      putStrLn "Gave up on reaching the given resource limit."
+    putStrLn "Here is the final rewrite system:"
+    forM_ actives $ \active ->
+      putStrLn ("  " ++ prettyShow (canonicalise (active_rule active)))
+    putStrLn ""
+    
+    when flags_proof_on_saturation $ do
+      let pres = present (cfg_proof_presentation config) (map active_proof actives) []
+      print $ pPrintPresentation (cfg_proof_presentation config) pres
+
+  return $
+    if solved state then Unsat Unsatisfiable Nothing
+    else if configIsComplete config && not (dropNonHorn horn) && not flags_give_up_on_saturation then Sat Satisfiable Nothing
+    else NoAnswer GaveUp
+
+data HornClause = HornClause [Equation Constant] (Equation Constant) deriving Eq
+instance Pretty HornClause where
+  pPrint (HornClause lhs rhs) = pPrint lhs <#> text "=>" <#> pPrint rhs
+data ClauseProof = ClauseProof (Maybe Name) HornClause InputSource
+instance Pretty ClauseProof where
+  pPrint (ClauseProof _ cl _) = pPrint cl
+type ConjunctiveProof = [ClauseProof] -- first proof is "main" clause
+
+jukeboxClause :: TweeContext -> [Equation Constant] -> Equation Constant -> Form
+jukeboxClause ctx lhs rhs =
+  toForm $ clause $ map (Neg . eqn) lhs ++ [Pos (eqn rhs)]
+  where
+    eqn (t :=: u) = jukeboxTerm ctx t Jukebox.:=: jukeboxTerm ctx u
+
+toInput :: TweeContext -> ClauseProof -> Input Form
+toInput ctx (ClauseProof ident (HornClause lhs rhs) pf) =
+  Input {
+    ident = ident,
+    tag = "step",
+    kind = Jukebox.Ax Jukebox.Axiom,
+    what = jukeboxClause ctx lhs rhs,
+    source = pf }
+
+toInput' :: TweeContext -> ConjunctiveProof -> Input Form
+toInput' ctx pf =
+  Input {
+    ident = Nothing,
+    tag = "conjunction",
+    kind = Jukebox.Ax Jukebox.Axiom,
+    what = And (map what inps),
+    source = inference "conjunction" "thm" inps }
+  where
+    inps = map (toInput ctx) pf
+
+findProof :: TweeContext -> ConjunctiveProof -> HornClause -> Maybe InputSource
+findProof ctx pf c =
+  trace ("finding " ++ prettyShow c) $
+  trace ("in " ++ prettyShow pf) $
+  listToMaybe $
+    [inf | ClauseProof _ c' inf <- pf, c == c'] ++
+    [inference "rewriting" "thm" (map (toInput ctx) [p1, p2]) | p1@(ClauseProof _ c1 _) <- pf, p2@(ClauseProof _ c2 _) <- pf, rewrites c1 c2 c]
+  where
+    rewrites (HornClause lhs (t :=: u)) (HornClause [] (u' :=: v)) (HornClause lhs' (t' :=: v'))
+      | lhs == lhs' && t == t' && u == u' && v == v' = True
+    rewrites _ _ _ = False
+
+clauseSets :: Equation Constant -> [(Equation Constant, [HornClause])]
+clauseSets (t :=: u) = do
+  (t', cs1) <- splits t
+  (u', cs2) <- splits u
+  return (t' :=: u', cs1 ++ cs2)
+  where
+    splits t@Var{} = [(t, [])]
+    splits (App (Sym Constant{con_label = Just "ifeq"}) ts) =
+      let [t, u, v, w] = unpack ts in
+        [(v, [HornClause [] (t :=: u)]), (w, [HornClause [t :=: u] (v :=: w)])]
+    splits (App f ts) =
+      [ (build (app f (map fst ss)), concatMap snd ss) | ss <- mapM splits (unpack ts) ]
+
+-- TODO don't go back and forth between Twee terms and Jukebox terms the whole time
+axiomProof :: (Jukebox.Term -> Term Constant) -> (Jukebox.Term -> Jukebox.Term -> Equation Constant) -> Input Form -> ConjunctiveProof
+axiomProof toTerm toEquation Input{source = Inference _ "clausify" _ [c]} =
+  axiomProof toTerm toEquation (inputValue c)
+axiomProof toTerm toEquation Input{source = Inference _ "type_encoding" _ [c]} =
+  axiomProof toTerm toEquation (inputValue c)
+axiomProof toTerm toEquation inp@Input{source = Inference _ "ifeq_elim" _ _} =
+  case toClause (what inp) of
+    Just (Clause (Bind _ [Pos (lhs Jukebox.:=: rhs)])) ->
+      trace ("eliminator: " ++ show (lhs, rhs)) $
+      trace (prettyShow (toEquation lhs rhs)) $
+      let App (Sym Constant{con_label = Just "ifeq"}) ts :=: y'@Var{} = toEquation lhs rhs
+          [x@Var{}, x'@Var{}, y@Var{}, z@Var{}] | trace (prettyShow (x, x', y, z)) $ x == x' && y == y' = unpack ts
+      in [reflexivity y, reflexivity x]
+axiomProof toTerm toEquation inp@Input{source = Inference _ "ifeq_intro" _ [c]} =
+  case toClause (what inp) of
+    Just (Clause (Bind _ [Pos (lhs Jukebox.:=: rhs)]))
+      | App (Sym Constant{con_label = Just "ifeq"}) ts :=: w' <- traceShow (lhs, rhs) $ toEquation lhs rhs ->
+        let [t, u, v, w] | w == w' = unpack ts
+        in [reflexivity w, ClauseProof Nothing (HornClause [t :=: u] (v :=: w)) (source (inputValue c))]
+    _ -> axiomProof toTerm toEquation (inputValue c)
+axiomProof _ toEquation inp =
+  case toClause (what inp) of
+    Just (Clause (Bind _ [Pos (t Jukebox.:=: u)])) ->
+      [ClauseProof (ident inp) (HornClause [] (toEquation t u)) (source inp)]
+
+reflexivity :: Term Constant -> ClauseProof
+reflexivity t =
+  ClauseProof Nothing (HornClause [] (t :=: t)) (inference "reflexivity" "thm" [])
+
+congruence :: Sym Constant -> [Term Constant] -> [Term Constant] -> ConjunctiveProof -> ConjunctiveProof
+congruence f ts us (ClauseProof _ (HornClause lhs (t :=: u)) inf:pfs) =
+  ClauseProof Nothing (HornClause lhs (cong t :=: cong u)) inf:pfs
+  where
+    cong t = build (app f (ts ++ [t] ++ us))
+
+symmetry :: ConjunctiveProof -> ConjunctiveProof
+symmetry (ClauseProof _ (HornClause lhs (t :=: u)) inf:pfs) =
+  ClauseProof Nothing (HornClause lhs (u :=: t)) inf:pfs
+
+-- TODO we are erasing idents everywhere, maybe labelProof shsould instead convert each one to an Input Form and wrap it in a ClauseProof
+substitute :: Subst Constant -> ConjunctiveProof -> ConjunctiveProof
+substitute sub pfs = [ClauseProof Nothing (HornClause (subst sub lhs) (subst sub rhs)) inf | ClauseProof _ (HornClause lhs rhs) inf <- pfs]
+
+labelProof :: Name -> ConjunctiveProof -> ConjunctiveProof
+labelProof ident pf = [ClauseProof (Just (variant ident [i])) c inf | (i, ClauseProof _ c inf) <- zip [0 :: Int ..] pf]
+
+-- Transform a proof presentation into a Jukebox proof.
+presentToJukebox ::
+  TweeContext ->
+  (Jukebox.Term -> Term Constant) ->
+  (Jukebox.Term -> Jukebox.Term -> Equation Constant) ->
+  -- Axioms, indexed by axiom number.
+  [(Int, Input Form)] ->
+  -- N.B. the formula here proves the negated goal.
+  [(Int, Input Form)] ->
+  Presentation Constant ->
+  Problem Form
+presentToJukebox ctx toTerm toEquation axioms goals Presentation{..} =
+  [ Input {
+      ident = Nothing,
+      tag = pg_name,
+      kind = Jukebox.Ax Jukebox.Axiom,
+      what = false,
+      source =
+        inference "resolution" "thm"
+          [-- A proof of t != u
+           existentialHack pg_goal_hint (fromJust (lookup pg_number goals)),
+           -- A proof of t = u
+           toInput ctx (the (fromJust (Map.lookup pg_number goal_proofs)))] }
+  | ProvedGoal{..} <- pres_goals ]
+
+  where
+    axiom_proofs =
+      Map.fromList
+        [ (axiom_number, labelProof (ident axiom_number) (axiomProof toTerm toEquation $! traceShowId (fromJust (lookup axiom_number axioms))))
+        | Axiom{..} <- pres_axioms ]
+      where
+        ident i = variant "axiom" [i]
+
+    lemma_proofs =
+      Map.fromList [(p, labelProof (ident i) (tstp p)) | (i, p) <- zip [0..] pres_lemmas]
+      where
+        ident i = variant "lemma" [i :: Int]
+
+    goal_proofs =
+      Map.fromList [(pg_number, tstp pg_proof) | ProvedGoal{..} <- pres_goals]
+
+    the [x] = x
+
+    tstp :: Proof Constant -> ConjunctiveProof
+    tstp p = snd (foldl1 combine (map step' (steps (derivation p))))
+
+    combine :: (Equation Constant, ConjunctiveProof) -> (Equation Constant, ConjunctiveProof) -> (Equation Constant, ConjunctiveProof)
+    combine (lhs1 :=: rhs1, p1) (lhs2 :=: rhs2, p2) =
+      -- TODO try all possible values of clauseSets (lhs1 :=: rhs2), see if we can match up
+      -- main one should either be rewriting wrt main one,
+      -- or clash resolvable by resolution
+      case [pf | (eqn, cs) <- clauseSets (lhs1 :=: rhs2), pf <- maybeToList (mapM find (HornClause [] eqn:cs))] of
+        (pf:_) ->
+          case pf of
+            ClauseProof _ (HornClause [] eqn) _:_ | eqn == (lhs1 :=: rhs2) -> (lhs1 :=: rhs2, pf)
+            _ -> error ("failed proof from:\n" ++ prettyShow (lhs1 :=: rhs1, p1) ++ "\nand\n" ++ prettyShow (lhs2 :=: rhs2, p2) ++ "\nto get\n" ++ prettyShow pf)
+        _ -> error ("can't combine:\n" ++ prettyShow (lhs1 :=: rhs1, p1) ++ "\nand\n" ++ prettyShow (lhs2 :=: rhs2, p2) ++ "\nwith\n" ++ prettyShow (clauseSets (lhs1 :=: rhs2)))
+      where
+        find c = ClauseProof Nothing c <$> findProof ctx (p1 ++ p2) c
+
+    step' p =
+      case pf of
+        ClauseProof _ (HornClause [] eqn') _:_ | eqn' `elem` map fst (clauseSets eqn) -> (eqn, pf)
+        _ -> error ("failed step:\n" ++ prettyShow (eqn, p) ++ "\nresulting in:\n" ++ prettyShow pf)
+      where
+        eqn = equation (certify p)
+        pf = step p
+
+    step :: Derivation Constant -> ConjunctiveProof
+    step (Symm p) = symmetry (step p)
+    step (Cong f ps) =
+      case span isRefl ps of
+        (qs, r:rs) | all isRefl rs ->
+          congruence f (map unRefl qs) (map unRefl rs) (step r)
+      where
+        isRefl Refl{} = True
+        isRefl _ = False
+        unRefl (Refl t) = t
+    step (UseAxiom Axiom{..} sub) =
+      substitute sub (fromJust (Map.lookup axiom_number axiom_proofs))
+    step (UseLemma lemma sub) =
+      substitute sub (fromJust (Map.lookup lemma lemma_proofs))
+{-
+    deriv :: Derivation Constant -> Input Form
+    deriv p =
+      Input {
+        ident = Nothing,
+        tag = "step",
+        kind = Jukebox.Ax Jukebox.Axiom,
+        what = jukeboxEquation (equation (certify p)),
+        source =
+          inference name "thm" sources }
+      where
+        (name, sources) = unpack p
+
+    unpack :: Derivation Constant -> (String, [Input Form])
+    unpack (Refl _) = ("reflexivity", [])
+    unpack (Symm p) = ("symmetry", [deriv p])
+    unpack (Trans p q) = ("transitivity", [deriv p, deriv q])
+    unpack (Cong _ ps) = ("congruence", [deriv p | p <- ps, let t :=: u = equation (certify p), t /= u])
+    unpack (UseAxiom Axiom{..} _) =
+      ("substitution", [toInput' ctx (fromJust (Map.lookup axiom_number axiom_proofs))])
+    unpack (UseLemma lemma _) =
+      ("substitution", [fromJust (Map.lookup lemma lemma_proofs)])
+
+    jukeboxEquation :: Equation Constant -> Form
+    jukeboxEquation (t :=: u) =
+      toForm $ clause [Pos (jukeboxTerm ctx t Jukebox.:=: jukeboxTerm ctx u)]
+-}
+    -- An ugly hack: since Twee.Proof decodes $true = $false into a
+    -- proof of the existentially quantified goal, we need to do the
+    -- same decoding at the Jukebox level.
+    existentialHack eqn input =
+      case find input of
+        [] -> error $ "bug in TSTP output: can't fix up decoded existential"
+        (inp:_) -> inp
+        where
+          -- Check if this looks like the correct clause;
+          -- if not, try its ancestors.
+          find inp | ok inp = [inp]
+          find Input{source = Inference _ _ _ inps} =
+            concatMap (find . inputValue) inps
+          find _ = []
+
+          ok inp =
+            case toClause (what inp) of
+              Nothing -> False
+              Just (Clause (Bind _ [Neg (t' Jukebox.:=: u')])) ->
+                let
+                  eqn' = toEquation t' u'
+                  ts = buildList [eqn_lhs eqn, eqn_rhs eqn]
+                  us = buildList [eqn_lhs eqn', eqn_rhs eqn']
+                in
+                  isJust (matchList ts us) && isJust (matchList us ts)
+
+main = do
+  hSetBuffering stdout LineBuffering
+  stampM (intern "twee") . join . parseCommandLineWithExtraArgs
+    ["--no-conjunctive-conjectures", "--no-split"]
+#ifdef VERSION_twee
+    "Twee, the wonderful equation engine" . version ("twee version " ++ VERSION_twee) $
+#else
+    "Twee, the wonderful equation engine" . version "twee development version" $
+#endif
+      globalFlags *> parseMainFlags *>
+      -- hack: get --quiet and --no-proof options to appear before --tstp
+      forAllFilesBox <*>
+        (readProblemBox =>>=
+         expert clausifyBox =>>=
+         forAllConjecturesBox <*>
+           (combine <$>
+             expert hornToUnitBox <*>
+             parseConfig <*>
+             parseMainFlags <*>
+             (toFormulasBox =>>=
+              expert (toFof <$> clausifyBox <*> pure (tags True)) =>>=
+              expert clausifyBox =>>= expert oneConjectureBox) <*>
+             (runTwee <$> globalFlags <*> tstpFlags <*> expert hornFlags <*> parsePrecedence)))
+  profile
+  where
+    getHint Input{what = Clause (Bind _ [Pos (Tru (hint :@: [t]))])}
+      | base (name hint) == "$hint" = Left t
+    getHint c = Right c
+    combine horn config main encode prove later prob0 = do
+      let prob1 = if flags_hint_goals main then hintGoals prob0 else prob0
+      let (hints, nonHints) = partitionEithers (map getHint prob1)
+      res <- horn nonHints
+      case res of
+        Left ans -> return ans
+        Right prob -> do
+          let
+            isUnitEquality [Pos (_ Jukebox.:=: _)] = True
+            isUnitEquality [Neg (_ Jukebox.:=: _)] = True
+            isUnitEquality _ = False
+            isUnit = all isUnitEquality (map (toLiterals . what) prob1)
+            main' = if isUnit then main{flags_explain_encoding = False} else main -- {flags_formal_proof = False}
+          encode prob >>= prove config main' later hints
diff --git a/misc/static-libstdc++ b/misc/static-libstdc++
deleted file mode 100644
--- a/misc/static-libstdc++
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/zsh
-typeset -a args
-
-process() {
-    for arg in $*; do
-        case $arg in
-            \"*\")
-                process $(echo $arg | cut -c2- | rev | cut -c2- | rev)
-                ;;
-            @*)
-                process $(cat $(echo $arg | cut -c2-))
-                ;;
-            -lstdc++ | -fuse-ld=gold)
-                ;;
-            *)
-                args+=$arg
-                ;;
-        esac
-    done
-}
-
-process $*
-
-exec g++ -static-libgcc -static-libstdc++ $args
diff --git a/test/Common.hs b/test/Common.hs
new file mode 100644
--- /dev/null
+++ b/test/Common.hs
@@ -0,0 +1,124 @@
+-- Common code used by the rest of the tests.
+
+{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, DeriveGeneric, DeriveAnyClass #-}
+module Common where
+
+import Data.Intern
+import Twee.Base
+import Twee.Constraints
+import Twee.Equation
+import Twee.Utils
+import qualified Twee.KBO as KBO
+import Control.Monad
+import Data.Hashable
+import Data.List
+import Data.Maybe
+import Data.Typeable
+import GHC.Generics
+import Test.QuickCheck hiding (Function)
+import Text.Printf
+import Data.Binary.Sharing
+
+data Func = Min | Skolem Int | F Int Integer deriving (Eq, Ord, Generic, Hashable, Binary)
+
+instance Show Func where
+  show Min = "m"
+  show (Skolem n) = printf "sk%d" n
+  show (F x y) = printf "f%d_%d" x y
+
+instance Pretty Func where
+  pPrint Min = text "m"
+  pPrint (Skolem m) = text "sk" <#> int m
+  pPrint (F 3 _) = text "a"
+  pPrint (F 4 _) = text "b"
+  pPrint (F 5 _) = text "zero"
+  pPrint (F 6 _) = text "plus"
+  pPrint (F 7 _) = text "times"
+  pPrint (F f _) = text "f" <#> int f
+instance PrettyTerm Func
+instance Arbitrary (Subst Func) where
+  arbitrary = fmap fromJust (fmap listToSubst (liftM2 zip (fmap nub arbitrary) (infiniteListOf arbitrary)))
+instance Arbitrary Func where
+  arbitrary =
+    frequency
+      [(10, F <$> choose (0, 2) <*> choose (1, 3)),
+       (2, Skolem <$> choose (0, 2)),
+       (1, return Min)]
+instance Minimal Func where
+  minimal = intern Min
+  skolem n = intern (Skolem n)
+instance KBO.Sized Func where
+  size (F _ n) = n
+  size _ = 1
+instance Weighted Func where
+  weight (F _ n) = fromIntegral n
+  weight _ = 1
+instance KBO.ArgWeighted Func where argWeight _ = 1
+class Arity f where
+  arity :: f -> Int
+instance Arity Func where
+  arity (F 0 _) = 0
+  arity (F 1 _) = 1
+  arity (F 2 _) = 2
+  arity (F 3 _) = 0 -- a
+  arity (F 4 _) = 0 -- b
+  arity (F 5 _) = 0 -- zero
+  arity (F 6 _) = 2 -- plus
+  arity (F 7 _) = 2 -- times
+  arity _ = 0
+instance EqualsBonus Func
+
+instance Arbitrary Var where arbitrary = fmap V (choose (0, 3))
+instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Sym f) where
+  arbitrary = fmap intern arbitrary
+
+instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Term f) where
+  arbitrary =
+    sized $ \n ->
+      oneof $
+        [ build <$> var <$> arbitrary ] ++
+        [ do { f <- arbitrary; build <$> app (Sym f) <$> vectorOf (arity f) (resize ((n-1) `div` arity f) arbitrary :: Gen (Term f)) } | n > 0 ]
+  shrink (App f ts0) =
+    ts ++ (build <$> app f <$> shrinkOne ts)
+    where
+      ts = unpack ts0
+      shrinkOne [] = []
+      shrinkOne (x:xs) =
+        [ y:xs | y <- shrink x ] ++
+        [ x:ys | ys <- shrinkOne xs ]
+  shrink _ = []
+
+instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (TermList f) where
+  arbitrary = buildList <$> listOf (arbitrary :: Gen (Term f))
+  shrink = map buildList . shrink . unpack
+
+data Pair f = Pair (Term f) (Term f) deriving Show
+
+instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Pair f) where
+  arbitrary = liftM2 Pair arbitrary arbitrary
+  shrink (Pair x y) =
+    [ Pair x' y  | x' <- shrink x ] ++
+    [ Pair x y'  | y' <- shrink y ] ++
+    [ Pair x' y' | x' <- shrink x, y' <- shrink y ]
+
+instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Equation f) where
+  arbitrary = do
+    Pair t u <- arbitrary
+    return (t :=: u)
+  shrink (t :=: u) = [t' :=: u' | Pair t' u' <- shrink (Pair t u)]
+
+instance Ordered Func where
+  lessIn = KBO.lessIn
+  lessEq = KBO.lessEq
+  lessEqSkolem = KBO.lessEqSkolem
+
+instance Function f => Arbitrary (Model f) where
+  arbitrary = fmap (modelFromOrder . map Variable . nub) arbitrary
+  shrink = weakenModel
+
+genSubst :: [Var] -> Gen (Subst Func)
+genSubst xs = do
+  let xs' = usort xs
+  ts <- sequence [arbitrary | _ <- xs']
+  let Just sub = listToSubst (zip xs' ts)
+  return sub
diff --git a/test/Index.hs b/test/Index.hs
new file mode 100644
--- /dev/null
+++ b/test/Index.hs
@@ -0,0 +1,73 @@
+-- Tests for the term index.
+
+{-# LANGUAGE TupleSections #-}
+module Index(tests) where
+
+import Common
+import Twee.Base
+import Twee.Index(Index)
+import qualified Twee.Index as Index
+import Data.Hashable
+import Data.List
+import Data.Maybe
+import Data.Typeable
+import Test.Tasty
+import Test.Tasty.QuickCheck
+import Data.Binary.Sharing
+
+newtype IndexOps f = IndexOps [IndexOp f] deriving Show
+data IndexOp f = Add (Term f) | Delete (Term f) deriving Show
+
+instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (IndexOps f) where
+  arbitrary =
+    sized $ \n -> IndexOps <$> take n <$> arbOps []
+    where
+      arbOps ts =
+        frequency $
+          [(2, do { t <- arbitrary; ops <- arbOps (t:ts); return (Add t:ops) })] ++
+          [(1, do { t <- elements ts; ops <- arbOps (delete t ts); return (Delete t:ops) }) | not (null ts)]
+  shrink (IndexOps ops) =
+    IndexOps <$> shrinkList shr ops
+    where
+      shr (Add t) = Add <$> shrink t
+      shr (Delete t) = Delete <$> shrink t
+
+prop_index_insert :: [Term Func] -> Term Func -> Property
+prop_index_insert ts u =
+  counterexample (show ts') $
+  counterexample (show idx) $
+  sort (catMaybes [fmap (,t) (match t u) | t <- ts']) ===
+  sort (Index.matches u idx)
+  where
+    idx = foldr (\t -> Index.insert t t) Index.empty ts
+    ts' = map canonicalise ts
+
+prop_index_invariant :: IndexOps Func -> Property
+prop_index_invariant (IndexOps ops) =
+  flip (foldr (counterexample . show)) idxs $
+  property $ Index.invariant (last idxs)
+  where
+    idxs = scanl (\idx op -> applyIndex op idx) Index.empty ops
+    applyIndex (Add t) = Index.insert t t
+    applyIndex (Delete t) = Index.delete t t
+
+prop_index_serialise :: [Term Func] -> Property
+prop_index_serialise ts =
+  counterexample (show idx) $
+  counterexample (show serial) $
+  counterexample (show idx') $
+  Index.elems idx === Index.elems idx' .&&.
+  serial === encode idx'
+  where
+    idx, idx' :: Index Func (Term Func)
+    idx = foldr (\t -> Index.insert t t) Index.empty ts
+    serial = encode idx
+    idx' = decode serial
+
+tests :: TestTree
+tests =
+  localOption (QuickCheckTests 100000) $
+  testGroup "Term indexing"
+    [testProperty "Invariant holds" prop_index_invariant,
+     testProperty "Inserted terms are found" prop_index_insert,
+     testProperty "Serialisation round trip" prop_index_serialise]
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,21 @@
+module Main where
+
+import qualified Index
+import qualified Nest
+import qualified Ordering
+import qualified Serial
+import qualified TermOrder
+import qualified Terms
+import Test.Tasty
+
+tests :: TestTree
+tests =
+  testGroup "Twee tests"
+    [Terms.tests,
+    TermOrder.tests,
+    Ordering.tests,
+    Index.tests,
+    Nest.tests,
+    Serial.tests]
+
+main = defaultMain tests
diff --git a/test/Nest.hs b/test/Nest.hs
new file mode 100644
--- /dev/null
+++ b/test/Nest.hs
@@ -0,0 +1,82 @@
+-- Tests for the 'nests' function.
+
+module Nest(tests) where
+
+import Common
+import Data.Intern
+import Twee.Base
+import Test.Tasty
+import Test.Tasty.QuickCheck
+import qualified Data.IntMap as M
+
+-- Define 'nest' from Fuchs "The application of goal-oriented heuristics...",
+-- then refine it to a more efficient version
+nestf :: Func -> Term Func -> Int
+nestf f _ | arity f == 0 = 0
+nestf f t = hnest (Sym f) t 0 0
+  where
+    hnest _ (Var _) c a = max c a
+    hnest _ (App _ Nil) c a = max c a
+    hnest f (App g ts) c a
+      | f == g = maximum [hnest f t (c+1) a | t <- unpack ts]
+      | otherwise = maximum [hnest f t 0 (max c a) | t <- unpack ts]
+
+-- a simpler version, to illustrate the meaning
+nestf1 :: Func -> Term Func -> Int
+nestf1 f t = hnest (Sym f) t 0
+  where
+    hnest _ (Var _) c = c
+    hnest _ (App _ Nil) c = c
+    hnest f (App g ts) c
+      | f == g = maximum [hnest f t (c+1) | t <- unpack ts]
+      | otherwise = max c (maximum [hnest f t 0 | t <- unpack ts])
+
+-- a more efficient version
+nestf2 :: Func -> Term Func -> Int
+nestf2 f t = hnest (Sym f) (singleton t) 0 0
+  where
+    hnest _ Nil c a = max c a
+    hnest f (Cons (Var _) ts) c a = hnest f ts c a
+    hnest f (Cons (App _ Nil) ts) c a = hnest f ts c a
+    hnest f (Cons (App g ts) us) c a
+      | f == g =
+        let a' = hnest f ts (c+1) a
+        in hnest f us c a'
+      | otherwise =
+        let a' = hnest f ts 0 a
+        in hnest f us c a'
+
+-- a version that does all function symbols at once
+nestf3 :: Term Func -> M.IntMap Int
+nestf3 t = hnest 0 0 M.empty (singleton t)
+  where
+    hnest f c as Nil = M.insertWith max f c as
+    hnest f c as (Cons (Var _) ts) = hnest f c as ts
+    hnest f c as (Cons (App _ Nil) ts) = hnest f c as ts
+    hnest f c as (Cons (App g ts) us) =
+      let as' = hnest (symId g) (if f == symId g then c+1 else 1) as ts
+      in hnest f c as' us
+
+prop_nest_1 :: Func -> Term Func -> Property
+prop_nest_1 f t = nestf f t === nestf1 f t
+
+prop_nest_2 :: Func -> Term Func -> Property
+prop_nest_2 f t = nestf f t === nestf2 f t
+
+prop_nest_3 :: Func -> Term Func -> Property
+prop_nest_3 f t =
+  nestf f t === M.findWithDefault 0 (symId (Sym f)) (nestf3 t)
+
+prop_nests :: Func -> TermList Func -> Property
+prop_nests f ts =
+  maximum (0:map (nestf f) (unpack ts)) ===
+  M.findWithDefault 0 (symId (Sym f)) (nests ts)
+
+tests :: TestTree
+tests =
+  localOption (QuickCheckTests 100000) $
+  testGroup "Nest function" [
+    testProperty "nestf1 is correct" prop_nest_1,
+    testProperty "nestf2 is correct" prop_nest_2,
+    testProperty "nestf3 is correct" prop_nest_3,
+    testProperty "nests is correct" prop_nests]
diff --git a/test/Ordering.hs b/test/Ordering.hs
new file mode 100644
--- /dev/null
+++ b/test/Ordering.hs
@@ -0,0 +1,85 @@
+-- Tests for equation and rule ordering.
+
+module Ordering(tests) where
+
+import Common
+import Test.QuickCheck hiding (Function, Fun)
+import Twee.Base
+import Twee.Constraints
+import Twee.Equation
+import Twee.Utils
+import Twee.Rule
+import Twee.CP
+import Twee.Proof
+import qualified Twee.KBO as KBO
+import Data.Maybe
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+-- TODO: this only checks for the default order (KBO)
+-- But very similar things are covered in TermOrder.hs.
+prop_reducesWith_correct :: Model Func -> Pair Func -> Subst Func -> Property
+prop_reducesWith_correct model (Pair t u) sub =
+  counterexample ("Model: " ++ prettyShow model) $
+  counterexample ("Subst: " ++ prettyShow sub) $
+  conjoin $ do
+    let cp = CriticalPair (t :=: u) Nothing (axiom (Axiom 0 "dummy" Nothing (t :=: u)))
+    r@Rule{lhs = t', rhs = u'} <- map (flip orient (certify (cp_proof cp))) (map cp_eqn (split cp))
+    return $
+      counterexample ("LHS:   " ++ prettyShow t') $
+      counterexample ("RHS:   " ++ prettyShow u') $
+      counterexample ("Rule:  " ++ prettyShow r) $
+      counterexample ("Inst:  " ++ prettyShow (subst sub r)) $
+      counterexample ("Res:   " ++ show (lessIn model (subst sub u') (subst sub t'))) $
+      not (reducesInModel model r sub) || isJust (lessIn model (subst sub u') (subst sub t'))
+
+prop_simplerThan_irreflexive :: Equation Func -> Bool
+prop_simplerThan_irreflexive eq =
+  not (eq `simplerThan` eq)
+
+prop_simplerThan_antisymmetric :: Equation Func -> Equation Func -> Property
+prop_simplerThan_antisymmetric eq1 eq2 =
+  eq1 `simplerThan` eq2 ==> not (eq2 `simplerThan` eq1)
+
+prop_order_simplerThan :: Equation Func -> Equation Func -> Bool
+prop_order_simplerThan eq1 eq2 =
+  eq1 `simplerThan` eq2 || eq2 `simplerThan` eq1 || order eq1 == order eq2
+
+prop_order_swap :: Equation Func -> Property
+prop_order_swap (t :=: u) =
+  order (t :=: u) === order (u :=: t)
+
+prop_order_rearrange :: Equation Func -> Property
+prop_order_rearrange eq@(t :=: u) =
+  let vs = usort (vars eq) in
+  forAll (shuffle vs) $ \ws swap (NonNegative n) ->
+    let
+      Just sub = listToSubst (zip vs [build (var (V (w + n))) | V w <- ws])
+      eq' = subst sub (if swap then u :=: t else t :=: u)
+    in
+      canonicalise (order eq) === canonicalise (order eq')
+
+prop_order_size :: Equation Func -> Property
+prop_order_size eq =
+  let eq' = order eq in
+  counterexample (show eq) $
+  KBO.size (eqn_lhs eq') >= KBO.size (eqn_rhs eq')
+
+prop_order_erase :: Equation Func -> Property
+prop_order_erase eq =
+  let eq' = order eq in
+  counterexample (show eq) $
+  eqn_rhs (ground eq') `lessEqSkolem` eqn_lhs (ground eq')
+
+tests :: TestTree
+tests =
+  localOption (QuickCheckTests 100000) $
+  testGroup "Equation ordering" [
+    testProperty "reducesWith respects KBO" prop_reducesWith_correct,
+    testProperty "simplerThan irreflexive" prop_simplerThan_irreflexive,
+    testProperty "simplerThan antisymmetric" prop_simplerThan_antisymmetric,
+    testProperty "order/simplerThan trichotomogy" prop_order_simplerThan,
+    testProperty "order invariant under swap" prop_order_swap,
+    testProperty "order invariant under rearrangement" prop_order_rearrange,
+    testProperty "order respects size" prop_order_size,
+    testProperty "order respects term order of erased terms" prop_order_erase ]
diff --git a/test/Serial.hs b/test/Serial.hs
new file mode 100644
--- /dev/null
+++ b/test/Serial.hs
@@ -0,0 +1,56 @@
+-- Tests for serialisation.
+
+{-# LANGUAGE DeriveGeneric, DeriveAnyClass, StandaloneDeriving #-}
+module Serial(tests) where
+
+import Test.Tasty
+import Test.Tasty.QuickCheck
+import Data.Binary.Sharing
+import Data.Intern
+import GHC.Generics
+import Data.Hashable
+import qualified Data.ByteString.Lazy as BS
+import Data.Int
+
+data Tree = Leaf Int8 | Node Tree Tree | SharedNode (Shared Tree) | SymNode (Sym Tree)
+  deriving (Eq, Show, Generic, Binary)
+instance Hashable Tree where
+  hashWithSalt s (Leaf x) = hashWithSalt s (0 :: Int, x)  
+  hashWithSalt s (Node t u) = hashWithSalt s (1 :: Int, t, u)
+  hashWithSalt s (SharedNode (Shared t)) = hashWithSalt s (2 :: Int, t)
+  hashWithSalt s (SymNode (Sym t)) = hashWithSalt s (2 :: Int, t)
+
+instance Arbitrary Tree where
+  arbitrary = sized arb
+    where
+      arb n =
+        frequency [
+          (1, Leaf <$> arbitrary),
+          (n, Node <$> arb (n `div` 2) <*> arb (n `div` 2)),
+          (n, SharedNode . Shared <$> arb (n-1)),
+          (n, SymNode . Sym <$> arb (n-1)) ]
+
+  shrink (Leaf n) = Leaf <$> shrink n
+  shrink (Node t u) =
+    [t, u] ++
+    [Node t' u' | (t', u') <- shrink (t, u)]
+  shrink (SharedNode (Shared t)) =
+    [t] ++ map (SharedNode . Shared) (shrink t)
+  shrink (SymNode (Sym t)) =
+    [t] ++ map (SymNode . Sym) (shrink t)
+
+{-# NOINLINE prop_tree_serialise #-}
+prop_tree_serialise :: Tree -> Property
+prop_tree_serialise t =
+  counterexample (show (BS.unpack serial)) $
+  counterexample (show t') $
+  t === t'
+  where
+    serial = encode t
+    t' = decode serial
+
+tests :: TestTree
+tests =
+  localOption (QuickCheckTests 10000) $
+  testGroup "Serialisation" [
+     testProperty "Tree serialisation round trip" prop_tree_serialise]
diff --git a/test/TermOrder.hs b/test/TermOrder.hs
new file mode 100644
--- /dev/null
+++ b/test/TermOrder.hs
@@ -0,0 +1,167 @@
+-- Tests for KBO and LPO.
+
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TypeFamilies #-}
+module TermOrder(tests) where
+
+import Common
+import Twee.Base
+import Twee.Constraints hiding (funs)
+import Twee.Utils
+import qualified Twee.KBO as KBO
+import qualified Twee.LPO as LPO
+import Data.Function
+import Data.List
+import Data.Maybe
+import Test.Tasty
+import Test.Tasty.QuickCheck hiding (Function, subterms)
+
+data TermOrder f =
+  TermOrder {
+    to_lessEq :: Term f -> Term f -> Bool,
+    to_lessIn :: Model f -> Term f -> Term f -> Maybe Strictness,
+    to_lessEqSkolem :: Term f -> Term f -> Bool }
+
+kbo :: (Function f, KBO.Sized f, KBO.ArgWeighted f) => TermOrder f
+kbo =
+   TermOrder {
+     to_lessEq = KBO.lessEq,
+     to_lessIn = KBO.lessIn,
+     to_lessEqSkolem = KBO.lessEqSkolem }
+
+lpo :: Function f => TermOrder f
+lpo =
+   TermOrder {
+     to_lessEq = LPO.lessEq,
+     to_lessIn = LPO.lessIn,
+     to_lessEqSkolem = LPO.lessEqSkolem }
+
+type OrderGen = forall prop. Testable prop => ((Term Func -> Term Func -> Bool) -> prop) -> Property
+
+prop_subterm_reduces :: OrderGen -> Term Func -> Property
+prop_subterm_reduces withLessEq t =
+  withLessEq $ \lessEq ->
+    conjoin [lessEq u t | u <- subterms t]
+
+prop_erase_reduces :: OrderGen -> Term Func -> [Var] -> Property
+prop_erase_reduces withLessEq t xs =
+  withLessEq $ \lessEq ->
+    erase xs t `lessEq` t
+
+prop_antisymmetric :: OrderGen -> Pair Func -> Property
+prop_antisymmetric withLessEq (Pair t u) =
+  t /= u ==>
+  withLessEq $ \lessEq ->
+    not (lessEq t u && lessEq u t)
+
+prop_reflexive :: OrderGen -> Term Func -> Property
+prop_reflexive withLessEq t =
+  withLessEq $ \lessEq ->
+    lessEq t t
+
+prop_total :: OrderGen -> Pair Func -> Property
+prop_total withLessEq (Pair t u) =
+  withLessEq $ \lessEq ->
+    lessEq (ground t) (ground u) || lessEq (ground u) (ground t)
+
+prop_skolem_correct :: TermOrder Func -> Pair Func -> Property
+prop_skolem_correct TermOrder{..} (Pair t u) =
+  skolemFree t && skolemFree u ==>
+  to_lessEqSkolem t u === to_lessEq (skolemise t) (skolemise u)
+  where
+    skolemFree t = all (not . isSkolem) (funs t)
+    isSkolem (Sym (Skolem _)) = True
+    isSkolem _ = False
+
+prop_lessIn_trivial :: TermOrder Func -> Pair Func -> Property
+prop_lessIn_trivial TermOrder{..} (Pair t u) =
+  to_lessIn (modelFromOrder []) t u === lessEq' t u
+  where
+    lessEq' t u
+      | to_lessEq t u = Just (if isJust (unify t u) then Nonstrict else Strict)
+      | otherwise = Nothing
+
+prop_lessIn_antisymmetric :: TermOrder Func -> Model Func -> Pair Func -> Bool
+prop_lessIn_antisymmetric TermOrder{..} model (Pair t u) =
+  not (to_lessIn model t u == Just Strict && isJust (to_lessIn model u t))
+
+prop_lessIn_nonstrict :: TermOrder Func -> Model Func -> Pair Func -> Property
+prop_lessIn_nonstrict TermOrder{..} model (Pair t u) =
+  to_lessIn model t u == Just Nonstrict ==>
+  isJust (unify t u)
+
+prop_lessIn_permutation :: TermOrder Func -> Term Func -> Property
+prop_lessIn_permutation TermOrder{..} t =
+  let vs = nub (vars t) in
+  forAll (shuffle vs) $ \ws ->
+    let Just sub = listToSubst [(v, build (var w)) | (v, w) <- zip vs ws]
+        u = subst sub t
+        model = modelFromOrder (map Variable vs)
+        weaken m = [m' | m' <- weakenModel m, and [varInModel m' v | v <- vs]]
+        allModels = fixpoint (usort . concatMap weaken) [model] in
+    conjoin [counterexample (prettyShow m) (isJust (to_lessIn m t u)) | m <- allModels]
+
+prop_lessIn_instance :: TermOrder Func -> Pair Func -> Property
+prop_lessIn_instance TermOrder{..} (Pair t u) =
+  not (to_lessEq t u) && not (to_lessEq u t) ==>
+  let vs = usort (vars t ++ vars u) in
+  forAll (ground <$> genSubst vs) $ \sub ->
+    case (to_lessEq (subst sub t) (subst sub u), to_lessEq (subst sub u) (subst sub t)) of
+      (False, False) ->
+        error "partial on ground terms"
+      (True, True) ->
+        counterexample "Equal terms" $
+        subst sub t === subst sub u
+      (True, False) ->
+        counterexample "t < u" $
+        property $ isNothing (to_lessIn (modelFromSubst sub) u t)
+      (False, True) ->
+        counterexample "t > u" $
+        property $ isNothing (to_lessIn (modelFromSubst sub) t u)
+  where
+    modelFromSubst =
+      modelFromOrder' . map (map (Variable . fst)) . groupBy ((==) `on` snd) . sortBy ord . substToList
+    ord (_, t) (_, u) =
+      case (to_lessEq t u, to_lessEq u t) of
+        (False, False) -> error "partial on ground terms"
+        (False, True)  -> GT
+        (True,  False) -> LT
+        (True,  True)  -> if t == u then EQ else error "not antisymmetric"
+
+prop_lpo_basic :: Pair Func -> Property
+prop_lpo_basic (Pair t u) =
+  minimal `notElem` funs t ==>
+  LPO.lessEq t u === LPO.lessEqBasic t u
+
+lessEqTests :: OrderGen -> [TestTree]
+lessEqTests withLessEq = [
+  testProperty "Order respects subterms" (prop_subterm_reduces withLessEq),
+  testProperty "Order respects erasure" (prop_erase_reduces withLessEq),
+  testProperty "Order is antisymmetric" (prop_antisymmetric withLessEq),
+  testProperty "Order is reflexive" (prop_reflexive withLessEq),
+  testProperty "Order is total on ground terms" (prop_total withLessEq)]
+
+orderTests :: TermOrder Func -> [TestTree]
+orderTests order@TermOrder{..} = [
+  testGroup "Basic order" (lessEqTests (\p -> property (p to_lessEq))),
+  testGroup "Skolemised order" $
+    lessEqTests (\p -> property (p to_lessEqSkolem)) ++
+    [testProperty "Order agrees with basic order" (prop_skolem_correct order)],
+  testGroup "Model-based order" $
+    lessEqTests (\p ->
+      property $ \model -> p (\t u -> isJust (to_lessIn model t u))) ++
+    [testProperty "Order is correct with empty model" (prop_lessIn_trivial order),
+     testProperty "Order is correct with permutations" (prop_lessIn_permutation order),
+     testProperty "Order only gives non-strict when necessary" (prop_lessIn_nonstrict order),
+     testProperty "Order is strongly antisymmetric" (prop_lessIn_antisymmetric order),
+     testProperty "Order is sound" (prop_lessIn_instance order)]]
+
+tests :: TestTree
+tests =
+  localOption (QuickCheckTests 100000) $
+  testGroup "Term ordering"
+    [testGroup "KBO" (orderTests kbo),
+     testGroup "LPO" $
+       [testProperty "Basic order agrees with simple implementation" prop_lpo_basic] ++
+       orderTests lpo]
diff --git a/test/Terms.hs b/test/Terms.hs
new file mode 100644
--- /dev/null
+++ b/test/Terms.hs
@@ -0,0 +1,45 @@
+-- Tests for basic term functionality.
+
+{-# LANGUAGE StandaloneDeriving, DeriveGeneric #-}
+module Terms(tests) where
+
+import Common
+import Twee.Base
+import Twee.Term.Core
+import Data.Int
+import GHC.Generics
+import Test.Tasty
+import Test.Tasty.QuickCheck
+
+deriving instance Eq Symbol
+deriving instance Generic Symbol
+
+instance Arbitrary Symbol where
+  arbitrary =
+    Symbol <$>
+      arbitrary <*>
+      fmap getLarge arbitrary <*>
+      (fmap (fromIntegral . getLarge) (arbitrary :: Gen (Large Int32)) `suchThat` (> 0) `suchThat` (< 2^31))
+  shrink s =
+    filter ok (genericShrink s)
+    where
+      ok s = Twee.Term.Core.size s > 0
+
+prop_paths :: Term Func -> Property
+prop_paths t =
+  forAllShrink (choose (0, len t-1)) shrink $ \n ->
+    counterexample (show (positionToPath t n)) $
+    pathToPosition t (positionToPath t n) === n
+  -- implies x = positionToPath t n ==> positionToPath t (pathToPosition t x) == x
+
+prop_symbol :: Int64 -> Property
+prop_symbol n =
+  fromSymbol (toSymbol n) === n
+  -- implies x = toSymbol n ==> toSymbol (fromSymbol x) == x
+
+tests :: TestTree
+tests =
+  localOption (QuickCheckTests 100000) $
+  testGroup "Terms" [
+    testProperty "Paths to positions round trip" prop_paths,
+    testProperty "Symbols to Int64 round trip" prop_symbol]
diff --git a/tests/BOO067-1.p b/tests/BOO067-1.p
deleted file mode 100644
--- a/tests/BOO067-1.p
+++ /dev/null
@@ -1,32 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : BOO067-1 : TPTP v6.3.0. Released v2.6.0.
-% Domain   : Boolean Algebra (Ternary)
-% Problem  : Ternary Boolean Algebra Single axiom is complete, part 1
-% Version  : [MP96] (equality) axioms.
-% English  :
-
-% Refs     : [McC98] McCune (1998), Email to G. Sutcliffe
-%          : [MP96]  McCune & Padmanabhan (1996), Automated Deduction in Eq
-% Source   : [TPTP]
-% Names    :
-
-% Status   : Unsatisfiable
-% Rating   : 0.42 v6.3.0, 0.35 v6.2.0, 0.29 v6.1.0, 0.31 v6.0.0, 0.48 v5.5.0, 0.47 v5.4.0, 0.33 v5.3.0, 0.25 v5.2.0, 0.29 v5.1.0, 0.33 v5.0.0, 0.29 v4.1.0, 0.18 v4.0.1, 0.36 v4.0.0, 0.38 v3.7.0, 0.11 v3.4.0, 0.12 v3.3.0, 0.21 v3.1.0, 0.33 v2.7.0, 0.27 v2.6.0
-% Syntax   : Number of clauses     :    2 (   0 non-Horn;   2 unit;   1 RR)
-%            Number of atoms       :    2 (   2 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    7 (   5 constant; 0-3 arity)
-%            Number of variables   :    7 (   0 singleton)
-%            Maximal term depth    :    5 (   3 average)
-% SPC      : CNF_UNS_RFO_PEQ_UEQ
-
-% Comments : A UEQ part of BOO035-1
-%--------------------------------------------------------------------------
-cnf(single_axiom,axiom,
-    ( multiply(multiply(A,inverse(A),B),inverse(multiply(multiply(C,D,E),F,multiply(C,D,G))),multiply(D,multiply(G,F,E),C)) = B )).
-
-cnf(prove_tba_axioms_1,negated_conjecture,
-    (  multiply(multiply(d,e,a),b,multiply(d,e,c)) != multiply(d,e,multiply(a,b,c)) )).
-
-%--------------------------------------------------------------------------
diff --git a/tests/GRP196-1.p b/tests/GRP196-1.p
deleted file mode 100644
--- a/tests/GRP196-1.p
+++ /dev/null
@@ -1,40 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : GRP196-1 : TPTP v7.4.0. Released v2.2.0.
-% Domain   : Group Theory (Semigroups)
-% Problem  : In semigroups, xyyy=yyyx -> (uy)^9 = u^9v^9.
-% Version  : [MP96] (equality) axioms.
-% English  :
-
-% Refs     : [McC98] McCune (1998), Email to G. Sutcliffe
-%          : [MP96]  McCune & Padmanabhan (1996), Automated Deduction in Eq
-%          : [McC95] McCune (1995), Four Challenge Problems in Equational L
-% Source   : [McC98]
-% Names    : CS-3 [MP96]
-%          : Problem B [McC95]
-
-% Status   : Unsatisfiable
-% Rating   : 0.88 v7.4.0, 0.91 v7.3.0, 0.89 v7.0.0, 0.95 v6.4.0, 1.00 v4.0.1, 0.93 v4.0.0, 0.92 v3.7.0, 0.89 v3.4.0, 1.00 v3.3.0, 0.93 v3.1.0, 1.00 v2.2.1
-% Syntax   : Number of clauses     :    3 (   0 non-Horn;   3 unit;   1 RR)
-%            Number of atoms       :    3 (   3 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    3 (   2 constant; 0-2 arity)
-%            Number of variables   :    5 (   0 singleton)
-%            Maximal term depth    :   18 (   8 average)
-% SPC      : CNF_UNS_RFO_PEQ_UEQ
-
-% Comments : The problem was originally posed for cancellative semigroups,
-%            Otter does this with a nonstandard representation [MP96].
-%--------------------------------------------------------------------------
-%----Include semigroups axioms
-include('Axioms/GRP008-0.ax').
-%--------------------------------------------------------------------------
-%----Hypothesis:
-cnf(condition,hypothesis,
-    ( '*'(X,'*'(Y,'*'(Y,Y))) = '*'(Y,'*'(Y,'*'(Y,X))) )).
-
-%----Denial of conclusion:
-cnf(prove_this,negated_conjecture,
-    (  '*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,'*'(b,'*'(a,b))))))))))))))))) != '*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(a,'*'(b,'*'(b,'*'(b,'*'(b,'*'(b,'*'(b,'*'(b,'*'(b,b))))))))))))))))) )).
-
-%--------------------------------------------------------------------------
diff --git a/tests/GRP666-4.p b/tests/GRP666-4.p
deleted file mode 100644
--- a/tests/GRP666-4.p
+++ /dev/null
@@ -1,63 +0,0 @@
-%------------------------------------------------------------------------------
-% File     : GRP666-4 : TPTP v7.2.0. Released v4.0.0.
-% Domain   : Group Theory (Quasigroups)
-% Problem  : Inverse property A-loops are Moufang
-% Version  : Especial.
-% English  :
-
-% Refs     : [KKP02] Kinyon et al. (2002), Every Diassociative A-loop is M
-%          : [PS08]  Phillips & Stanovsky (2008), Automated Theorem Proving
-%          : [Sta08] Stanovsky (2008), Email to G. Sutcliffe
-% Source   : [Sta08]
-% Names    : KKP02a [PS08]
-
-% Status   : Unsatisfiable
-% Rating   : 0.84 v7.1.0, 0.83 v7.0.0, 0.89 v6.3.0, 0.82 v6.2.0, 0.71 v6.1.0, 0.81 v5.5.0, 0.84 v5.4.0, 0.87 v5.3.0, 0.75 v5.2.0, 0.86 v5.1.0, 0.87 v5.0.0, 0.86 v4.1.0, 0.82 v4.0.1, 0.86 v4.0.0
-% Syntax   : Number of clauses     :   12 (   0 non-Horn;  12 unit;   1 RR)
-%            Number of atoms       :   12 (  12 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    8 (   4 constant; 0-2 arity)
-%            Number of variables   :   25 (   0 singleton)
-%            Maximal term depth    :    5 (   3 average)
-% SPC      : CNF_UNS_RFO_PEQ_UEQ
-
-% Comments :
-%------------------------------------------------------------------------------
-cnf(c01,axiom,
-    ( mult(A,ld(A,B)) = B )).
-
-cnf(c02,axiom,
-    ( ld(A,mult(A,B)) = B )).
-
-cnf(c03,axiom,
-    ( mult(rd(A,B),B) = A )).
-
-cnf(c04,axiom,
-    ( rd(mult(A,B),B) = A )).
-
-cnf(c05,axiom,
-    ( mult(A,unit) = A )).
-
-cnf(c06,axiom,
-    ( mult(unit,A) = A )).
-
-cnf(c07,axiom,
-    ( ld(mult(A,B),mult(A,mult(B,mult(C,D)))) = mult(ld(mult(A,B),mult(A,mult(B,C))),ld(mult(A,B),mult(A,mult(B,D)))) )).
-
-cnf(c08,axiom,
-    ( rd(mult(mult(mult(A,B),C),D),mult(C,D)) = mult(rd(mult(mult(A,C),D),mult(C,D)),rd(mult(mult(B,C),D),mult(C,D))) )).
-
-cnf(c09,axiom,
-    ( ld(A,mult(mult(B,C),A)) = mult(ld(A,mult(B,A)),ld(A,mult(C,A))) )).
-
-cnf(c10,axiom,
-    ( mult(i(A),mult(A,B)) = B )).
-
-cnf(c11,axiom,
-    ( mult(mult(A,B),i(B)) = A )).
-
-cnf(goals,negated_conjecture,
-    ( mult(mult(a,b),mult(c,a)) != mult(mult(a,mult(b,c)),a) )).
-
-%------------------------------------------------------------------------------
diff --git a/tests/KLE125+1.p b/tests/KLE125+1.p
deleted file mode 100644
--- a/tests/KLE125+1.p
+++ /dev/null
@@ -1,47 +0,0 @@
-%------------------------------------------------------------------------------
-% File     : KLE125+1 : TPTP v9.0.0. Released v4.0.0.
-% Domain   : Kleene Algebra (Modal with Divergence)
-% Problem  : Quasicommutation theorem
-% Version  : [Hoe08] axioms.
-% English  : If x quasicommutes over y, then x+y terminates if x and y
-%            individually do.
-
-% Refs     : [BD86]  Bachmair & Dershowitz (1986), Commutation, Transformat
-%          : [Str07] Struth (2007), Reasoning Automatically about Terminati
-%          : [Hoe08] Hoefner (2008), Email to G. Sutcliffe
-% Source   : [Hoe08]
-% Names    :
-
-% Status   : Theorem
-% Rating   : 1.00 v4.0.0
-% Syntax   : Number of formulae    :   29 (  26 unt;   0 def)
-%            Number of atoms       :   33 (  32 equ)
-%            Maximal formula atoms :    3 (   1 avg)
-%            Number of connectives :    4 (   0   ~;   0   |;   0   &)
-%                                         (   2 <=>;   2  =>;   0  <=;   0 <~>)
-%            Maximal formula depth :    5 (   3 avg)
-%            Maximal term depth    :    6 (   2 avg)
-%            Number of predicates  :    2 (   1 usr;   0 prp; 2-2 aty)
-%            Number of functors    :   16 (  16 usr;   2 con; 0-2 aty)
-%            Number of variables   :   49 (  49   !;   0   ?)
-% SPC      : FOF_THM_RFO_SEQ
-
-% Comments : An abstract version of a theorem in [BD86].
-%          : Equational encoding
-%------------------------------------------------------------------------------
-%---Include axioms for modal Kleene algebra with divergence
-include('Axioms/KLE001+0.ax').
-%---Include axioms for Boolean domain/codomain
-include('Axioms/KLE001+4.ax').
-%---Include axioms for diamond and boxes
-include('Axioms/KLE001+6.ax').
-%---Include axioms for divergence
-include('Axioms/KLE001+7.ax').
-%------------------------------------------------------------------------------
-fof(goals,conjecture,
-    ! [X0,X1] :
-      ( addition(multiplication(X0,X1),multiplication(X1,star(addition(X1,X0)))) = multiplication(X1,star(addition(X1,X0)))
-     => ( divergence(addition(X1,X0)) = zero
-      <= addition(divergence(X1),divergence(X0)) = zero ) ) ).
-
-%------------------------------------------------------------------------------
diff --git a/tests/LAT071-1.p b/tests/LAT071-1.p
deleted file mode 100644
--- a/tests/LAT071-1.p
+++ /dev/null
@@ -1,37 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : LAT071-1 : TPTP v7.2.0. Released v2.6.0.
-% Domain   : Lattice Theory (Orthomodularlattices)
-% Problem  : Given single axiom OML-21C, prove associativity
-% Version  : [MRV03] (equality) axioms.
-% English  : Given a single axiom candidate OML-21C for orthomodular lattices
-%            (OML) in terms of the Sheffer Stroke, prove a Sheffer stroke form
-%            of associativity.
-
-% Refs     : [MRV03] McCune et al. (2003), Sheffer Stroke Bases for Ortholatt
-% Source   : [MRV03]
-% Names    : OML-21C-associativity [MRV03]
-
-% Status   : Open
-% Rating   : 1.00 v2.6.0
-% Syntax   : Number of clauses     :    2 (   0 non-Horn;   2 unit;   1 RR)
-%            Number of atoms       :    2 (   2 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    4 (   3 constant; 0-2 arity)
-%            Number of variables   :    4 (   2 singleton)
-%            Maximal term depth    :    6 (   4 average)
-% SPC      : CNF_OPN_RFO_PEQ_UEQ
-
-% Comments :
-%--------------------------------------------------------------------------
-%----Single axiom OML-21C
-cnf(oml_21C,axiom,
-    ( f(f(B,A),f(f(f(f(B,A),A),f(C,A)),f(f(A,A),D))) = A )).
-
-%----Denial of Sheffer stroke associativity
-cnf(associativity,negated_conjecture,
-    (  f(a,f(f(b,c),f(b,c))) != f(c,f(f(b,a),f(b,a))) )).
-
-cnf(bonus, axiom, f(A,B)=f(B,A)).
-
-%--------------------------------------------------------------------------
diff --git a/tests/LAT072-1.p b/tests/LAT072-1.p
deleted file mode 100644
--- a/tests/LAT072-1.p
+++ /dev/null
@@ -1,37 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : LAT072-1 : TPTP v6.3.0. Released v2.6.0.
-% Domain   : Lattice Theory (Ortholattices)
-% Problem  : Given single axiom OML-23A, prove associativity
-% Version  : [MRV03] (equality) axioms.
-% English  : Given a single axiom candidate OML-23A for orthomodular lattices
-%            (OML) in terms of the Sheffer Stroke, prove a Sheffer stroke form
-%            of associativity.
-
-% Refs     : [MRV03] McCune et al. (2003), Sheffer Stroke Bases for Ortholatt
-% Source   : [MRV03]
-% Names    : OML-23A-associativity [MRV03]
-
-% Status   : Unsatisfiable
-% Rating   : 0.95 v6.3.0, 0.94 v6.2.0, 0.93 v6.1.0, 0.94 v6.0.0, 0.95 v5.4.0, 1.00 v2.6.0
-% Syntax   : Number of clauses     :    2 (   0 non-Horn;   2 unit;   1 RR)
-%            Number of atoms       :    2 (   2 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    4 (   3 constant; 0-2 arity)
-%            Number of variables   :    4 (   2 singleton)
-%            Maximal term depth    :    7 (   4 average)
-% SPC      : CNF_UNS_RFO_PEQ_UEQ
-
-% Comments :
-%--------------------------------------------------------------------------
-%----Single axiom OML-23A
-cnf(oml_23A,axiom,
-    ( f(f(f(f(B,A),f(A,C)),D),f(A,f(f(C,f(f(A,A),C)),C))) = A )).
-
-cnf(a, axiom, f(X,Y) = f(Y, X)).
-
-%----Denial of Sheffer stroke associativity
-cnf(associativity,negated_conjecture,
-    (  f(a,f(f(b,c),f(b,c))) != f(c,f(f(b,a),f(b,a))) )).
-
-%--------------------------------------------------------------------------
diff --git a/tests/LAT073-1.p b/tests/LAT073-1.p
deleted file mode 100644
--- a/tests/LAT073-1.p
+++ /dev/null
@@ -1,37 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : LAT073-1 : TPTP v7.2.0. Released v2.6.0.
-% Domain   : Lattice Theory (Ortholattices)
-% Problem  : Given single axiom MOL-23C, prove modularity
-% Version  : [MRV03] (equality) axioms.
-% English  : Given a single axiom candidate MOL-23C for modular ortholattices
-%            (MOL) in terms of the Sheffer Stroke, prove a Sheffer stroke form
-%            of modularity.
-
-% Refs     : [MRV03] McCune et al. (2003), Sheffer Stroke Bases for Ortholatt
-% Source   : [MRV03]
-% Names    : MOL-23C-modularity [MRV03]
-
-% Status   : Open
-% Rating   : 1.00 v2.6.0
-% Syntax   : Number of clauses     :    2 (   0 non-Horn;   2 unit;   1 RR)
-%            Number of atoms       :    2 (   2 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    4 (   3 constant; 0-2 arity)
-%            Number of variables   :    4 (   1 singleton)
-%            Maximal term depth    :    7 (   4 average)
-% SPC      : CNF_OPN_RFO_PEQ_UEQ
-
-% Comments :
-%--------------------------------------------------------------------------
-%----Single axiom MOL-23C
-cnf(mol_23C,axiom,
-    ( f(f(f(B,f(A,B)),B),f(A,f(C,f(f(A,B),f(f(C,C),D))))) = A )).
-
-%----Denial of Sheffer stroke modularity
-cnf(modularity,negated_conjecture,
-    (  f(a,f(b,f(a,f(c,c)))) != f(a,f(c,f(a,f(b,b)))) )).
-
-cnf(bonus, axiom, f(A,B)=f(B,A)).
-
-%--------------------------------------------------------------------------
diff --git a/tests/LAT078-1.p b/tests/LAT078-1.p
deleted file mode 100644
--- a/tests/LAT078-1.p
+++ /dev/null
@@ -1,38 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : LAT078-1 : TPTP v9.0.0. Released v2.6.0.
-% Domain   : Lattice Theory (Ortholattices)
-% Problem  : Given single axiom MOL-27B2, prove associativity
-% Version  : [MRV03] (equality) axioms.
-% English  : Given a single axiom candidate MOL-27B2 for modular ortholattices
-%            (MOL) in terms of the Sheffer Stroke, prove a Sheffer stroke form
-%            of associativity.
-
-% Refs     : [MRV03] McCune et al. (2003), Sheffer Stroke Bases for Ortholatt
-% Source   : [MRV03]
-% Names    : MOL-27B2-associativity [MRV03]
-
-% Status   : Unsatisfiable
-% Rating   : 0.91 v8.2.0, 0.96 v8.1.0, 0.95 v7.5.0, 0.96 v7.4.0, 1.00 v7.3.0, 0.95 v7.1.0, 0.94 v7.0.0, 0.95 v6.4.0, 1.00 v2.6.0
-% Syntax   : Number of clauses     :    2 (   2 unt;   0 nHn;   1 RR)
-%            Number of literals    :    2 (   2 equ;   1 neg)
-%            Maximal clause size   :    1 (   1 avg)
-%            Maximal term depth    :    9 (   2 avg)
-%            Number of predicates  :    1 (   0 usr;   0 prp; 2-2 aty)
-%            Number of functors    :    4 (   4 usr;   3 con; 0-2 aty)
-%            Number of variables   :    4 (   1 sgn)
-% SPC      : CNF_UNS_RFO_PEQ_UEQ
-
-% Comments :
-%--------------------------------------------------------------------------
-%----Single axiom MOL-27B2
-cnf(mol_27B2,axiom,
-    f(f(f(f(B,A),f(A,C)),D),f(A,f(f(f(B,f(B,f(f(C,C),A))),A),C))) = A ).
-
-%----Denial of Sheffer stroke associativity
-cnf(associativity,negated_conjecture,
-    f(a,f(f(b,c),f(b,c))) != f(c,f(f(b,a),f(b,a))) ).
-
-%--------------------------------------------------------------------------
-
-cnf(not, axiom,
-    not(X) = f(X,X)).
diff --git a/tests/PUZ037-3-2.p b/tests/PUZ037-3-2.p
deleted file mode 100644
--- a/tests/PUZ037-3-2.p
+++ /dev/null
@@ -1,106 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : PUZ037-3 : TPTP v7.2.0. Released v2.3.0.
-% Domain   : Puzzles
-% Problem  : Rubik's Cube
-% Version  : [HM98] axioms : Especial.
-%            Theorem formulation : Rotation in all three planes.
-% English  : Rubik's Cube is a 3x3x3 cube consisting of 27 subcubes with
-%            colored faces. The three layers perpendicular to any axis may
-%            be rotated independently. The object is to take a scrambled
-%            cube and unscramble it so that each side consists entirely
-%            of one color(Blue, White, Green, Yellow, Orange, Red).
-
-% Refs     : [HM98]  Huang & Myers (1998), Subgoal Strategies for Solving B
-% Source   : [HM98]
-% Names    : Rubik's Cube [HM98]
-
-% Status   : Unsatisfiable
-% Rating   : 0.20 v7.2.0, 0.22 v7.1.0, 0.14 v6.4.0, 0.17 v6.3.0, 0.25 v6.2.0, 0.12 v6.1.0, 0.00 v5.5.0, 0.20 v5.4.0, 0.33 v5.0.0, 0.50 v4.1.0, 0.60 v3.7.0, 0.50 v3.5.0, 0.33 v3.1.0, 0.44 v2.7.0, 0.50 v2.6.0, 0.44 v2.5.0, 0.75 v2.4.0, 0.67 v2.3.0
-% Syntax   : Number of clauses     :   20 (   0 non-Horn;   2 unit;  20 RR)
-%            Number of atoms       :   38 (   0 equality)
-%            Maximal clause size   :    2 (   2 average)
-%            Number of predicates  :    1 (   0 propositional; 54-54 arity)
-%            Number of functors    :    6 (   6 constant; 0-0 arity)
-%            Number of variables   :  972 (   0 singleton)
-%            Maximal term depth    :    1 (   1 average)
-% SPC      : CNF_UNS_EPR
-
-% Comments : mzy, mzy, bzy, byx, lzx rotations to solve.
-%--------------------------------------------------------------------------
-cnf(a, axiom,
-    state(b,b,b,b,b,b,b,b,b,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,w,w,w,w,w,w,w,w,w) !=
-    state(b,r,r,w,w,w,y,b,b,g,y,r,b,g,g,o,g,y,w,w,r,g,o,r,b,g,g,o,r,b,y,y,r,g,o,g,o,o,o,y,r,b,y,y,r,w,w,w,b,b,y,w,o,o)).
-
-cnf(txy,axiom,
-    (  state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
-    = state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
-
-cnf(mxy,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
-    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
-
-cnf(bxy,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3)
-    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5) )).
-
-cnf(fzy,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6)
-    = state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6) )).
-
-cnf(mzy,axiom,
-    (  state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6)
-    = state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6) )).
-
-cnf(bzy,axiom,
-    (  state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4)
-    = state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7) )).
-
-cnf(lzx,axiom,
-    (  state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7)
-    = state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7) )).
-
-cnf(mzx,axiom,
-    (  state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6)
-    = state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6) )).
-
-cnf(rzx,axiom,
-    (  state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6)
-    = state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9) )).
-
-cnf(tyx,axiom,
-    (  state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
-    = state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
-
-cnf(myx,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
-    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
-
-cnf(byx,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5)
-    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3) )).
-
-cnf(fyz,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6)
-    = state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6) )).
-
-cnf(myz,axiom,
-    (  state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6)
-    = state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6) )).
-
-cnf(byz,axiom,
-    (  state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7)
-    = state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4) )).
-
-cnf(lxz,axiom,
-    (  state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7)
-    = state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7) )).
-
-cnf(mxz,axiom,
-    (  state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6)
-    = state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6) )).
-
-cnf(rxz,axiom,
-    (  state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9)
-    = state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6) )).
-
-%--------------------------------------------------------------------------
diff --git a/tests/PUZ037-3.p b/tests/PUZ037-3.p
deleted file mode 100644
--- a/tests/PUZ037-3.p
+++ /dev/null
@@ -1,110 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : PUZ037-3 : TPTP v7.2.0. Released v2.3.0.
-% Domain   : Puzzles
-% Problem  : Rubik's Cube
-% Version  : [HM98] axioms : Especial.
-%            Theorem formulation : Rotation in all three planes.
-% English  : Rubik's Cube is a 3x3x3 cube consisting of 27 subcubes with
-%            colored faces. The three layers perpendicular to any axis may
-%            be rotated independently. The object is to take a scrambled
-%            cube and unscramble it so that each side consists entirely
-%            of one color(Blue, White, Green, Yellow, Orange, Red).
-
-% Refs     : [HM98]  Huang & Myers (1998), Subgoal Strategies for Solving B
-% Source   : [HM98]
-% Names    : Rubik's Cube [HM98]
-
-% Status   : Unsatisfiable
-% Rating   : 0.20 v7.2.0, 0.22 v7.1.0, 0.14 v6.4.0, 0.17 v6.3.0, 0.25 v6.2.0, 0.12 v6.1.0, 0.00 v5.5.0, 0.20 v5.4.0, 0.33 v5.0.0, 0.50 v4.1.0, 0.60 v3.7.0, 0.50 v3.5.0, 0.33 v3.1.0, 0.44 v2.7.0, 0.50 v2.6.0, 0.44 v2.5.0, 0.75 v2.4.0, 0.67 v2.3.0
-% Syntax   : Number of clauses     :   20 (   0 non-Horn;   2 unit;  20 RR)
-%            Number of atoms       :   38 (   0 equality)
-%            Maximal clause size   :    2 (   2 average)
-%            Number of predicates  :    1 (   0 propositional; 54-54 arity)
-%            Number of functors    :    6 (   6 constant; 0-0 arity)
-%            Number of variables   :  972 (   0 singleton)
-%            Maximal term depth    :    1 (   1 average)
-% SPC      : CNF_UNS_EPR
-
-% Comments : mzy, mzy, bzy, byx, lzx rotations to solve.
-%--------------------------------------------------------------------------
-cnf(make_like_this,negated_conjecture, lhs != rhs).
-
-cnf(a, axiom, lhs =
-    state(b,b,b,b,b,b,b,b,b,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,w,w,w,w,w,w,w,w,w)).
-
-cnf(b, axiom, rhs =
-    state(b,r,r,w,w,w,y,b,b,g,y,r,b,g,g,o,g,y,w,w,r,g,o,r,b,g,g,o,r,b,y,y,r,g,o,g,o,o,o,y,r,b,y,y,r,w,w,w,b,b,y,w,o,o)).
-
-cnf(txy,axiom,
-    (  state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
-    = state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
-
-cnf(mxy,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
-    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
-
-cnf(bxy,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3)
-    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5) )).
-
-cnf(fzy,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6)
-    = state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6) )).
-
-cnf(mzy,axiom,
-    (  state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6)
-    = state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6) )).
-
-cnf(bzy,axiom,
-    (  state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4)
-    = state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7) )).
-
-cnf(lzx,axiom,
-    (  state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7)
-    = state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7) )).
-
-cnf(mzx,axiom,
-    (  state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6)
-    = state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6) )).
-
-cnf(rzx,axiom,
-    (  state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6)
-    = state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9) )).
-
-cnf(tyx,axiom,
-    (  state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
-    = state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
-
-cnf(myx,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
-    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
-
-cnf(byx,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5)
-    = state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3) )).
-
-cnf(fyz,axiom,
-    (  state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6)
-    = state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6) )).
-
-cnf(myz,axiom,
-    (  state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6)
-    = state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6) )).
-
-cnf(byz,axiom,
-    (  state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7)
-    = state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4) )).
-
-cnf(lxz,axiom,
-    (  state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7)
-    = state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7) )).
-
-cnf(mxz,axiom,
-    (  state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6)
-    = state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6) )).
-
-cnf(rxz,axiom,
-    (  state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9)
-    = state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6) )).
-
-%--------------------------------------------------------------------------
diff --git a/tests/PUZ052-1.p b/tests/PUZ052-1.p
deleted file mode 100644
--- a/tests/PUZ052-1.p
+++ /dev/null
@@ -1,129 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : PUZ052-1 : TPTP v7.2.0. Released v2.7.0.
-% Domain   : Puzzles
-% Problem  : Rubik's Cube unreachability
-% Version  : [HM98] axioms : Especial.
-%            Theorem formulation : Rotations in one plane only.
-% English  : Rubik's Cube is a 3x3x3 cube consisting of 27 subcubes with
-%            colored faces. The three layers perpendicular to any axis may
-%            be rotated independently. The object is to take a scrambled
-%            cube and unscramble it so that each side consists entirely
-%            of one color(Blue, White, Green, Yellow, Orange, Red).
-%            The objective here is unreachable: there are 10 b's and only
-%            8 r's.
-
-% Refs     : [HM98]  Huang & Myers (1998), Subgoal Strategies for Solving B
-%          : [Cla03] Claessen (2003), Email to G. Sutcliffe
-% Source   : [Cla03]
-% Names    :
-
-% Status   : Satisfiable
-% Rating   : 1.00 v2.7.0
-% Syntax   : Number of clauses     :   20 (   0 non-Horn;   2 unit;  20 RR)
-%            Number of atoms       :   38 (   0 equality)
-%            Maximal clause size   :    2 (   2 average)
-%            Number of predicates  :    1 (   0 propositional; 54-54 arity)
-%            Number of functors    :    6 (   6 constant; 0-0 arity)
-%            Number of variables   :  972 (   0 singleton)
-%            Maximal term depth    :    1 (   1 average)
-% SPC      : CNF_SAT_EPR
-
-% Comments : Replaced one b by an r in make_like_this from PUZ037-1.p
-%            Model never found; a domain of size 2 should be enough though.
-%--------------------------------------------------------------------------
-cnf(make_like_this,negated_conjecture,
-    ( state(b,b,b,b,b,b,b,b,b,b,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,r,r,r,g,g,g,o,o,o,y,y,y,w,w,w,w,w,w,w,w,w) !=
-     state(b,b,b,b,b,b,b,b,b,r,r,r,g,g,g,o,o,o,y,y,y,g,g,g,o,o,o,y,y,y,r,r,r,r,r,r,g,g,g,o,o,o,y,y,y,w,w,w,w,w,w,w,w,w) )).
-
-cnf(txy,axiom,
-    ( 
-state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) 
-= state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
-
-cnf(mxy,axiom,
-    ( 
-state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) 
-=
-    state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
-
-cnf(bxy,axiom,
-    ( state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3)
-    = 
-state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5) )).
-
-cnf(fzy,axiom,
-    ( state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6)
-    = 
-state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6) )).
-
-cnf(mzy,axiom,
-    ( state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6)
-    = 
-state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6) )).
-
-cnf(bzy,axiom,
-    ( state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4)
-    = 
-state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7) )).
-
-cnf(lzx,axiom,
-    ( state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7)
-    = 
-state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7) )).
-
-cnf(mzx,axiom,
-    ( state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6)
-    = 
-state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6) )).
-
-cnf(rzx,axiom,
-    ( state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6)
-    = 
-state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9) )).
-
-cnf(tyx,axiom,
-    ( state(W1,W8,W7,W2,A1,W6,W3,W4,W5,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7)
-    = 
-state(W7,W6,W5,W8,A1,W4,W1,W2,W3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7) )).
-
-cnf(myx,axiom,
-    ( state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6)
-    = 
-state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6) )).
-
-cnf(byx,axiom,
-    ( state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,X1,X2,X3,X4,X5,X6,X7,X8,X9,Y1,Y2,Y3,W1,W2,W3,W8,D7,W4,W7,W6,W5)
-    = 
-state(A1,A2,A3,A4,A5,A6,A7,A8,A9,B1,B2,B3,B4,B5,B6,B7,B8,B9,C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,Y1,Y2,Y3,X1,X2,X3,X4,X5,X6,X7,X8,X9,W7,W8,W1,W6,D7,W2,W5,W4,W3) )).
-
-cnf(fyz,axiom,
-    ( state(A1,A2,A3,A4,A5,A6,X1,X2,X3,A7,A8,Y1,Y2,Y3,Y4,Y5,A9,B1,B2,B3,B4,B5,B6,U1,U2,U3,U4,U5,B7,B8,B9,C1,C2,C3,C4,V1,V2,V3,V4,V5,C5,C6,C7,C8,C9,W1,W2,W3,D1,D2,D3,D4,D5,D6)
-    = 
-state(A1,A2,A3,A4,A5,A6,V1,U1,Y1,A7,A8,W1,V2,U2,Y2,X1,A9,B1,B2,B3,B4,B5,B6,W2,V3,U3,Y3,X2,B7,B8,B9,C1,C2,C3,C4,W3,V4,U4,Y4,X3,C5,C6,C7,C8,C9,V5,U5,Y5,D1,D2,D3,D4,D5,D6) )).
-
-cnf(myz,axiom,
-    ( state(A1,A2,A3,X1,X2,X3,A4,A5,A6,A7,Y3,A8,A9,B1,B2,B3,X4,B4,B5,B6,B7,B8,Y2,B9,C1,C2,C3,C4,X5,C5,C6,C7,C8,C9,Y1,D1,D2,D3,D4,D5,X6,D6,D7,D8,D9,E1,E2,E3,X9,X8,X7,E4,E5,E6)
-    = 
-state(A1,A2,A3,Y1,Y2,Y3,A4,A5,A6,A7,X9,A8,A9,B1,B2,B3,X1,B4,B5,B6,B7,B8,X8,B9,C1,C2,C3,C4,X2,C5,C6,C7,C8,C9,X7,D1,D2,D3,D4,D5,X3,D6,D7,D8,D9,E1,E2,E3,X6,X5,X4,E4,E5,E6) )).
-
-cnf(byz,axiom,
-    ( state(X1,X2,X3,A1,A2,A3,A4,A5,A6,Y3,A7,A8,A9,B1,B2,B3,B4,X4,W3,W2,W1,Y2,B5,B6,B7,B8,B9,C1,C2,X5,W4,C3,W8,Y1,C4,C5,C6,C7,C8,C9,D1,X6,W5,W6,W7,D2,D3,D4,D5,D6,D7,X9,X8,X7)
-    = 
-state(Y1,Y2,Y3,A1,A2,A3,A4,A5,A6,X9,A7,A8,A9,B1,B2,B3,B4,X1,W1,W8,W7,X8,B5,B6,B7,B8,B9,C1,C2,X2,W2,C3,W6,X7,C4,C5,C6,C7,C8,C9,D1,X3,W3,W4,W5,D2,D3,D4,D5,D6,D7,X6,X5,X4) )).
-
-cnf(lxz,axiom,
-    ( state(X1,A1,A2,X2,A3,A4,X3,A5,A6,W1,W2,W3,X4,A7,A8,A9,B1,B2,B3,B4,Y3,W8,B5,W4,X5,B6,B7,B8,B9,C1,C2,C3,Y2,W7,W6,W5,X6,C4,C5,C6,C7,C8,C9,D1,Y1,X7,D2,D3,X8,D4,D5,X9,D6,D7)
-    = 
-state(Y1,A1,A2,Y2,A3,A4,Y3,A5,A6,W7,W8,W1,X1,A7,A8,A9,B1,B2,B3,B4,X9,W6,B5,W2,X2,B6,B7,B8,B9,C1,C2,C3,X8,W5,W4,W3,X3,C4,C5,C6,C7,C8,C9,D1,X7,X4,D2,D3,X5,D4,D5,X6,D6,D7) )).
-
-cnf(mxz,axiom,
-    ( state(A1,X1,A2,A3,X2,A4,A5,X3,A6,A7,A8,A9,B1,X4,B2,B3,B4,B5,B6,Y3,B7,B8,B9,C1,C2,X5,C3,C4,C5,C6,C7,Y2,C8,C9,D1,D2,D3,X6,D4,D5,D6,D7,D8,Y1,D9,E1,X7,E2,E3,X8,E4,E5,X9,E6)
-    = 
-state(A1,Y1,A2,A3,Y2,A4,A5,Y3,A6,A7,A8,A9,B1,X1,B2,B3,B4,B5,B6,X9,B7,B8,B9,C1,C2,X2,C3,C4,C5,C6,C7,X8,C8,C9,D1,D2,D3,X3,D4,D5,D6,D7,D8,X7,D9,E1,X4,E2,E3,X5,E4,E5,X6,E6) )).
-
-cnf(rxz,axiom,
-    ( state(A1,A2,X1,A3,A4,X2,A5,A6,X3,A7,A8,A9,B1,B2,X4,W3,W2,W1,Y3,B3,B4,B5,B6,B7,B8,B9,X5,W4,C1,W8,Y2,C2,C3,C4,C5,C6,C7,C8,X6,W5,W6,W7,Y1,C9,D1,D2,D3,X7,D4,D5,X8,D6,D7,X9)
-    = 
-state(A1,A2,Y1,A3,A4,Y2,A5,A6,Y3,A7,A8,A9,B1,B2,X1,W1,W8,W7,X9,B3,B4,B5,B6,B7,B8,B9,X2,W2,C1,W6,X8,C2,C3,C4,C5,C6,C7,C8,X3,W3,W4,W5,X7,C9,D1,D2,D3,X4,D4,D5,X5,D6,D7,X6) )).
-
-%--------------------------------------------------------------------------
diff --git a/tests/REL038-1.p b/tests/REL038-1.p
deleted file mode 100644
--- a/tests/REL038-1.p
+++ /dev/null
@@ -1,14 +0,0 @@
-cnf(maddux1_join_commutativity_1, axiom, join(A, B)=join(B, A)).
-cnf(maddux2_join_associativity_2, axiom, join(A, join(B, C))=join(join(A, B), C)).
-cnf(maddux3_a_kind_of_de_Morgan_3, axiom, A=join(complement(join(complement(A), complement(B))), complement(join(complement(A), B)))).
-cnf(maddux4_definiton_of_meet_4, axiom, meet(A, B)=complement(join(complement(A), complement(B)))).
-cnf(composition_associativity_5, axiom, composition(A, composition(B, C))=composition(composition(A, B), C)).
-cnf(composition_identity_6, axiom, composition(A, one)=A).
-cnf(composition_distributivity_7, axiom, composition(join(A, B), C)=join(composition(A, C), composition(B, C))).
-cnf(converse_idempotence_8, axiom, converse(converse(A))=A).
-cnf(converse_additivity_9, axiom, converse(join(A, B))=join(converse(A), converse(B))).
-cnf(converse_multiplicativity_10, axiom, converse(composition(A, B))=composition(converse(B), converse(A))).
-cnf(converse_cancellativity_11, axiom, join(composition(converse(A), complement(composition(A, B))), complement(B))=complement(B)).
-cnf(def_top_12, axiom, top=join(A, complement(A))).
-cnf(def_zero_13, axiom, zero=meet(A, complement(A))).
-cnf(goals_14, negated_conjecture, join(meet(composition(sk1, sk2), sk3), meet(composition(sk1, meet(sk2, composition(converse(sk1), sk3))), sk3))!=meet(composition(sk1, meet(sk2, composition(converse(sk1), sk3))), sk3)).
diff --git a/tests/RNG025-buggy.p b/tests/RNG025-buggy.p
deleted file mode 100644
--- a/tests/RNG025-buggy.p
+++ /dev/null
@@ -1,9 +0,0 @@
-% SPASS solves this instantly, Twee takes ages!
-cnf(axiom, axiom, multiply(U,add(V,W))=add(multiply(U,V),multiply(U,W))).
-cnf(axiom, axiom, add(U,additive_inverse(add(additive_inverse(V),U)))=V).
-cnf(axiom, axiom, add(U,additive_inverse(add(V,add(W,U))))=additive_inverse(add(V,W))).
-cnf(axiom, axiom, add(additive_inverse(U),V)=additive_inverse(add(U,additive_inverse(V)))).
-cnf(axiom, axiom, multiply(multiply(U,V),W)=add(associator(U,V,W),multiply(U,multiply(V,W)))).
-cnf(axiom, axiom, additive_inverse(add(multiply(U,multiply(V,W)),add(multiply(U,multiply(X,W)),additive_inverse(add(multiply(multiply(U,V),W),multiply(multiply(U,X),W))))))=associator(U,add(V,X),W)).
-
-cnf(conjecture, conjecture, add(associator(U,V,W),associator(U,X,W))=associator(U,add(V,X),W)).
diff --git a/tests/RNG035-7.p b/tests/RNG035-7.p
deleted file mode 100644
--- a/tests/RNG035-7.p
+++ /dev/null
@@ -1,12 +0,0 @@
-cnf(left_additive_identity, axiom, add(additive_identity, X)=X).
-cnf(right_additive_identity, axiom, add(X, additive_identity)=X).
-cnf(left_additive_inverse, axiom, add(additive_inverse(X), X)=additive_identity).
-cnf(right_additive_inverse, axiom, add(X, additive_inverse(X))=additive_identity).
-cnf(associativity_for_addition, axiom, add(X, add(Y, Z))=add(add(X, Y), Z)).
-cnf(commutativity_for_addition, axiom, add(X, Y)=add(Y, X)).
-cnf(associativity_for_multiplication, axiom, multiply(X, multiply(Y, Z))=multiply(multiply(X, Y), Z)).
-cnf(distribute1, axiom, multiply(X, add(Y, Z))=add(multiply(X, Y), multiply(X, Z))).
-cnf(distribute2, axiom, multiply(add(X, Y), Z)=add(multiply(X, Z), multiply(Y, Z))).
-cnf(x_fourthed_is_x, hypothesis, multiply(X, multiply(X, multiply(X, X)))=X).
-cnf(a_times_b_is_c, negated_conjecture, multiply(a, b)=c).
-cnf(prove_commutativity, negated_conjecture, multiply(b, a)!=c).
diff --git a/tests/ROB001-1-a.p b/tests/ROB001-1-a.p
deleted file mode 100644
--- a/tests/ROB001-1-a.p
+++ /dev/null
@@ -1,42 +0,0 @@
-%------------------------------------------------------------------------------
-% File     : ROB001-1 : TPTP v9.0.0. Released v1.0.0.
-% Domain   : Robbins Algebra
-% Problem  : Is every Robbins algebra Boolean?
-% Version  : [Win90] (equality) axioms.
-% English  :
-
-% Refs     : [HMT71] Henkin et al. (1971), Cylindrical Algebras
-%          : [Win90] Winker (1990), Robbins Algebra: Conditions that make a
-% Source   : [TPTP]
-% Names    :
-
-% Status   : Unsatisfiable
-% Rating   : 1.00 v2.0.0
-% Syntax   : Number of clauses     :    4 (   4 unt;   0 nHn;   1 RR)
-%            Number of literals    :    4 (   4 equ;   1 neg)
-%            Maximal clause size   :    1 (   1 avg)
-%            Maximal term depth    :    6 (   2 avg)
-%            Number of predicates  :    1 (   0 usr;   0 prp; 2-2 aty)
-%            Number of functors    :    4 (   4 usr;   2 con; 0-2 aty)
-%            Number of variables   :    7 (   0 sgn)
-% SPC      : CNF_UNS_RFO_PEQ_UEQ
-
-% Comments : Commutativity, associativity, and Huntington's axiom axiomatize 
-%            Boolean algebra.
-%------------------------------------------------------------------------------
-%----Include axioms for Robbins algebra
-include('Axioms/ROB001-0.ax').
-%------------------------------------------------------------------------------
-cnf(prove_huntingtons_axiom,negated_conjecture,
-    add(negate(add(a,negate(b))),negate(add(negate(a),negate(b)))) != b ).
-
-%------------------------------------------------------------------------------
-
-cnf(sos04,axiom,(
-    g(A) = inv(add(A,inv(A))) )).
-
-%----Definition of h
-%cnf(sos05,axiom,(
-%    h(A) = add(A,add(A,add(A,inv(add(A,inv(A)))))))).
-cnf(sos05,axiom,(
-    $hint(add(A,add(A,add(A,g(A))))))).
diff --git a/tests/ROB007-1-a.p b/tests/ROB007-1-a.p
deleted file mode 100644
--- a/tests/ROB007-1-a.p
+++ /dev/null
@@ -1,12 +0,0 @@
-cnf(commutativity_of_add, axiom, add(X, Y)=add(Y, X)).
-cnf(associativity_of_add, axiom, add(add(X, Y), Z)=add(X, add(Y, Z))).
-cnf(robbins_axiom, axiom, inv(add(inv(add(X, Y)), inv(add(X, inv(Y)))))=X).
-cnf(condition, hypothesis, inv(add(a, b))=inv(b)).
-cnf(prove_huntingtons_axiom, negated_conjecture, add(inv(add(a, inv(b))), inv(add(inv(a), inv(b))))!=b).
-
-cnf(sos04,axiom,(
-    g(A) = inv(add(A,inv(A))) )).
-
-%----Definition of h
-cnf(sos05,axiom,(
-    h(A) = add(A,add(A,add(A,inv(add(A,inv(A)))))))).
diff --git a/tests/ROB007-1-b.p b/tests/ROB007-1-b.p
deleted file mode 100644
--- a/tests/ROB007-1-b.p
+++ /dev/null
@@ -1,12 +0,0 @@
-cnf(commutativity_of_add, axiom, add(X, Y)=add(Y, X)).
-cnf(associativity_of_add, axiom, add(add(X, Y), Z)=add(X, add(Y, Z))).
-cnf(robbins_axiom, axiom, inv(add(inv(add(X, Y)), inv(add(X, inv(Y)))))=X).
-cnf(condition, hypothesis, inv(add(a, b))=inv(b)).
-cnf(prove_huntingtons_axiom, negated_conjecture, add(inv(add(a, inv(b))), inv(add(inv(a), inv(b))))!=b).
-
-cnf(sos04,axiom,(
-    $hint(inv(add(A,inv(A)))) )).
-
-%----Definition of h
-cnf(sos05,axiom,(
-    $hint(add(A,add(A,add(A,inv(add(A,inv(A))))))))).
diff --git a/tests/ROB007-1.p b/tests/ROB007-1.p
deleted file mode 100644
--- a/tests/ROB007-1.p
+++ /dev/null
@@ -1,5 +0,0 @@
-cnf(commutativity_of_add, axiom, add(X, Y)=add(Y, X)).
-cnf(associativity_of_add, axiom, add(add(X, Y), Z)=add(X, add(Y, Z))).
-cnf(robbins_axiom, axiom, negate(add(negate(add(X, Y)), negate(add(X, negate(Y)))))=X).
-cnf(condition, hypothesis, negate(add(a, b))=negate(b)).
-cnf(prove_huntingtons_axiom, negated_conjecture, add(negate(add(a, negate(b))), negate(add(negate(a), negate(b))))!=b).
diff --git a/tests/ROB010-1.p b/tests/ROB010-1.p
deleted file mode 100644
--- a/tests/ROB010-1.p
+++ /dev/null
@@ -1,11 +0,0 @@
-cnf(condition,hypothesis,
-    ( negate(add(a,negate(b))) = c )).
-
-cnf(prove_result,negated_conjecture,
-    (  negate(add(c,negate(add(b,a)))) != a )).
-
-cnf(commutativity_of_add,axiom,
-    ( add(X,Y) = add(Y,X) )).
-
-cnf(robbins_axiom,axiom,
-    ( negate(add(negate(add(X,Y)),negate(add(X,negate(Y))))) = X )).
diff --git a/tests/ROB027-1-inv.p b/tests/ROB027-1-inv.p
deleted file mode 100644
--- a/tests/ROB027-1-inv.p
+++ /dev/null
@@ -1,58 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : ROB027-1 : TPTP v6.3.0. Released v1.2.0.
-% Domain   : Robbins Algebra
-% Problem  : -(-c) = c => Boolean
-% Version  : [Win90] (equality) axioms.
-%            Theorem formulation : Denies Huntington's axiom.
-% English  : If there are elements c and d such that c+d=d, then the
-%            algebra is Boolean.
-
-% Refs     : [HMT71] Henkin et al. (1971), Cylindrical Algebras
-%          : [Win90] Winker (1990), Robbins Algebra: Conditions that make a
-%          : [Wos94] Wos (1994), Two Challenge Problems
-% Source   : [Wos94]
-% Names    : - [Wos94]
-
-% Status   : Open
-% Rating   : 1.00 v2.0.0
-% Syntax   : Number of clauses     :    5 (   0 non-Horn;   5 unit;   2 RR)
-%            Number of atoms       :    5 (   5 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    5 (   3 constant; 0-2 arity)
-%            Number of variables   :    7 (   0 singleton)
-%            Maximal term depth    :    6 (   3 average)
-% SPC      : CNF_UNK_UEQ
-
-% Comments : Commutativity, associativity, and Huntington's axiom
-%            axiomatize Boolean algebra.
-%--------------------------------------------------------------------------
-%----Include axioms for Robbins algebra
-%--------------------------------------------------------------------------
-cnf(commutativity_of_add,axiom,
-    ( add(X,Y) = add(Y,X) )).
-
-cnf(associativity_of_add,axiom,
-    ( add(add(X,Y),Z) = add(X,add(Y,Z)) )).
-
-cnf(robbins_axiom,axiom,
-    ( inv(add(inv(add(X,Y)),inv(add(X,inv(Y))))) = X )).
-
-%--------------------------------------------------------------------------
-%--------------------------------------------------------------------------
-cnf(double_negation,hypothesis,
-    ( inv(inv(c)) = c )).
-
-cnf(prove_huntingtons_axiom,negated_conjecture,
-    add(inv(add(a,inv(b))),inv(add(inv(a),inv(b)))) != b).
-
-%--------------------------------------------------------------------------
-%----Definition of g
-cnf(sos04,axiom,(
-    g(A) = inv(add(A,inv(A))) )).
-
-%----Definition of h
-cnf(sos05,axiom,(
-    h(A) = add(A,add(A,add(A,inv(add(A,inv(A)))))))).
-
-cnf(sos06, axiom, i(X,Y) = inv(add(X, inv(add(X, Y))))).
diff --git a/tests/ROB027-1-pretty.p b/tests/ROB027-1-pretty.p
deleted file mode 100644
--- a/tests/ROB027-1-pretty.p
+++ /dev/null
@@ -1,56 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : ROB027-1 : TPTP v6.3.0. Released v1.2.0.
-% Domain   : Robbins Algebra
-% Problem  : -(-c) = c => Boolean
-% Version  : [Win90] (equality) axioms.
-%            Theorem formulation : Denies Huntington's axiom.
-% English  : If there are elements c and d such that c+d=d, then the
-%            algebra is Boolean.
-
-% Refs     : [HMT71] Henkin et al. (1971), Cylindrical Algebras
-%          : [Win90] Winker (1990), Robbins Algebra: Conditions that make a
-%          : [Wos94] Wos (1994), Two Challenge Problems
-% Source   : [Wos94]
-% Names    : - [Wos94]
-
-% Status   : Open
-% Rating   : 1.00 v2.0.0
-% Syntax   : Number of clauses     :    5 (   0 non-Horn;   5 unit;   2 RR)
-%            Number of atoms       :    5 (   5 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    5 (   3 constant; 0-2 arity)
-%            Number of variables   :    7 (   0 singleton)
-%            Maximal term depth    :    6 (   3 average)
-% SPC      : CNF_UNK_UEQ
-
-% Comments : Commutativity, associativity, and Huntington's axiom
-%            axiomatize Boolean algebra.
-%--------------------------------------------------------------------------
-%----Include axioms for Robbins algebra
-%--------------------------------------------------------------------------
-cnf(commutativity_of_add,axiom,
-    ( '+'(X,Y) = '+'(Y,X) )).
-
-cnf(associativity_of_add,axiom,
-    ( '+'('+'(X,Y),Z) = '+'(X,'+'(Y,Z)) )).
-
-cnf(robbins_axiom,axiom,
-    ( '-'('+'('-'('+'(X,Y)),'-'('+'(X,'-'(Y))))) = X )).
-
-%--------------------------------------------------------------------------
-%--------------------------------------------------------------------------
-cnf(double_negation,hypothesis,
-    ( '-'('-'(c)) = c )).
-
-cnf(prove_huntingtons_axiom,negated_conjecture,
-    '+'('-'('+'(a,'-'(b))),'-'('+'('-'(a),'-'(b)))) != b).
-
-%--------------------------------------------------------------------------
-%----Definition of g
-cnf(sos04,axiom,(
-    g(A) = '-'('+'(A,'-'(A))) )).
-
-%----Definition of h
-cnf(sos05,axiom,(
-    h(A) = '+'(A,'+'(A,'+'(A,'-'('+'(A,'-'(A)))))))).
diff --git a/tests/ROB027-1.p b/tests/ROB027-1.p
deleted file mode 100644
--- a/tests/ROB027-1.p
+++ /dev/null
@@ -1,56 +0,0 @@
-%--------------------------------------------------------------------------
-% File     : ROB027-1 : TPTP v6.3.0. Released v1.2.0.
-% Domain   : Robbins Algebra
-% Problem  : -(-c) = c => Boolean
-% Version  : [Win90] (equality) axioms.
-%            Theorem formulation : Denies Huntington's axiom.
-% English  : If there are elements c and d such that c+d=d, then the
-%            algebra is Boolean.
-
-% Refs     : [HMT71] Henkin et al. (1971), Cylindrical Algebras
-%          : [Win90] Winker (1990), Robbins Algebra: Conditions that make a
-%          : [Wos94] Wos (1994), Two Challenge Problems
-% Source   : [Wos94]
-% Names    : - [Wos94]
-
-% Status   : Open
-% Rating   : 1.00 v2.0.0
-% Syntax   : Number of clauses     :    5 (   0 non-Horn;   5 unit;   2 RR)
-%            Number of atoms       :    5 (   5 equality)
-%            Maximal clause size   :    1 (   1 average)
-%            Number of predicates  :    1 (   0 propositional; 2-2 arity)
-%            Number of functors    :    5 (   3 constant; 0-2 arity)
-%            Number of variables   :    7 (   0 singleton)
-%            Maximal term depth    :    6 (   3 average)
-% SPC      : CNF_UNK_UEQ
-
-% Comments : Commutativity, associativity, and Huntington's axiom
-%            axiomatize Boolean algebra.
-%--------------------------------------------------------------------------
-%----Include axioms for Robbins algebra
-%--------------------------------------------------------------------------
-cnf(commutativity_of_add,axiom,
-    ( add(X,Y) = add(Y,X) )).
-
-cnf(associativity_of_add,axiom,
-    ( add(add(X,Y),Z) = add(X,add(Y,Z)) )).
-
-cnf(robbins_axiom,axiom,
-    ( negate(add(negate(add(X,Y)),negate(add(X,negate(Y))))) = X )).
-
-%--------------------------------------------------------------------------
-%--------------------------------------------------------------------------
-cnf(double_negation,hypothesis,
-    ( negate(negate(c)) = c )).
-
-cnf(prove_huntingtons_axiom,negated_conjecture,
-    add(negate(add(a,negate(b))),negate(add(negate(a),negate(b)))) != b).
-
-%--------------------------------------------------------------------------
-%----Definition of g
-cnf(sos04,axiom,(
-    g(A) = negate(add(A,negate(A))) )).
-
-%----Definition of h
-cnf(sos05,axiom,(
-    h(A) = add(A,add(A,add(A,negate(add(A,negate(A)))))))).
diff --git a/tests/ROB033-1.p b/tests/ROB033-1.p
deleted file mode 100644
--- a/tests/ROB033-1.p
+++ /dev/null
@@ -1,10 +0,0 @@
-cnf(commutativity_of_add, axiom, add(X, Y)=add(Y, X)).
-cnf(associativity_of_add, axiom,
-    add(add(X, Y), Z)=add(X, add(Y, Z))).
-cnf(robbins_axiom, axiom,
-    negate(add(negate(add(X, Y)), negate(add(X, negate(Y)))))=X).
-cnf(sos04, axiom, g(A)=negate(add(A, negate(A)))).
-cnf(sos05, axiom, h(A)=add(A, add(A, add(A, g(A))))).
-cnf(goals, negated_conjecture,
-    add(negate(add(x0, negate(x1))),
-        negate(add(negate(x0), negate(x1))))!=x1).
diff --git a/tests/aim.p b/tests/aim.p
deleted file mode 100644
--- a/tests/aim.p
+++ /dev/null
@@ -1,62 +0,0 @@
-cnf(left_ident, axiom,
-  '1' * X = X).
-cnf(right_ident, axiom,
-  X * '1' = X).
-cnf(left_division_1, axiom,
-  X \ (X * Y) = Y).
-cnf(left_division_2, axiom,
-  X * (X \ Y) = Y).
-cnf(right_division_1, axiom,
-  (X * Y) / Y = X).
-cnf(right_division_2, axiom,
-  (X / Y) * Y = X).
-cnf(associator, axiom,
-  (X * (Y * Z)) \ ((X * Y) * Z) = a(X,Y,Z)).
-cnf(commutator, axiom,
-  (X * Y) \ (Y * X) = k(Y,X)).
-cnf(l, axiom,
-  (Y * X) \ (Y * (X * U)) = l(U,X,Y)).
-cnf(r, axiom,
-  ((U * X) * Y) / (X * Y) = r(U,X,Y)).
-cnf(t, axiom,
-  X \ (U * X) = t(U,X)).
-cnf(abelian_inner_mapping_1, axiom,
-  t(t(U,X),Y) = t(t(U,Y),X)).
-cnf(abelian_inner_mapping_2, axiom,
-  t(l(U,X,Y),Z) = l(t(U,Z),X,Y)).
-cnf(abelian_inner_mapping_3, axiom,
-  t(r(U,X,Y),Z) = r(t(U,Z),X,Y)).
-cnf(abelian_inner_mapping_4, axiom,
-  l(r(U,X,Y),Z,W) = r(l(U,Z,W),X,Y)).
-cnf(abelian_inner_mapping_5, axiom,
-  l(l(U,X,Y),Z,W) = l(l(U,Z,W),X,Y)).
-cnf(abelian_inner_mapping_6, axiom,
-  r(r(U,X,Y),Z,W) = r(r(U,Z,W),X,Y)).
-
-% aK (or "single-a") goals
-cnf(ka, conjecture,
-  k(a(x,y,z),u) = '1').
-cnf(aK1, conjecture,
-  a(k(x,y),z,u) = '1').
-cnf(aK2, conjecture,
-  a(x,k(y,z),u) = '1').
-cnf(aK3, conjecture,
-  a(x,y,k(z,u)) = '1').
-
-% aa (or "double-a") goals
-cnf(aa1, conjecture,
-  a(a(x,y,z),u,w) = '1').
-cnf(aa2, conjecture,
-  a(x,a(y,z,u),w) = '1').
-cnf(aa3, conjecture,
-  a(x,y,a(z,u,w)) = '1').
-
-%cnf(everything, conjecture,
-%  k(a(X,Y,Z),U) = '1' |
-%  a(k(X,Y),Z,U) = '1' |
-%  a(X,k(Y,Z),U) = '1' |
-%  a(X,Y,k(Z,U)) = '1' |
-%  a(a(X,Y,Z),U,W) = '1' |
-%  a(X,a(Y,Z,U),W) = '1' |
-%  a(X,Y,a(Z,U,W)) = '1').
-
diff --git a/tests/aim2.p b/tests/aim2.p
deleted file mode 100644
--- a/tests/aim2.p
+++ /dev/null
@@ -1,64 +0,0 @@
-cnf(left_ident, axiom,
-  '1' * X = X).
-cnf(right_ident, axiom,
-  X * '1' = X).
-cnf(left_division_1, axiom,
-  X \ (X * Y) = Y).
-cnf(left_division_2, axiom,
-  X * (X \ Y) = Y).
-cnf(right_division_1, axiom,
-  (X * Y) / Y = X).
-cnf(right_division_2, axiom,
-  (X / Y) * Y = X).
-cnf(associator, axiom,
-  (X * (Y * Z)) \ ((X * Y) * Z) = a(X,Y,Z)).
-cnf(commutator, axiom,
-  (X * Y) \ (Y * X) = k(Y,X)).
-cnf(l, axiom,
-  (Y * X) \ (Y * (X * U)) = l(U,X,Y)).
-cnf(r, axiom,
-  ((U * X) * Y) / (X * Y) = r(U,X,Y)).
-cnf(t, axiom,
-  X \ (U * X) = t(U,X)).
-cnf(abelian_inner_mapping_1, axiom,
-  t(t(U,X),Y) = t(t(U,Y),X)).
-cnf(abelian_inner_mapping_2, axiom,
-  t(l(U,X,Y),Z) = l(t(U,Z),X,Y)).
-cnf(abelian_inner_mapping_3, axiom,
-  t(r(U,X,Y),Z) = r(t(U,Z),X,Y)).
-cnf(abelian_inner_mapping_4, axiom,
-  l(r(U,X,Y),Z,W) = r(l(U,Z,W),X,Y)).
-cnf(abelian_inner_mapping_5, axiom,
-  l(l(U,X,Y),Z,W) = l(l(U,Z,W),X,Y)).
-cnf(abelian_inner_mapping_6, axiom,
-  r(r(U,X,Y),Z,W) = r(r(U,Z,W),X,Y)).
-
-% aK (or "single-a") goals
-cnf(ka, conjecture,
-  k(a(X,Y,Z),U) = '1').
-cnf(aK1, conjecture,
-  a(k(X,Y),Z,U) = '1').
-cnf(aK2, conjecture,
-  a(X,k(Y,Z),U) = '1').
-cnf(aK3, conjecture,
-  a(X,Y,k(Z,U)) = '1').
-
-% aa (or "double-a") goals
-cnf(aa1, conjecture,
-  a(a(X,Y,Z),U,W) = '1').
-cnf(aa2, conjecture,
-  a(X,a(Y,Z,U),W) = '1').
-cnf(aa3, conjecture,
-  a(X,Y,a(Z,U,W)) = '1').
-
-%cnf(everything, conjecture,
-%  k(a(X,Y,Z),U) = '1' |
-%  a(k(X,Y),Z,U) = '1' |
-%  a(X,k(Y,Z),U) = '1' |
-%  a(X,Y,k(Z,U)) = '1' |
-%  a(a(X,Y,Z),U,W) = '1' |
-%  a(X,a(Y,Z,U),W) = '1' |
-%  a(X,Y,a(Z,U,W)) = '1').
-
-
-cnf(bonus, axiom, (X * (Y / X)) \ X = Y \ (Y / (Y / X))).
diff --git a/tests/append-rev.p b/tests/append-rev.p
deleted file mode 100644
--- a/tests/append-rev.p
+++ /dev/null
@@ -1,4 +0,0 @@
-cnf(rev_rev, axiom, rev(rev(X)) = X).
-cnf(app_assoc, axiom, X ++ (Y ++ Z) = (X ++ Y) ++ Z).
-cnf(rev_app, axiom, rev(X) ++ rev(Y) = rev(Y ++ X)).
-fof(conjecture, conjecture, ![A,B]: A ++ rev(B) = rev(B ++ rev(A))).
diff --git a/tests/cm.p b/tests/cm.p
deleted file mode 100644
--- a/tests/cm.p
+++ /dev/null
@@ -1,3 +0,0 @@
-fof(a, axiom, ![X, Y]: plus(X, Y)=plus(Y, X)).
-fof(a, axiom, ![X, Y, Z]: plus(plus(X, Y), Z)=plus(X, plus(Z, Y))).
-fof(a, axiom, a!=b).
diff --git a/tests/deriv.p b/tests/deriv.p
deleted file mode 100644
--- a/tests/deriv.p
+++ /dev/null
@@ -1,37 +0,0 @@
-% Axioms about arithmetic.
-
-cnf('commutativity of +', axiom,
-    X + Y = Y + X).
-cnf('associativity of +', axiom,
-    X + (Y + Z) = (X + Y) + Z).
-cnf('commutativity of *', axiom,
-    X * Y = Y * X).
-cnf('associativity of *', axiom,
-    X * (Y * Z) = (X * Y) * Z).
-cnf('plus 0', axiom,
-    '0' + X = X).
-cnf('times 0', axiom,
-    '0' * X = '0').
-cnf('times 1', axiom,
-    '1' * X = X).
-cnf('distributivity', axiom,
-    X * (Y + Z) = (X * Y) + (X * Z)).
-cnf('minus', axiom,
-    X + -X = '0').
-cnf('derivative of 0', axiom,
-    d('0') = '0').
-cnf('derivative of 1', axiom,
-    d('1') = '0').
-cnf('derivative of x', axiom,
-    d(x) = '1').
-cnf('derivative of +', axiom,
-    d(T+U) = d(T) + d(U)).
-cnf('derivative of *', axiom,
-    d(T*U) = (T*d(U)) + (U*d(T))).
-cnf('derivative of sin', axiom,
-    d(sin(T)) = cos(T) * d(T)).
-cnf('derivative of cos', axiom,
-    d(cos(T)) = -(sin(T)*d(T))).
-
-fof(goal, conjecture,
-    ?[T]: d(T) = x*cos(x)).
diff --git a/tests/diff.p b/tests/diff.p
deleted file mode 100644
--- a/tests/diff.p
+++ /dev/null
@@ -1,8 +0,0 @@
-cnf('x\\(y\\x)=x', axiom,
-    X \ (Y \ X) = X).
-cnf('x\\(x\\y)=y\\(y\\x)', axiom,
-    X \ (X \ Y) = Y \ (Y \ X)).
-cnf('(x\\y)\\z=(x\\z)\\(y\\z)', axiom,
-    (X \ Y) \ Z = (X \ Z) \ (Y \ Z)).
-cnf(conjecture, conjecture,
-    (a \ c) \ b = (a \ b) \ c).
diff --git a/tests/diff2.p b/tests/diff2.p
deleted file mode 100644
--- a/tests/diff2.p
+++ /dev/null
@@ -1,34 +0,0 @@
-cnf('x\\(y\\x)=x', axiom,
-    X \ (Y \ X) = X).
-cnf('x\\(x\\y)=y\\(y\\x)', axiom,
-    X \ (X \ Y) = Y \ (Y \ X)).
-cnf('(x\\y)\\z=(x\\z)\\(y\\z)', axiom,
-    (X \ Y) \ Z = (X \ Z) \ (Y \ Z)).
-
-cnf(empty, axiom,
-    X \ empty = X).
-
-cnf(equals, conjecture,
-    (X \ Y = empty & Y \ X = empty) => X = Y).
-
-cnf(union, axiom,
-    X \ union(Y, Z) = (X \ Y) \ Z).
-
-cnf(union, conjecture,
-    union(a,b) = union(b,a)).
-cnf(union, conjecture,
-    union(a,a) = a).
-cnf(union, conjecture,
-    union(a,union(b,c)) = union(union(a,b),c)).
-
-cnf(intersection, axiom,
-    intersection(X, Y) = X \ (X \ Y)).
-
-cnf(intersection, conjecture,
-    intersection(a,b) = intersection(b,a)).
-cnf(intersection, conjecture,
-    intersection(a,a) = a).
-cnf(intersection, conjecture,
-    intersection(a,intersection(b,c)) = intersection(intersection(a,b),c)).
-cnf(intersection, conjecture,
-    intersection(X, Y) = union(X,Y) \ union(X \ Y, Y \ X)).
diff --git a/tests/factor.p b/tests/factor.p
deleted file mode 100644
--- a/tests/factor.p
+++ /dev/null
@@ -1,44 +0,0 @@
-% Axioms about arithmetic.
-
-cnf('commutativity_of_plus', axiom,
-    X + Y = Y + X).
-cnf('associativity_of_plus', axiom,
-    X + (Y + Z) = (X + Y) + Z).
-cnf('commutativity_of_times', axiom,
-    X * Y = Y * X).
-cnf('associativity_of_times', axiom,
-    X * (Y * Z) = (X * Y) * Z).
-cnf('plus_zero', axiom,
-    '0' + X = X).
-cnf('times_zero', axiom,
-    '0' * X = '0').
-cnf('times_one', axiom,
-    '1' * X = X).
-cnf('distributivity', axiom,
-    X * (Y + Z) = (X * Y) + (X * Z)).
-cnf('minus', axiom,
-    X + -X = '0').
-
-cnf(two, axiom, two = '1'+'1').
-cnf(three, axiom, three = '1'+two).
-cnf(four, axiom, four = '1'+three).
-cnf(five, axiom, five = '1'+four).
-cnf(six, axiom, six = '1'+five).
-cnf(seven, axiom, seven = '1'+six).
-cnf(eight, axiom, eight = '1'+seven).
-cnf(nine, axiom, nine = '1'+eight).
-cnf(minus_six, axiom, minus_four = -four).
-cnf(minus_six, axiom, minus_six = -six).
-
-fof(factoring, conjecture,
-    ?[A,B,C]: ![X]:
-      (X*(X*X)) + ((minus_six*(X*X)) + ((nine*X) + minus_four)) = ((X +
-      -'1')*((X + -'1') * (X + -four)))).
-
-fof(factoring, conjecture,
-    ?[A,B,C]: ![X]:
-    (X*(X*X)) +
-    (-(('1'+('1'+('1'+('1'+('1'+'1')))))*(X*X)) +
-     ((('1'+('1'+('1'+('1'+('1'+('1'+('1'+('1'+'1'))))))))*X) +
-     -('1'+('1'+('1'+'1'))))) =
-    (X + -A)*((X + -B)*(X + -C))).
diff --git a/tests/filter.p b/tests/filter.p
deleted file mode 100644
--- a/tests/filter.p
+++ /dev/null
@@ -1,59 +0,0 @@
-fof('associativity of ∘', axiom,
-    ![F, G, H]:
-    F ∘ (G ∘ H) = (F ∘ G) ∘ H).
-
-fof('∘ identity', axiom,
-    ![F]:
-    id ∘ F = F).
-
-fof('∘ identity', axiom,
-    ![F]:
-    F ∘ id = F).
-
-fof('map functor', axiom,
-    ![F, G]:
-    map(F) ∘ map(G) = map(F ∘ G)).
-
-fof('map functor', axiom,
-    map(id) = id).
-
-fof('naturality of concat', axiom,
-    ![F]:
-    map(F) ∘ concat = concat ∘ map(map(F))).
-
-fof('defn filter', axiom,
-    ![P]:
-    filter(P) = concat ∘ map(test(P))).
-
-% test(P) = \x -> if P(x) then [x] else []
-
-fof('test property', axiom,
-    ![P, F]:
-    test(P) ∘ F =
-    map(F) ∘ test(P ∘ F)).
-
-fof('map/filter', conjecture,
-    ![P, F]:
-    filter(P) ∘ map(F) = map(F) ∘ filter(P ∘ F)).
-
-
-% cond(P, F, G) = \x -> if P(x) then F(x) else G(x)
-
-%fof('test defn', axiom,
-%    ![P]:
-%    test(P) = cond(P, unit, nil)).
-%fof('cond ∘', axiom,
-%    ![F, P, G, H]:
-%    F ∘ cond(P, G, H) = cond(P, F ∘ G, F ∘ H)).
-%fof('cond ∘', axiom,
-%    ![F, P, G, H]:
-%    cond(P, G, H) ∘ F = cond(P ∘ F, G ∘ F, H ∘ F)).
-%fof('nil', axiom,
-%    ![F]:
-%    nil ∘ F = nil).
-%fof('nil', axiom,
-%    ![F]:
-%    map(F) ∘ nil = nil).
-%fof('unit', axiom,
-%    ![F]:
-%    map(F) ∘ unit = unit ∘ F).
diff --git a/tests/filter2.p b/tests/filter2.p
deleted file mode 100644
--- a/tests/filter2.p
+++ /dev/null
@@ -1,59 +0,0 @@
-fof('associativity of ∘', axiom,
-    ![F, G, H]:
-    F ∘ (G ∘ H) = (F ∘ G) ∘ H).
-
-fof('∘ identity', axiom,
-    ![F]:
-    id ∘ F = F).
-
-fof('∘ identity', axiom,
-    ![F]:
-    F ∘ id = F).
-
-fof('map functor', axiom,
-    ![F, G]:
-    map(F) ∘ map(G) = map(F ∘ G)).
-
-fof('map functor', axiom,
-    map(id) = id).
-
-fof('naturality of concat', axiom,
-    ![F]:
-    map(F) ∘ concat = concat ∘ map(map(F))).
-
-fof('defn filter', axiom,
-    ![P]:
-    filter(P) = concat ∘ map(test(P))).
-
-% test(P) = \x -> if P(x) then [x] else []
-
-%fof('test property', axiom,
-%    ![P, F]:
-%    test(P) ∘ F =
-%    map(F) ∘ test(P ∘ F)).
-
-fof('map/filter', conjecture,
-    ![P, F]:
-    filter(P) ∘ map(F) = map(F) ∘ filter(P ∘ F)).
-
-
-% cond(P, F, G) = \x -> if P(x) then F(x) else G(x)
-
-fof('test defn', axiom,
-    ![P]:
-    test(P) = cond(P, unit, nil)).
-fof('cond ∘', axiom,
-    ![F, P, G, H]:
-    F ∘ cond(P, G, H) = cond(P, F ∘ G, F ∘ H)).
-fof('cond ∘', axiom,
-    ![F, P, G, H]:
-    cond(P, G, H) ∘ F = cond(P ∘ F, G ∘ F, H ∘ F)).
-fof('nil', axiom,
-    ![F]:
-    nil ∘ F = nil).
-fof('nil', axiom,
-    ![F]:
-    map(F) ∘ nil = nil).
-fof('unit', axiom,
-    ![F]:
-    map(F) ∘ unit = unit ∘ F).
diff --git a/tests/gmv.p b/tests/gmv.p
deleted file mode 100644
--- a/tests/gmv.p
+++ /dev/null
@@ -1,74 +0,0 @@
-cnf('Associativity-∧', axiom,
-    (X ∧ Y) ∧ Z = X ∧ (Y ∧ Z)).   
-cnf('Associativity-∨', axiom,
-    (X ∨ Y) ∨ Z = X ∨ (Y ∨ Z)).
-cnf('Idempotence-∧', axiom,
-    X ∧ X = X).
-cnf('Idempotence-∨', axiom,
-    X ∨ X = X).
-cnf('Commutativity-∧', axiom,
-    X ∧ Y = Y ∧ X).
-cnf('Commutativity-∨', axiom,
-    X ∨ Y = Y ∨ X).
-cnf('Absorption a', axiom,
-    (X ∧ Y) ∨ X = X).
-cnf('Absorption b', axiom,
-    (X ∨ Y) ∧ X = X).
-
-cnf('Residual a', axiom,
-    (X * ((X \ Z) ∧ Y)) ∨ Z = Z).
-cnf('Residual b', axiom,
-    ((Y ∧ (Z / X)) * X) ∨ Z = Z).
-cnf('Residual c', axiom,
-    (X \ ((X * Y) ∨ Z)) ∧ Y = Y).
-cnf('Residual d', axiom,
-    (((Y * X) ∨ Z) / X) ∧ Y = Y).
-
-cnf('Associativity-* (fusion)', axiom,
-    (X * Y) * Z = X * (Y * Z)).
-cnf('Left monoid unit', axiom,
-    '1' * X = X).
-cnf('Right monoid unit', axiom,
-    X * '1' = X).
-
-cnf('GMV a', axiom,
-    X ∨ Y = X / ((X ∨ Y) \ X)).
-cnf('GMV b', axiom,
-    X ∨ Y = (X / (X ∨ Y)) \ X).
-
-cnf('Definition-@', axiom,
-    X @ Y = (X * (X \ '1')) * ((Y \ '1') \ '1')).
-
-cnf('Goal 1', conjecture,
-    x @ x = x).
-cnf('Goal 2', conjecture,
-    (x @ y) @ z = x @ z).
-cnf('Goal 3', conjecture,
-    x @ (y @ z) = x @ z).
-  
-cnf('Goal 4', conjecture,
-    (x ∧ y) @ (z ∧ u) = (x @ z) ∧ (y @ u)).
-cnf('Goal 5', conjecture,
-    (x ∨ y) @ (z ∨ u) = (x @ z) ∨ (y @ u)).
-cnf('Goal 6', conjecture,
-    (x \ y) @ (z \ u) = (x @ z) \ (y @ u)).
-cnf('Goal 7', conjecture,
-    (x / y) @ (z / u) = (x @ z) / (y @ u)).
-  
-cnf('Goal 8', conjecture,
-    (x * (x \ '1')) @ '1' = x * (x \ '1')).
-cnf('Goal 9', conjecture,
-    '1' @ (x * (x \ '1')) = '1').
-cnf('Goal 10', conjecture,
-    (x \ '1') @ '1' = '1').
-cnf('Goal 11', conjecture,
-    '1' @ (x \ '1') = x \ '1').
-  
-cnf('Goal 12', conjecture,
-    (x / (y \ x)) @ (x ∨ y) = x ∨ y).
-cnf('Goal 13', conjecture,
-    ((x / y) \ x) @ (x ∨ y) = x ∨ y).
-cnf('Goal 14', conjecture,
-    (x ∨ y) @ (x / (y \ x)) = x / (y \ x)).
-cnf('Goal 15', conjecture,
-    (x ∨ y) @ ((x / y) \ x) = (x / y) \ x).
diff --git a/tests/group.p b/tests/group.p
deleted file mode 100644
--- a/tests/group.p
+++ /dev/null
@@ -1,14 +0,0 @@
-cnf(associativity, axiom,
-    X + (Y + Z) = (X + Y) + Z).
-cnf(plus_zero, axiom,
-    '0' + X = X).
-cnf(plus_zero, axiom,
-    X + '0' = X).
-cnf(minus_left, axiom,
-    (-X) + X = '0').
-cnf(minus_right, axiom,
-    X + (-X) = '0').
-cnf(assumption, assumption,
-    a + b = a).
-cnf(goal, conjecture,
-    b = '0').
diff --git a/tests/haken.p b/tests/haken.p
deleted file mode 100644
--- a/tests/haken.p
+++ /dev/null
@@ -1,170 +0,0 @@
-cnf(a, conjecture, a1 = a2 & a2 = a3 & a3 = a4 & a4 = a5 & a5 = a6 &
-a6 = a7 & a7 = a8 & a8 = a9 & a9 = a10 & a10 = a11 & a11 = a12 & a12 =
-a13 & a13 = a14 & a14 = a15 & a15 = a16 & a16 = a17 & a17 = a18 & a18
-= a19 & a19 = a20 & a20 = a21 & a20 = a22 & a21 = a23 & a23 = a24 &
-a24 = a25 & a25 = a26 & a26 = a27 & a27 = a28 & a28 = a29 & a29 = a30
-& a30 = a31 & a31 = a32 & a32 = a33 & a33 = a34 & a34 = a35 & a35 =
-a36 & a36 = a37 & a37 = a38 & a38 = a39 & a39 = a40 & a40 = a41 & a41
-= a42 & a42 = a43 & a43 = a44 & a44 = a45 & a45 = a46 & a46 = a47 &
-a47 = a48 & a48 = a49 & a49 = a50 & a50 = a51 & a51 = a52 & a52 = a53
-& a53 = a54 & a54 = a55 & a55 = a56 & a56 = a57 & a57 = a58 & a58 =
-a59 & a59 = a60 & a60 = a61 & a61 = a62 & a62 = a63 & a63 = a64 & a64
-= a65 & a65 = a66 & a66 = a67 & a67 = a68 & a68 = a69 & a69 = a70 &
-a70 = a71 & a71 = a72 & a72 = a73 & a73 = a74 & a74 = a75 & a75 = a76
-& a76 = a77 & a77 = a78 & a78 = a79 & a79 = a80 & a80 = a81 & a81 =
-a82 & a82 = a83 & a83 = a84 & a84 = a85 & a85 = a86 & a86 = a87 & a87
-= a88 & a88 = a89 & a89 = a90 & a90 = a91 & a91 = a92 & a92 = a93 &
-a93 = a94 & a94 = a95 & a95 = a96 & a96 = a97 & a97 = a98 & a98 = a99
-& a99 = a100 & a100 = a101 & a101 = a102 & a102 = a103 & a103 = a104 &
-a104 = a105 & a105 = a106 & a106 = a107 & a107 = a108 & a108 = a109 &
-a109 = a110 & a110 = a111 & a111 = a112 & a112 = a113 & a113 = a114 &
-a114 = a115 & a115 = a116 & a116 = a117 & a117 = a118 & a118 = a119 &
-a119 = a120 & a120 = a121 & a121 = a122 & a122 = a123 & a123 = a124 &
-a124 = a125 & a125 = a126 & a126 = a127 & a127 = a128 & a128 = a129 &
-a129 = a130 & a130 = a131 & a131 = a132 & a132 = a133 & a133 = a134 &
-a134 = a135 & a135 = a136 & a136 = a137 & a137 = a138 & a138 = a139 &
-a139 = a140 & a140 = a141).
-cnf(a, axiom, '*'(X, X) = X).
-cnf(a, axiom, '*'('*'(X,Y),Y) = X).
-cnf(a, axiom, '*'('*'(X,Y),Z) = '*'('*'(X, Z), '*'(Y, Z))).
-cnf(a, axiom, a2 = '*'(a1, a42)).
-cnf(a, axiom, a3 = '*'(a2, a41)).
-cnf(a, axiom, a4 = '*'(a3, a14)).
-cnf(a, axiom, a5 = '*'(a4, a39)).
-cnf(a, axiom, a6 = '*'(a5, a136)).
-cnf(a, axiom, a7 = '*'(a6, a52)).
-cnf(a, axiom, a8 = '*'(a7, a17)).
-cnf(a, axiom, a9 = '*'(a8, a56)).
-cnf(a, axiom, a10 = '*'(a9, a134)).
-cnf(a, axiom, a11 = '*'(a10, a37)).
-cnf(a, axiom, a12 = '*'(a11, a21)).
-cnf(a, axiom, a13 = '*'(a12, a23)).
-cnf(a, axiom, a14 = '*'(a13, a32)).
-cnf(a, axiom, a15 = '*'(a14, a53)).
-cnf(a, axiom, a16 = '*'(a15, a136)).
-cnf(a, axiom, a17 = '*'(a16, a29)).
-cnf(a, axiom, a18 = '*'(a17, a133)).
-cnf(a, axiom, a19 = '*'(a18, a58)).
-cnf(a, axiom, a20 = '*'(a19, a26)).
-cnf(a, axiom, a21 = '*'(a20, a35)).
-cnf(a, axiom, a22 = '*'(a21, a141)).
-cnf(a, axiom, a23 = '*'(a22, a45)).
-cnf(a, axiom, a24 = '*'(a23, a35)).
-cnf(a, axiom, a25 = '*'(a24, a49)).
-cnf(a, axiom, a26 = '*'(a25, a138)).
-cnf(a, axiom, a27 = '*'(a26, a8)).
-cnf(a, axiom, a28 = '*'(a27, a37)).
-cnf(a, axiom, a29 = '*'(a28, a17)).
-cnf(a, axiom, a30 = '*'(a29, a14)).
-cnf(a, axiom, a31 = '*'(a30, a5)).
-cnf(a, axiom, a32 = '*'(a31, a39)).
-cnf(a, axiom, a33 = '*'(a32, a13)).
-cnf(a, axiom, a34 = '*'(a33, a131)).
-cnf(a, axiom, a35 = '*'(a34, a60)).
-cnf(a, axiom, a36 = '*'(a35, a139)).
-cnf(a, axiom, a37 = '*'(a36, a47)).
-cnf(a, axiom, a38 = '*'(a37, a17)).
-cnf(a, axiom, a39 = '*'(a38, a7)).
-cnf(a, axiom, a40 = '*'(a39, a4)).
-cnf(a, axiom, a41 = '*'(a40, a14)).
-cnf(a, axiom, a42 = '*'(a41, a2)).
-cnf(a, axiom, a43 = '*'(a42, a62)).
-cnf(a, axiom, a44 = '*'(a43, a128)).
-cnf(a, axiom, a45 = '*'(a44, a23)).
-cnf(a, axiom, a46 = '*'(a45, a141)).
-cnf(a, axiom, a47 = '*'(a46, a11)).
-cnf(a, axiom, a48 = '*'(a47, a20)).
-cnf(a, axiom, a49 = '*'(a48, a138)).
-cnf(a, axiom, a50 = '*'(a49, a131)).
-cnf(a, axiom, a51 = '*'(a50, a59)).
-cnf(a, axiom, a52 = '*'(a51, a39)).
-cnf(a, axiom, a53 = '*'(a52, a136)).
-cnf(a, axiom, a54 = '*'(a53, a29)).
-cnf(a, axiom, a55 = '*'(a54, a135)).
-cnf(a, axiom, a56 = '*'(a55, a37)).
-cnf(a, axiom, a57 = '*'(a56, a134)).
-cnf(a, axiom, a58 = '*'(a57, a26)).
-cnf(a, axiom, a59 = '*'(a58, a138)).
-cnf(a, axiom, a60 = '*'(a59, a131)).
-cnf(a, axiom, a61 = '*'(a60, a13)).
-cnf(a, axiom, a62 = '*'(a61, a1)).
-cnf(a, axiom, a63 = '*'(a62, a96)).
-cnf(a, axiom, a64 = '*'(a63, a127)).
-cnf(a, axiom, a65 = '*'(a64, a41)).
-cnf(a, axiom, a66 = '*'(a65, a2)).
-cnf(a, axiom, a67 = '*'(a66, a92)).
-cnf(a, axiom, a68 = '*'(a67, a98)).
-cnf(a, axiom, a69 = '*'(a68, a32)).
-cnf(a, axiom, a70 = '*'(a69, a13)).
-cnf(a, axiom, a71 = '*'(a70, a118)).
-cnf(a, axiom, a72 = '*'(a71, a109)).
-cnf(a, axiom, a73 = '*'(a72, a82)).
-cnf(a, axiom, a74 = '*'(a73, a32)).
-cnf(a, axiom, a75 = '*'(a74, a14)).
-cnf(a, axiom, a76 = '*'(a75, a68)).
-cnf(a, axiom, a77 = '*'(a76, a114)).
-cnf(a, axiom, a78 = '*'(a77, a13)).
-cnf(a, axiom, a79 = '*'(a78, a33)).
-cnf(a, axiom, a80 = '*'(a79, a119)).
-cnf(a, axiom, a81 = '*'(a80, a70)).
-cnf(a, axiom, a82 = '*'(a81, a109)).
-cnf(a, axiom, a83 = '*'(a82, a118)).
-cnf(a, axiom, a84 = '*'(a83, a39)).
-cnf(a, axiom, a85 = '*'(a84, a5)).
-cnf(a, axiom, a86 = '*'(a85, a30)).
-cnf(a, axiom, a87 = '*'(a86, a104)).
-cnf(a, axiom, a88 = '*'(a87, a4)).
-cnf(a, axiom, a89 = '*'(a88, a14)).
-cnf(a, axiom, a90 = '*'(a89, a41)).
-cnf(a, axiom, a91 = '*'(a90, a100)).
-cnf(a, axiom, a92 = '*'(a91, a124)).
-cnf(a, axiom, a93 = '*'(a92, a2)).
-cnf(a, axiom, a94 = '*'(a93, a41)).
-cnf(a, axiom, a95 = '*'(a94, a127)).
-cnf(a, axiom, a96 = '*'(a95, a64)).
-cnf(a, axiom, a97 = '*'(a96, a42)).
-cnf(a, axiom, a98 = '*'(a97, a1)).
-cnf(a, axiom, a99 = '*'(a98, a92)).
-cnf(a, axiom, a100 = '*'(a99, a124)).
-cnf(a, axiom, a101 = '*'(a100, a14)).
-cnf(a, axiom, a102 = '*'(a101, a40)).
-cnf(a, axiom, a103 = '*'(a102, a4)).
-cnf(a, axiom, a104 = '*'(a103, a87)).
-cnf(a, axiom, a105 = '*'(a104, a30)).
-cnf(a, axiom, a106 = '*'(a105, a5)).
-cnf(a, axiom, a107 = '*'(a106, a84)).
-cnf(a, axiom, a108 = '*'(a107, a39)).
-cnf(a, axiom, a109 = '*'(a108, a118)).
-cnf(a, axiom, a110 = '*'(a109, a70)).
-cnf(a, axiom, a111 = '*'(a110, a119)).
-cnf(a, axiom, a112 = '*'(a111, a79)).
-cnf(a, axiom, a113 = '*'(a112, a33)).
-cnf(a, axiom, a114 = '*'(a113, a13)).
-cnf(a, axiom, a115 = '*'(a114, a68)).
-cnf(a, axiom, a116 = '*'(a115, a14)).
-cnf(a, axiom, a117 = '*'(a116, a74)).
-cnf(a, axiom, a118 = '*'(a117, a32)).
-cnf(a, axiom, a119 = '*'(a118, a70)).
-cnf(a, axiom, a120 = '*'(a119, a13)).
-cnf(a, axiom, a121 = '*'(a120, a32)).
-cnf(a, axiom, a122 = '*'(a121, a68)).
-cnf(a, axiom, a123 = '*'(a122, a115)).
-cnf(a, axiom, a124 = '*'(a123, a75)).
-cnf(a, axiom, a125 = '*'(a124, a2)).
-cnf(a, axiom, a126 = '*'(a125, a65)).
-cnf(a, axiom, a127 = '*'(a126, a41)).
-cnf(a, axiom, a128 = '*'(a127, a96)).
-cnf(a, axiom, a129 = '*'(a128, a62)).
-cnf(a, axiom, a130 = '*'(a129, a1)).
-cnf(a, axiom, a131 = '*'(a130, a13)).
-cnf(a, axiom, a132 = '*'(a131, a138)).
-cnf(a, axiom, a133 = '*'(a132, a58)).
-cnf(a, axiom, a134 = '*'(a133, a26)).
-cnf(a, axiom, a135 = '*'(a134, a37)).
-cnf(a, axiom, a136 = '*'(a135, a29)).
-cnf(a, axiom, a137 = '*'(a136, a39)).
-cnf(a, axiom, a138 = '*'(a137, a51)).
-cnf(a, axiom, a139 = '*'(a138, a20)).
-cnf(a, axiom, a140 = '*'(a139, a47)).
-cnf(a, axiom, a141 = '*'(a140, a11)).
-cnf(a, axiom, a1 = '*'(a141, a23)).
diff --git a/tests/loop.p b/tests/loop.p
deleted file mode 100644
--- a/tests/loop.p
+++ /dev/null
@@ -1,6 +0,0 @@
-cnf(mult_ld, axiom, X * (X \ Y) = Y).
-cnf(ld_mult, axiom, X \ (X * Y) = Y).
-cnf(mult_rd, axiom, (X / Y) * Y = X).
-cnf(rd_mult, axiom, (X * Y) / Y = X).
-cnf(moufang, axiom, X * (Y * (X * Z)) = ((X * Y) * X) * Z).
-cnf(conjecture, conjecture, a \ a = a / a).
diff --git a/tests/loop2.p b/tests/loop2.p
deleted file mode 100644
--- a/tests/loop2.p
+++ /dev/null
@@ -1,6 +0,0 @@
-cnf('*-\\', axiom, X * (X \ Y) = Y).
-cnf('\\-*', axiom, X \ (X * Y) = Y).
-cnf('*-/', axiom, (X / Y) * Y = X).
-cnf('/-*', axiom, (X * Y) / Y = X).
-cnf(moufang, axiom, X * (Y * (X * Z)) = ((X * Y) * X) * Z).
-cnf(conjecture, conjecture, a * (b / b) = a).
diff --git a/tests/lukasiewicz.p b/tests/lukasiewicz.p
deleted file mode 100644
--- a/tests/lukasiewicz.p
+++ /dev/null
@@ -1,6 +0,0 @@
-cnf(imp_true, axiom, implies(true, X) = X).
-cnf(imp_compose, axiom, implies(implies(X, Y), implies(implies(Y, Z), implies(X, Z))) = true).
-cnf(imp_not, axiom, implies(implies(not(X), not(Y)), implies(Y, X)) = true).
-cnf(imp_switch, axiom, implies(implies(X, Y), Y) = implies(implies(Y, X), X)).
-cnf(or_def, axiom, or(X, Y) = implies(not(X), Y)).
-cnf(conjecture, negated_conjecture, or(a,or(b,c)) != or(or(a,b),c)).
diff --git a/tests/lukasiewicz2.p b/tests/lukasiewicz2.p
deleted file mode 100644
--- a/tests/lukasiewicz2.p
+++ /dev/null
@@ -1,5 +0,0 @@
-cnf(detachment, axiom, (p(X) & p(i(X,Y))) => p(Y)).
-cnf(lukasiewicz, axiom, p(i(i(i(P,Q),R),i(i(R,P),i(S,P))))).
-cnf(simp, axiom, p(i(P, i(Q, Q)))).
-cnf(peirce, axiom, p(i(i(i(P,Q),P),P))).
-cnf(syll, conjecture, p(i(i(a,b),i(i(b,c),i(a,c))))).
diff --git a/tests/minus.p b/tests/minus.p
deleted file mode 100644
--- a/tests/minus.p
+++ /dev/null
@@ -1,10 +0,0 @@
-cnf(plus_zero, axiom,
-    '0' + X = X).
-cnf(plus_zero, axiom,
-    X + '0' = X).
-cnf(minus_minus, axiom,
-    - -X = X).
-cnf(minus_plus, axiom,
-    -(X + Y) = -X + -Y).
-cnf(goal, conjecture,
-    -'0' = '0').
diff --git a/tests/nicomachus-tptp-2.p b/tests/nicomachus-tptp-2.p
deleted file mode 100644
--- a/tests/nicomachus-tptp-2.p
+++ /dev/null
@@ -1,19 +0,0 @@
-cnf(plus_comm, axiom, plus(X, Y)=plus(Y, X)).
-cnf(plus_assoc, axiom, plus(X, plus(Y, Z))=plus(plus(X, Y), Z)).
-cnf(times_comm, axiom, times(X, Y)=times(Y, X)).
-cnf(times_assoc, axiom, times(X, times(Y, Z))=times(times(X, Y), Z)).
-cnf(plus_zero, axiom, plus(X, zero)=X).
-cnf(times_zero, axiom, times(X, zero)=zero).
-cnf(times_one, axiom, times(X, one)=X).
-cnf(distr, axiom, times(X, plus(Y, Z))=plus(times(X, Y), times(X, Z))).
-cnf(distr, axiom, times(plus(X, Y), Z)=plus(times(X, Z), times(Y, Z))).
-cnf(plus_s, axiom, plus(s(X), Y)=s(plus(X, Y))).
-cnf(times_s, axiom, times(s(X), Y)=plus(Y, times(X, Y))).
-cnf(sum_zero, axiom, sum(zero)=zero).
-cnf(sum_s, axiom, sum(s(N))=plus(s(N), sum(N))).
-cnf(cubes_zero, axiom, cubes(zero)=zero).
-cnf(cubes_s, axiom, cubes(s(N))=plus(times(s(N), times(s(N), s(N))), cubes(N))).
-cnf(plus_sum_step_1, axiom, plus(sum(zero), sum(zero))!=times(zero, s(zero)) | plus(sum(ih_a), sum(ih_a))=times(ih_a, s(ih_a))).
-cnf(plus_sum, axiom, plus(sum(zero), sum(zero))!=times(zero, s(zero)) | plus(sum(s(ih_a)), sum(s(ih_a)))!=times(s(ih_a), s(s(ih_a))) | plus(sum(N), sum(N))=times(N, s(N))).
-cnf(ih, axiom, times(sum(a), sum(a))=cubes(a)).
-cnf(conjecture, negated_conjecture, times(sum(s(a)), sum(s(a)))!=cubes(s(a))).
diff --git a/tests/nicomachus-tptp.p b/tests/nicomachus-tptp.p
deleted file mode 100644
--- a/tests/nicomachus-tptp.p
+++ /dev/null
@@ -1,20 +0,0 @@
-cnf(plus_comm, axiom, plus(X, Y)=plus(Y, X)).
-cnf(plus_assoc, axiom, plus(X, plus(Y, Z))=plus(plus(X, Y), Z)).
-cnf(times_comm, axiom, times(X, Y)=times(Y, X)).
-cnf(times_assoc, axiom, times(X, times(Y, Z))=times(times(X, Y), Z)).
-cnf(plus_zero, axiom, plus(X, zero)=X).
-cnf(times_zero, axiom, times(X, zero)=zero).
-cnf(times_one, axiom, times(X, one)=X).
-cnf(distr, axiom, times(X, plus(Y, Z))=plus(times(X, Y), times(X, Z))).
-cnf(distr, axiom, times(plus(X, Y), Z)=plus(times(X, Z), times(Y, Z))).
-cnf(plus_s, axiom, plus(s(X), Y)=s(plus(X, Y))).
-cnf(times_s, axiom, times(s(X), Y)=plus(Y, times(X, Y))).
-cnf(sum_zero, axiom, sum(zero)=zero).
-cnf(sum_s, axiom, sum(s(N))=plus(s(N), sum(N))).
-cnf(cubes_zero, axiom, cubes(zero)=zero).
-cnf(cubes_s, axiom, cubes(s(N))=plus(times(s(N), times(s(N), s(N))), cubes(N))).
-%cnf(plus_sum, axiom, plus(sum(N), sum(N))=times(N, s(N))).
-cnf(plus_sum_step_1, axiom, plus(sum(zero), sum(zero)) = times(zero, s(zero)) => plus(sum(ih_a), sum(ih_a)) = times(ih_a, s(ih_a))).
-cnf(plus_sum, axiom, (plus(sum(zero), sum(zero)) = times(zero, s(zero)) & plus(sum(s(ih_a)), sum(s(ih_a))) = times(s(ih_a), s(s(ih_a)))) => plus(sum(N),sum(N))=times(N,s(N))).
-cnf(ih, axiom, times(sum(a), sum(a))=cubes(a)).
-cnf(conjecture, negated_conjecture, times(sum(s(a)), sum(s(a)))!=cubes(s(a))).
diff --git a/tests/nicomachus.p b/tests/nicomachus.p
deleted file mode 100644
--- a/tests/nicomachus.p
+++ /dev/null
@@ -1,36 +0,0 @@
-cnf(plus_comm, axiom,
-    X + Y = Y + X).
-cnf(plus_assoc, axiom,
-    X + (Y + Z) = (X + Y) + Z).
-cnf(times_comm, axiom,
-    X * Y = Y * X).
-cnf(times_assoc, axiom,
-    X * (Y * Z) = (X * Y) * Z).
-cnf(plus_zero, axiom,
-    X + zero = X).
-cnf(times_zero, axiom,
-    X * zero = zero).
-cnf(times_one, axiom,
-    X * one = X).
-cnf(distr, axiom,
-    X * (Y + Z) = (X * Y) + (X * Z)).
-cnf(distr, axiom,
-    (X + Y) * Z = (X * Z) + (Y * Z)).
-cnf(plus_s, axiom,
-    s(X) + Y = s(X+Y)).
-cnf(times_s, axiom,
-    s(X)*Y = Y + (X*Y)).
-cnf(sum_zero, axiom,
-    sum(zero) = zero).
-cnf(sum_s, axiom,
-    sum(s(N)) = s(N) + sum(N)).
-cnf(cubes_zero, axiom,
-    cubes(zero) = zero).
-cnf(cubes_s, axiom,
-    cubes(s(N)) = (s(N) * (s(N) * s(N))) + cubes(N)).
-cnf(plus_sum, axiom,
-    sum(N) + sum(N) = N * s(N)).
-cnf(ih, axiom,
-    sum(a) * sum(a) = cubes(a)).
-cnf(conjecture, conjecture,
-    sum(s(a)) * sum(s(a)) = cubes(s(a))).
diff --git a/tests/nicomachus2.p b/tests/nicomachus2.p
deleted file mode 100644
--- a/tests/nicomachus2.p
+++ /dev/null
@@ -1,36 +0,0 @@
-cnf(plus_comm, axiom,
-    X + Y = Y + X).
-cnf(plus_assoc, axiom,
-    X + (Y + Z) = (X + Y) + Z).
-cnf(times_comm, axiom,
-    X * Y = Y * X).
-cnf(times_assoc, axiom,
-    X * (Y * Z) = (X * Y) * Z).
-cnf(plus_zero, axiom,
-    X + zero = X).
-cnf(times_zero, axiom,
-    X * zero = zero).
-cnf(times_one, axiom,
-    X * one = X).
-cnf(distr, axiom,
-    X * (Y + Z) = (X * Y) + (X * Z)).
-cnf(distr, axiom,
-    (X + Y) * Z = (X * Z) + (Y * Z)).
-cnf(plus_s, axiom,
-    s(X) + Y = s(X+Y)).
-cnf(times_s, axiom,
-    s(X)*Y = Y + (X*Y)).
-cnf(sum_zero, axiom,
-    sum(zero) = zero).
-cnf(sum_s, axiom,
-    sum(s(N)) = s(N) + sum(N)).
-cnf(cubes_zero, axiom,
-    cubes(zero) = zero).
-cnf(cubes_s, axiom,
-    cubes(s(N)) = (s(N) * (s(N) * s(N))) + cubes(N)).
-cnf(plus_sum, axiom,
-    sum(N) + sum(N) = N * s(N)).
-cnf(ih, axiom,
-    sum(a) * sum(a) = cubes(a)).
-cnf(conjecture, conjecture,
-    sum(s(a)) * sum(s(a)) = cubes(s(a))).
diff --git a/tests/p.p b/tests/p.p
deleted file mode 100644
--- a/tests/p.p
+++ /dev/null
@@ -1,11 +0,0 @@
-cnf(a, axiom, p(X)!=true | p(s(X))!=true).
-cnf(a, axiom, p(X)!=false | p(s(X))!=false).
-cnf(a, axiom, p(a)=true).
-cnf(a, axiom, p(s(s(a)))!=true).
-cnf(a, axiom, true!=false).
-
-cnf(p, axiom, p(a)=true).
-cnf(p, axiom, p(s(a))=true).
-cnf(p, axiom, p(s(s(a)))=false).
-cnf(p, axiom, p(s(s(s(a))))=true).
-cnf(p, axiom, p(s(s(s(X))))=false => p(s(s(s(s(X)))))=true).
diff --git a/tests/regexp.p b/tests/regexp.p
deleted file mode 100644
--- a/tests/regexp.p
+++ /dev/null
@@ -1,54 +0,0 @@
-%% and, or
-cnf(def, axiom, and(true,B) = B).
-cnf(def, axiom, and(false,B) = false).
-cnf(def, axiom, and(X,Y) = and(Y,X)).
-
-cnf(def, axiom, or(true,B) = true).
-cnf(def, axiom, or(false,B) = B).
-cnf(def, axiom, or(X,Y) = or(Y,X)).
-
-%% eq
-cnf(def, axiom, eq(X,X) = true).
-cnf(def, axiom, eq(X,Y) = eq(Y,X)).
-cnf(def, axiom, eq(a,b) = false).
-cnf(def, axiom, eq(a,c) = false).
-cnf(def, axiom, eq(b,c) = false).
-
-%% haseps
-cnf(def, axiom, haseps(atom(A)) = false).
-cnf(def, axiom, haseps(zero) = false).
-cnf(def, axiom, haseps(eps) = true).
-cnf(def, axiom, haseps(plus(P,Q)) = or(haseps(P),haseps(Q))).
-cnf(def, axiom, haseps(seq(P,Q)) = and(haseps(P),haseps(Q))).
-cnf(def, axiom, haseps(star(P)) = true).
-
-%% step
-cnf(def, axiom, step(atom(A),A) = eps).
-cnf(def, axiom, eq(A,B) = false => step(atom(A),B) = zero).
-cnf(def, axiom, step(zero,B) = zero).
-cnf(def, axiom, step(eps,B) = zero).
-cnf(def, axiom, step(plus(P,Q),B) = plus(step(P,B),step(Q,B))).
-cnf(def, axiom, haseps(P) = true => step(seq(P,Q),B) = plus(seq(step(P,B),Q),step(Q,B))).
-cnf(def, axiom, haseps(P) = false => step(seq(P,Q),B) = plus(seq(step(P,B),Q),zero)).
-cnf(def, axiom, step(star(P),B) = seq(step(P,B),star(P))).
-
-%% rec
-cnf(def, axiom, rec(P,nil) = haseps(P)).
-cnf(def, axiom, rec(P,cons(A,As)) = rec(step(P,A),As)).
-
-%% question
-cnf(hypothesis, axiom, rec(seq(P,Q), As) = rec(seq(Q,P), As)).
-cnf(goal, axiom, true != false).
-
-%cnf(a, axiom, atom(A) != zero & atom(A) != eps & atom(A) != plus(P, Q) & atom(A) != seq(P, Q) & atom(A) != star(P)).
-%cnf(a, axiom, zero != eps & zero != plus(P, Q) & zero != seq(P, Q) & zero != star(P)).
-%cnf(a, axiom, eps != plus(P, Q) & eps != seq(P, Q) & eps != star(P)).
-%cnf(a, axiom, plus(P, Q) != seq(P, Q) & plus(P, Q) != star(P)).
-%cnf(a, axiom, seq(P, Q) != star(P)).
-%cnf(a, axiom, un_atom(atom(A)) = A).
-%cnf(a, axiom, un_plus_1(plus(P, Q)) = P).
-%cnf(a, axiom, un_plus_2(plus(P, Q)) = Q).
-%cnf(a, axiom, un_seq_1(seq(P, Q)) = P).
-%cnf(a, axiom, un_seq_2(seq(P, Q)) = Q).
-%cnf(a, axiom, un_star(star(P)) = P).
-%cnf(a, axiom, a != b & b != c & a != c).
diff --git a/tests/rel.p b/tests/rel.p
deleted file mode 100644
--- a/tests/rel.p
+++ /dev/null
@@ -1,32 +0,0 @@
-tff(type, type, '_⁻¹' : $i > $i).
-tff(type, type, '_⁻' : $i > $i).
-
-cnf('commutativity of ∨', axiom,
-    A ∨ B = B ∨ A).
-cnf('associativity of ∨', axiom,
-    A ∨ (B ∨ C) = (A ∨ B) ∨ C).
-cnf('a kind of de Morgan', axiom,
-    (A⁻ ∨ B⁻)⁻ ∨ (A⁻ ∨ B)⁻ = A).
-cnf('definition of ∧', axiom,
-    A ∧ B = (A⁻ ∨ B⁻)⁻).
-cnf('associativity of ;', axiom,
-    A ; (B ; C) = (A ; B) ; C).
-cnf('identity for ;', axiom,
-    A ; '1' = A).
-cnf('distributivity of ; over ∨', axiom,
-    (A ∨ B) ; C = (A ; C) ∨ (B ; C)).
-cnf('involution of ⁻¹', axiom,
-    A⁻¹ ⁻¹ = A).
-cnf('additivity of ⁻¹', axiom,
-    (A ∨ B)⁻¹ = A⁻¹ ∨ B⁻¹).
-cnf('multiplicativity of ⁻¹', axiom,
-    (A ; B)⁻¹ = B⁻¹ ; A⁻¹).
-cnf('cancellativity of ⁻', axiom,
-    (A⁻¹ ; (A ; B)⁻) ∨ B⁻ = B⁻).
-cnf('definition of top', axiom,
-    top = A ∨ A⁻).
-cnf('definition of zero', axiom,
-    zero = A ∧ A⁻).
-cnf(goal, conjecture,
-    (r1 ; (r2 ∧ r3)) ∨ ((r1 ; r2) ∧ (r1 ; r3)) =
-    (r1 ; r2) ∧ (r1 ; r3)).
diff --git a/tests/rel2.p b/tests/rel2.p
deleted file mode 100644
--- a/tests/rel2.p
+++ /dev/null
@@ -1,32 +0,0 @@
-tff(type, type, '_⁻¹' : $i > $i).
-tff(type, type, '_⁻' : $i > $i).
-
-cnf('commutativity of ∨', axiom,
-    A ∨ B = B ∨ A).
-cnf('associativity of ∨', axiom,
-    A ∨ (B ∨ C) = (A ∨ B) ∨ C).
-cnf('a kind of de Morgan', axiom,
-    (A⁻ ∨ B⁻)⁻ ∨ (A⁻ ∨ B)⁻ = A).
-cnf('definition of ∧', axiom,
-    A ∧ B = (A⁻ ∨ B⁻)⁻).
-cnf('associativity of ;', axiom,
-    A ; (B ; C) = (A ; B) ; C).
-cnf('identity for ;', axiom,
-    A ; '1' = A).
-cnf('distributivity of ; over ∨', axiom,
-    (A ∨ B) ; C = (A ; C) ∨ (B ; C)).
-cnf('involution of ⁻¹', axiom,
-    A⁻¹ ⁻¹ = A).
-cnf('additivity of ⁻¹', axiom,
-    (A ∨ B)⁻¹ = A⁻¹ ∨ B⁻¹).
-cnf('multiplicativity of ⁻¹', axiom,
-    (A ; B)⁻¹ = B⁻¹ ; A⁻¹).
-cnf('cancellativity of ⁻', axiom,
-    (A⁻¹ ; (A ; B)⁻) ∨ B⁻ = B⁻).
-cnf('definition of top', axiom,
-    top = A ∨ A⁻).
-cnf('definition of zero', axiom,
-    zero = A ∧ A⁻).
-cnf(goal, conjecture,
-    ((r1 ; r2) ∧ r3) ∨ ((r1; (r2 ∧ (r1⁻¹ ; r3))) ∧ r3) =
-    (r1 ; (r2 ∧ (r1⁻¹ ; r3))) ∧ r3).
diff --git a/tests/rellat_appendixa.p b/tests/rellat_appendixa.p
deleted file mode 100644
--- a/tests/rellat_appendixa.p
+++ /dev/null
@@ -1,27 +0,0 @@
-% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
-% appendix a. theorem 3.4, clause 7.
-cnf(commutativity, axiom,
-    X ∧ Y = Y ∧ X).
-cnf(associativity, axiom,
-    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
-cnf(commutativity, axiom,
-    X ∨ Y = Y ∨ X).
-cnf(associativity, axiom,
-    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
-cnf(absorption, axiom,
-    X ∨ (X ∧ Y) = X).
-cnf(absorption, axiom,
-    X ∧ (X ∨ Y) = X).
-cnf(definition_of_upme, axiom,
-    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
-cnf(definition_of_lome, axiom,
-    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
-cnf(definition_of_upjo, axiom,
-    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
-cnf(definition_of_lojo, axiom,
-    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
-
-fof(conjecture, conjecture,
-    (![X1, Y1, W]:
-    upme(a ∧ X1,Y1,W) ∨ (Y1 ∧ W) = (((a ∧ X1) ∧ Y1) ∨ W) ∧ (((a ∧ X1) ∧ W) ∨ Y1)) =>
-    upme(a ∧ z1,z2,z3) = lome(a ∧ z1,z2,z3)).
diff --git a/tests/rellat_appendixb.p b/tests/rellat_appendixb.p
deleted file mode 100644
--- a/tests/rellat_appendixb.p
+++ /dev/null
@@ -1,28 +0,0 @@
-% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
-% appendix b. theorem 3.4, clause 8.
-cnf(commutativity, axiom,
-    X ∧ Y = Y ∧ X).
-cnf(associativity, axiom,
-    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
-cnf(commutativity, axiom,
-    X ∨ Y = Y ∨ X).
-cnf(associativity, axiom,
-    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
-cnf(absorption, axiom,
-    X ∨ (X ∧ Y) = X).
-cnf(absorption, axiom,
-    X ∧ (X ∨ Y) = X).
-cnf(definition_of_upme, axiom,
-    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
-cnf(definition_of_lome, axiom,
-    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
-cnf(definition_of_upjo, axiom,
-    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
-cnf(definition_of_lojo, axiom,
-    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
-cnf(rh1, axiom,
-    upme(a ∧ X1,Y1,Z1) ∨ (Y1 ∧ Z1) = (((a ∧ X1) ∧ Y1) ∨ Z1) ∧ (((a ∧ X1) ∧ Z1) ∨ Y1)).
-cnf(rh2, axiom,
-    upme(X,Y,Z) = upme(X,Y,a ∧ Z) ∨ upme(X,Z,a ∧ Y)).
-fof(conjecture, conjecture,
-    upme(a,x2,y2) = upme(a,x2,z2) => upme(x2,y2,z2) = lome(x2,y2,z2)).
diff --git a/tests/rellat_appendixb_easier.p b/tests/rellat_appendixb_easier.p
deleted file mode 100644
--- a/tests/rellat_appendixb_easier.p
+++ /dev/null
@@ -1,30 +0,0 @@
-% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
-% appendix b. theorem 3.4, clause 8, assuming axiom rl1.
-cnf(commutativity, axiom,
-    X ∧ Y = Y ∧ X).
-cnf(associativity, axiom,
-    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
-cnf(commutativity, axiom,
-    X ∨ Y = Y ∨ X).
-cnf(associativity, axiom,
-    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
-cnf(absorption, axiom,
-    X ∨ (X ∧ Y) = X).
-cnf(absorption, axiom,
-    X ∧ (X ∨ Y) = X).
-cnf(definition_of_upme, axiom,
-    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
-cnf(definition_of_lome, axiom,
-    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
-cnf(definition_of_upjo, axiom,
-    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
-cnf(definition_of_lojo, axiom,
-    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
-cnf(rh1, axiom,
-    upme(a ∧ X1,Y1,Z1) ∨ (Y1 ∧ Z1) = (((a ∧ X1) ∧ Y1) ∨ Z1) ∧ (((a ∧ X1) ∧ Z1) ∨ Y1)).
-cnf(rh2, axiom,
-    upme(X,Y,Z) = upme(X,Y,a ∧ Z) ∨ upme(X,Z,a ∧ Y)).
-cnf(rl1, axiom,
-    lome(X,Y,Z) = upme(X,upme(Y,X,Z),upme(Z,X,Y))).
-fof(conjecture, conjecture,
-    upme(a,x2,y2) = upme(a,x2,z2) => upme(x2,y2,z2) = lome(x2,y2,z2)).
diff --git a/tests/rellat_appendixc.p b/tests/rellat_appendixc.p
deleted file mode 100644
--- a/tests/rellat_appendixc.p
+++ /dev/null
@@ -1,30 +0,0 @@
-% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
-% appendix c. theorem 3.4, clause 9.
-cnf(commutativity, axiom,
-    X ∧ Y = Y ∧ X).
-cnf(associativity, axiom,
-    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
-cnf(commutativity, axiom,
-    X ∨ Y = Y ∨ X).
-cnf(associativity, axiom,
-    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
-cnf(absorption, axiom,
-    X ∨ (X ∧ Y) = X).
-cnf(absorption, axiom,
-    X ∧ (X ∨ Y) = X).
-cnf(definition_of_upme, axiom,
-    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
-cnf(definition_of_lome, axiom,
-    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
-cnf(definition_of_upjo, axiom,
-    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
-cnf(definition_of_lojo, axiom,
-    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
-cnf(upme_property_1, axiom,
-    upme(a ∧ X1,Y1,Z1) ∨ (Y1 ∧ Z1) = (((a ∧ X1) ∧ Y1) ∨ Z1) ∧ (((a ∧ X1) ∧ Z1) ∨ Y1)).
-cnf(upme_property_2, axiom,
-    upme(X,Y,Z) = upme(X,Y,a ∧ Z) ∨ upme(X,Z,a ∧ Y)).
-fof(conjecture, conjecture,
-    (upme(a,x2,y2) = upme(a,x2,z2) &
-     upme(a,x2,y2) = upme(a,y2,z2)) =>
-    upjo(x2,y2,z2) = lojo(x2,y2,z2)).
diff --git a/tests/rellat_theorem34_6.p b/tests/rellat_theorem34_6.p
deleted file mode 100644
--- a/tests/rellat_theorem34_6.p
+++ /dev/null
@@ -1,32 +0,0 @@
-% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
-% theorem 3.4, clause 6.
-cnf(commutativity, axiom,
-    X ∧ Y = Y ∧ X).
-cnf(associativity, axiom,
-    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
-cnf(commutativity, axiom,
-    X ∨ Y = Y ∨ X).
-cnf(associativity, axiom,
-    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
-cnf(absorption, axiom,
-    X ∨ (X ∧ Y) = X).
-cnf(absorption, axiom,
-    X ∧ (X ∨ Y) = X).
-cnf(definition_of_upme, axiom,
-    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
-cnf(definition_of_lome, axiom,
-    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
-cnf(definition_of_upjo, axiom,
-    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
-cnf(definition_of_lojo, axiom,
-    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
-cnf(eq1, axiom,
-    upme(a ∧ Z1,Z2,Z3) = lome(a ∧ Z1,Z2,Z3)).
-cnf(qu2, axiom,
-    upme(a,X2,Y2) = upme(a,X2,Z2) => upme(X2,Y2,Z2) = lome(X2,Y2,Z2)).
-fof(rl1, conjecture,
-    lome(x,y,z) =
-    (x∧(y∧(x∨z)))∨(z∧(x∨y))).
-%fof(rl2, conjecture,
-%    t∧(((x∨y)∧(x∨z))∨((u∨w)∧(u∨v))) =
-%    (t∧(((x∨y)∧(x∨z))∨(u∨(w∧v))))∨(t∧(((u∨w)∧(u∨v))∨(x∨(y∧z))))).
diff --git a/tests/rellat_theorem34_6a.p b/tests/rellat_theorem34_6a.p
deleted file mode 100644
--- a/tests/rellat_theorem34_6a.p
+++ /dev/null
@@ -1,29 +0,0 @@
-% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
-% theorem 3.4, clause 6.
-cnf(commutativity, axiom,
-    X ∧ Y = Y ∧ X).
-cnf(associativity, axiom,
-    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
-cnf(commutativity, axiom,
-    X ∨ Y = Y ∨ X).
-cnf(associativity, axiom,
-    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
-cnf(absorption, axiom,
-    X ∨ (X ∧ Y) = X).
-cnf(absorption, axiom,
-    X ∧ (X ∨ Y) = X).
-cnf(definition_of_upme, axiom,
-    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
-cnf(definition_of_lome, axiom,
-    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
-cnf(definition_of_upjo, axiom,
-    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
-cnf(definition_of_lojo, axiom,
-    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
-cnf(eq1, axiom,
-    upme(a ∧ Z1,Z2,Z3) = lome(a ∧ Z1,Z2,Z3)).
-cnf(qu2, axiom,
-    upme(a,X2,Y2) = upme(a,X2,Z2) => upme(X2,Y2,Z2) = lome(X2,Y2,Z2)).
-fof(rl1, conjecture,
-    lome(x,y,z) =
-    x∧((y∧(x∨z))∨(z∧(x∨y)))).
diff --git a/tests/rellat_theorem34_6b.p b/tests/rellat_theorem34_6b.p
deleted file mode 100644
--- a/tests/rellat_theorem34_6b.p
+++ /dev/null
@@ -1,29 +0,0 @@
-% http://www.dcs.bbk.ac.uk/~szabolcs/rellat-jlamp-second-submission-2.pdf
-% theorem 3.4, clause 6.
-cnf(commutativity, axiom,
-    X ∧ Y = Y ∧ X).
-cnf(associativity, axiom,
-    X ∧ (Y ∧ Z) = (X ∧ Y) ∧ Z).
-cnf(commutativity, axiom,
-    X ∨ Y = Y ∨ X).
-cnf(associativity, axiom,
-    X ∨ (Y ∨ Z) = (X ∨ Y) ∨ Z).
-cnf(absorption, axiom,
-    X ∨ (X ∧ Y) = X).
-cnf(absorption, axiom,
-    X ∧ (X ∨ Y) = X).
-cnf(definition_of_upme, axiom,
-    upme(X,Y,Z) = X ∧ (Y ∨ Z)).
-cnf(definition_of_lome, axiom,
-    lome(X,Y,Z) = (X ∧ Y) ∨ (X ∧ Z)).
-cnf(definition_of_upjo, axiom,
-    upjo(X,Y,Z) = (X ∨ Y) ∧ (X ∨ Z)).
-cnf(definition_of_lojo, axiom,
-    lojo(X,Y,Z) = X ∨ (Y ∧ Z)).
-cnf(eq1, axiom,
-    upme(a ∧ Z1,Z2,Z3) = lome(a ∧ Z1,Z2,Z3)).
-cnf(qu2, axiom,
-    upme(a,X2,Y2) = upme(a,X2,Z2) => upme(X2,Y2,Z2) = lome(X2,Y2,Z2)).
-fof(rl2, conjecture,
-    t∧(((x∨y)∧(x∨z))∨((u∨w)∧(u∨v))) =
-    (t∧(((x∨y)∧(x∨z))∨(u∨(w∧v))))∨(t∧(((u∨w)∧(u∨v))∨(x∨(y∧z))))).
diff --git a/tests/ring.p b/tests/ring.p
deleted file mode 100644
--- a/tests/ring.p
+++ /dev/null
@@ -1,9 +0,0 @@
-cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(plus_zero, axiom, '+'('0', X) = X).
-cnf(plus_inv, axiom, '+'(X, '-'(X)) = '0').
-cnf(times_assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
-cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
-cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
-cnf(cube, axiom, X = '*'(X, '*'(X, X))).
-cnf(conjecture, negated_conjecture, '*'(a, b) != '*'(b, a)).
diff --git a/tests/ring2-cancel.p b/tests/ring2-cancel.p
deleted file mode 100644
--- a/tests/ring2-cancel.p
+++ /dev/null
@@ -1,9 +0,0 @@
-cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(plus_zero, axiom, '+'('0', X) = X).
-cnf(plus_inv, axiom, '+'(X, '-'(X)) = '0').
-cnf(times_assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
-cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
-cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
-cnf(power_six, axiom, X = '*'(X, '*'(X, '*'(X, '*'(X, '*'(X, X)))))).
-cnf(conjecture, negated_conjecture, '+'(x, x) != '0').
diff --git a/tests/ring2.p b/tests/ring2.p
deleted file mode 100644
--- a/tests/ring2.p
+++ /dev/null
@@ -1,9 +0,0 @@
-cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(plus_zero, axiom, '+'('0', X) = X).
-cnf(plus_inv, axiom, '+'(X, '-'(X)) = '0').
-cnf(times_assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
-cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
-cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
-cnf(power_six, axiom, X = '*'(X, '*'(X, '*'(X, '*'(X, '*'(X, X)))))).
-cnf(conjecture, negated_conjecture, '*'(a, b) != '*'(b, a)).
diff --git a/tests/ring3.p b/tests/ring3.p
deleted file mode 100644
--- a/tests/ring3.p
+++ /dev/null
@@ -1,9 +0,0 @@
-cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(plus_zero, axiom, '+'('0', X) = X).
-cnf(plus_neg, axiom, '+'(X, '-'(X)) = '0').
-cnf(times_assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
-cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
-cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
-cnf(power_four, axiom, X = '*'(X, '*'(X, '*'(X, X)))).
-cnf(conjecture, negated_conjecture, '*'(a, b) != '*'(b, a)).
diff --git a/tests/ring4.p b/tests/ring4.p
deleted file mode 100644
--- a/tests/ring4.p
+++ /dev/null
@@ -1,9 +0,0 @@
-cnf(plus_comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(plus_assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(plus_zero, axiom, '+'('0', X) = X).
-cnf(plus_inv, axiom, '+'(X, '-'(X)) = '0').
-cnf(times_ssoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
-cnf(distrib, axiom, '*'(X, '+'(Y, Z)) = '+'('*'(X, Y), '*'(X, Z))).
-cnf(distrib, axiom, '*'('+'(X, Y), Z) = '+'('*'(X, Z), '*'(Y, Z))).
-cnf(power_five, axiom, X = '*'(X, '*'(X, '*'(X, '*'(X, X))))).
-cnf(conjecture, negated_conjecture, '*'(a, b) != '*'(b, a)).
diff --git a/tests/rob.p b/tests/rob.p
deleted file mode 100644
--- a/tests/rob.p
+++ /dev/null
@@ -1,7 +0,0 @@
-cnf(commutativity_of_add, axiom, add(X, Y)=add(Y, X)).
-cnf(associativity_of_add, axiom,
-    add(add(X, Y), Z)=add(X, add(Y, Z))).
-cnf(robbins_axiom, axiom,
-    negate(add(negate(add(X, Y)), negate(add(X, negate(Y)))))=X).
-cnf(winker_specialised, conjecture,
-    add(add(x,x), negate(add(negate(add(x,add(x,x))),x))) = add(x,x)).
diff --git a/tests/rob2.p b/tests/rob2.p
deleted file mode 100644
--- a/tests/rob2.p
+++ /dev/null
@@ -1,7 +0,0 @@
-cnf(commutativity_of_add, axiom, add(X, Y)=add(Y, X)).
-cnf(associativity_of_add, axiom,
-    add(add(X, Y), Z)=add(X, add(Y, Z))).
-cnf(robbins_axiom, axiom,
-    negate(add(negate(add(X, Y)), negate(add(X, negate(Y)))))=X).
-fof(winker, conjecture,
-    ?[X,Y]: add(X,Y) = X).
diff --git a/tests/robbins-easy.p b/tests/robbins-easy.p
deleted file mode 100644
--- a/tests/robbins-easy.p
+++ /dev/null
@@ -1,4 +0,0 @@
-cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(funny, axiom, '+'('-'('+'('-'(X), Y)), '-'('+'('-'(X), '-'(Y)))) = X).
-cnf(conjecture, negated_conjecture, '-'('+'('-'('+'(a, b)), '-'('+'(a, '-'(b))))) != a).
diff --git a/tests/robbins.p b/tests/robbins.p
deleted file mode 100644
--- a/tests/robbins.p
+++ /dev/null
@@ -1,4 +0,0 @@
-cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(funny, axiom, '-'('+'('-'('+'(X, Y)), '-'('+'(X, '-'(Y))))) = X).
-cnf(conjecture, negated_conjecture, '-'('-'(a)) != a).
diff --git a/tests/sam.p b/tests/sam.p
deleted file mode 100644
--- a/tests/sam.p
+++ /dev/null
@@ -1,38 +0,0 @@
-cnf(f_assoc, axiom,
-    meet(X,meet(Y,Z)) = meet(meet(X,Y),Z)).
-cnf(f_comm, axiom,
-    meet(X,Y) = meet(Y,X)).
-cnf(f_idem, axiom,
-    meet(X,X) = X).
-cnf(g_assoc, axiom,
-    join(X,join(Y,Z)) = join(join(X,Y),Z)).
-cnf(g_comm, axiom,
-    join(X,Y) = join(Y,X)).
-cnf(g_idem, axiom,
-    join(X,X) = X).
-
-cnf(ax31, axiom,
-    meet(X, join(X,Y)) = X).
-cnf(ax32, axiom,
-    meet(zero, X) = zero).
-cnf(ax33, axiom,
-    join(zero, X) = X).
-cnf(ax34, axiom,
-    join(X, meet(X, Y)) = X).
-cnf(ax35, axiom,
-    meet(one, X) = X).
-cnf(ax36, axiom,
-    join(one, X) = one).
-cnf(ax37, axiom,
-    meet(X,Z) = X =>
-    meet(join(X,Y),Z) = join(X,meet(Y,Z))).
-
-cnf(comp, definition,
-    comp(X,Y) <=> (meet(X,Y) = zero & join(X,Y) = one)).
-
-cnf(premise1, assumption,
-    comp(a, join(c,d))).
-cnf(premise2, assumption,
-    comp(b, join(c,d))).
-cnf(goal, conjecture,
-    meet(join(a,meet(b,c)),join(a,meet(b,d)))=a).
diff --git a/tests/semigroup.p b/tests/semigroup.p
deleted file mode 100644
--- a/tests/semigroup.p
+++ /dev/null
@@ -1,4 +0,0 @@
-cnf(assoc, axiom, '*'(X, '*'(Y, Z)) = '*'('*'(X, Y), Z)).
-cnf(two_three, axiom, '*'(X, X) = '*'(X, '*'(X, X))).
-cnf(twiddle, axiom, '*'('*'(X, X), Y) = '*'(Y, '*'(X, X))).
-cnf(conjecture, negated_conjecture, '*'('*'(a, b), '*'(a, b)) != '*'('*'(a, a), '*'(b, b))).
diff --git a/tests/sudoku.p b/tests/sudoku.p
deleted file mode 100644
--- a/tests/sudoku.p
+++ /dev/null
@@ -1,39 +0,0 @@
-cnf('associativity of ∘', axiom,
-    F ∘ (G ∘ H) = (F ∘ G) ∘ H).
-
-cnf('∘ identity', axiom,
-    id ∘ F = F).
-
-cnf('∘ identity', axiom,
-    F ∘ id = F).
-
-cnf('map functor', axiom,
-    map(F) ∘ map(G) = map(F ∘ G)).
-
-cnf('map functor', axiom,
-    map(id) = id).
-
-cnf('defn pruneBy', axiom,
-    pruneBy(F) = F ∘ (map(pruneRow) ∘ F)).
-
-cnf('defn expand', axiom,
-    expand = product ∘ map(product)).
-
-cnf('expand after boxs', axiom,
-    expand ∘ boxs = map(boxs) ∘ expand).
-
-cnf('filter with boxs', axiom,
-    filter (P ∘ boxs) = map(boxs) ∘ (filter(P) ∘ map(boxs))).
-
-cnf('boxs involution', axiom,
-    boxs ∘ boxs = id).
-
-cnf('filter after product', axiom,
-    filter(all(P)) ∘ product = product ∘ map(filter(P))).
-
-cnf('law of pruneRow', axiom,
-    filter(nodups) ∘ (product ∘ pruneRow) = filter(nodups) ∘ product).
-
-cnf('conjecture', conjecture,
-    filter(all(nodups) ∘ boxs) ∘ (expand ∘ pruneBy(boxs)) =
-    filter(all(nodups) ∘ boxs) ∘ expand).
diff --git a/tests/sudoku2.p b/tests/sudoku2.p
deleted file mode 100644
--- a/tests/sudoku2.p
+++ /dev/null
@@ -1,44 +0,0 @@
-cnf('associativity of ∘', axiom,
-    F ∘ (G ∘ H) = (F ∘ G) ∘ H).
-
-cnf('∘ identity', axiom,
-    id ∘ F = F).
-
-cnf('∘ identity', axiom,
-    F ∘ id = F).
-
-cnf('map functor', axiom,
-    map(F) ∘ map(G) = map(F ∘ G)).
-
-cnf('map functor', axiom,
-    map(id) = id).
-
-cnf('defn pruneBy', axiom,
-    pruneBy(F) = F ∘ (map(pruneRow) ∘ F)).
-
-cnf('defn expand', axiom,
-    expand = product ∘ map(product)).
-
-cnf('expand after boxs', axiom,
-    expand ∘ boxs = map(boxs) ∘ expand).
-
-cnf('filter with boxs', axiom,
-    filter (P ∘ boxs) = map(boxs) ∘ (filter(P) ∘ map(boxs))).
-
-cnf('boxs involution', axiom,
-    boxs ∘ boxs = id).
-
-cnf('filter after product', axiom,
-    filter(all(P)) ∘ product = product ∘ map(filter(P))).
-
-cnf('law of pruneRow', axiom,
-    filter(nodups) ∘ (product ∘ pruneRow) = filter(nodups) ∘ product).
-
-cnf('lhs', axiom,
-    lhs = filter(all(nodups) ∘ boxs) ∘ (expand ∘ pruneBy(boxs))).
-
-cnf('rhs', axiom,
-    rhs = filter(all(nodups) ∘ boxs) ∘ expand).
-
-cnf('conjecture', conjecture,
-    lhs = rhs).
diff --git a/tests/sudoku3.p b/tests/sudoku3.p
deleted file mode 100644
--- a/tests/sudoku3.p
+++ /dev/null
@@ -1,42 +0,0 @@
-cnf('associativity of ∘', axiom,
-    F ∘ (G ∘ H) = (F ∘ G) ∘ H).
-
-cnf('∘ identity', axiom,
-    id ∘ F = F).
-
-cnf('∘ identity', axiom,
-    F ∘ id = F).
-
-cnf('map functor', axiom,
-    map(F) ∘ map(G) = map(F ∘ G)).
-
-cnf('map functor', axiom,
-    map(id) = id).
-
-cnf('defn pruneBy', axiom,
-    pruneBy(F) = F ∘ (map(pruneRow) ∘ F)).
-
-cnf('defn expand', axiom,
-    expand = product ∘ map(product)).
-
-cnf('expand after boxs', axiom,
-    expand ∘ boxs = map(boxs) ∘ expand).
-
-cnf('filter with boxs', axiom,
-    filter (P ∘ boxs) = map(boxs) ∘ (filter(P) ∘ map(boxs))).
-
-cnf('boxs involution', axiom,
-    boxs ∘ boxs = id).
-
-cnf('filter after product', axiom,
-    filter(all(P)) ∘ product = product ∘ map(filter(P))).
-
-cnf('law of pruneRow', axiom,
-    filter(nodups) ∘ (product ∘ pruneRow) = filter(nodups) ∘ product).
-
-cnf('map/filter', axiom,
-    filter(P) ∘ map(F) = map(F) ∘ filter(P ∘ F)).
-
-cnf('conjecture', conjecture,
-    filter(all(nodups) ∘ boxs) ∘ (expand ∘ pruneBy(boxs)) =
-    filter(all(nodups) ∘ boxs) ∘ expand).
diff --git a/tests/sudoku4.p b/tests/sudoku4.p
deleted file mode 100644
--- a/tests/sudoku4.p
+++ /dev/null
@@ -1,45 +0,0 @@
-fof('associativity of ∘', axiom,
-    ![F,G,H]: F ∘ (G ∘ H) = (F ∘ G) ∘ H).
-
-fof('∘ identity', axiom,
-    ![F]: id ∘ F = F).
-
-fof('∘ identity', axiom,
-    ![F]: F ∘ id = F).
-
-fof('map functor', axiom,
-    ![F, G]: map(F) ∘ map(G) = map(F ∘ G)).
-
-fof('map functor', axiom,
-    map(id) = id).
-
-fof('defn pruneBy', axiom,
-    ![F]: pruneBy(F) = F ∘ (map(pruneRow) ∘ F)).
-
-fof('defn expand', axiom,
-    expand = product ∘ map(product)).
-
-fof('expand after boxs', axiom,
-    expand ∘ boxs = map(boxs) ∘ expand).
-
-fof('filter with boxs', axiom,
-    ![P, F]: filter (P ∘ boxs) = map(boxs) ∘ (filter(P) ∘ map(boxs))).
-
-fof('boxs involution', axiom,
-    boxs ∘ boxs = id).
-
-fof('filter after product', axiom,
-    ![P]: filter(all(P)) ∘ product = product ∘ map(filter(P))).
-
-fof('law of pruneRow', axiom,
-    filter(nodups) ∘ (product ∘ pruneRow) = filter(nodups) ∘ product).
-
-fof('map/filter', axiom,
-    ![P, F]: filter(P) ∘ map(F) = map(F) ∘ filter(P ∘ F)).
-
-fof('product/map', axiom,
-    ![F]: product ∘ map(F) = map(map(F)) ∘ product).
-
-fof('conjecture', conjecture,
-    filter(all(nodups) ∘ boxs) ∘ (expand ∘ pruneBy(boxs)) =
-    filter(all(nodups) ∘ boxs) ∘ expand).
diff --git a/tests/sudoku5.p b/tests/sudoku5.p
deleted file mode 100644
--- a/tests/sudoku5.p
+++ /dev/null
@@ -1,42 +0,0 @@
-cnf('associativity of ∘', axiom,
-    F ∘ (G ∘ H) = (F ∘ G) ∘ H).
-
-cnf('∘ identity', axiom,
-    id ∘ F = F).
-
-cnf('∘ identity', axiom,
-    F ∘ id = F).
-
-cnf('map functor', axiom,
-    map(F) ∘ map(G) = map(F ∘ G)).
-
-cnf('map functor', axiom,
-    map(id) = id).
-
-cnf('defn pruneBy', axiom,
-    pruneBy(F) = F ∘ (map(pruneRow) ∘ F)).
-
-cnf('defn expand', axiom,
-    expand = product ∘ map(product)).
-
-cnf('expand after boxs', axiom,
-    expand ∘ boxs = map(boxs) ∘ expand).
-
-cnf('filter with boxs', axiom,
-    filter (P ∘ boxs) = map(boxs) ∘ (filter(P) ∘ map(boxs))).
-
-cnf('boxs involution', axiom,
-    boxs ∘ boxs = id).
-
-cnf('filter after product', axiom,
-    filter(all(P)) ∘ product = product ∘ map(filter(P))).
-
-cnf('law of pruneRow', axiom,
-    filter(nodups) ∘ (product ∘ pruneRow) = filter(nodups) ∘ product).
-
-cnf('product/map', axiom,
-    product ∘ map(F) = map(map(F)) ∘ product).
-
-cnf('conjecture', conjecture,
-    filter(all(nodups) ∘ boxs) ∘ (expand ∘ pruneBy(boxs)) =
-    filter(all(nodups) ∘ boxs) ∘ expand).
diff --git a/tests/sum.p b/tests/sum.p
deleted file mode 100644
--- a/tests/sum.p
+++ /dev/null
@@ -1,30 +0,0 @@
-cnf(plus_comm, axiom,
-    X + Y = Y + X).
-cnf(plus_assoc, axiom,
-    X + (Y + Z) = (X + Y) + Z).
-cnf(times_comm, axiom,
-    X * Y = Y * X).
-cnf(times_assoc, axiom,
-    X * (Y * Z) = (X * Y) * Z).
-cnf(plus_zero, axiom,
-    X + zero = X).
-cnf(times_zero, axiom,
-    X * zero = zero).
-cnf(times_one, axiom,
-    X * one = X).
-cnf(distr, axiom,
-    X * (Y + Z) = (X * Y) + (X * Z)).
-cnf(distr, axiom,
-    (X + Y) * Z = (X * Z) + (Y * Z)).
-cnf(plus_s, axiom,
-    s(X) + Y = s(X+Y)).
-cnf(times_s, axiom,
-    s(X)*Y = Y + (X*Y)).
-cnf(sum_zero, axiom,
-    sum(zero) = zero).
-cnf(sum_s, axiom,
-    sum(s(N)) = s(N) + sum(N)).
-cnf(ih, axiom,
-    sum(a) + sum(a) = a * s(a)).
-cnf(conjecture, conjecture,
-    sum(s(a)) + sum(s(a)) = s(a) * s(s(a))).
diff --git a/tests/union.p b/tests/union.p
deleted file mode 100644
--- a/tests/union.p
+++ /dev/null
@@ -1,9 +0,0 @@
-cnf(elem_union_1, axiom, notelem(X, A) | ~notelem(X, union(A, B))).
-cnf(elem_union_2, axiom, notelem(X, B) | ~notelem(X, union(A, B))).
-cnf(elem_union_3, axiom, notelem(X, union(A, B)) | ~notelem(X, A) | ~notelem(X, B)).
-cnf(elem_equals, axiom, A=B | ~notelem(sK1_elem_equals_X(A, B), A) | ~notelem(sK1_elem_equals_X(A, B), B)).
-cnf(union_commutative, negated_conjecture, union(a, b)!=union(b, a)).
-
-cnf(elem_equals_1, axiom, choice(A,B) = c1 => notelem(sK1_elem_equals_X(A, B), A)).
-cnf(elem_equals_2, axiom, choice(A,B) = c2 => notelem(sK1_elem_equals_X(A, B), B)).
-cnf(elem_equals_3, axiom, choice(A,B) = c3 => A=B).
diff --git a/tests/union2.p b/tests/union2.p
deleted file mode 100644
--- a/tests/union2.p
+++ /dev/null
@@ -1,25 +0,0 @@
-cnf(ifeq_axiom, axiom, ifeq4(A, A, B, C)=B).
-cnf(ifeq_axiom, axiom, ifeq3(A, A, B, C)=B).
-cnf(ifeq_axiom, axiom, ifeq2(A, A, B, C)=B).
-cnf(ifeq_axiom, axiom, ifeq(A, A, B, C)=B).
-cnf(elem_union_1, axiom, ifeq(notelem(X, union(A, B)), true, notelem(X, A), true)=true).
-cnf(elem_union_2, axiom, ifeq(notelem(X, union(A, B)), true, notelem(X, B), true)=true).
-cnf(elem_union_3, axiom, ifeq(notelem(X, B), true, ifeq(notelem(X, A), true, notelem(X, union(A, B)), true), true)=true).
-cnf(elem_equals, axiom, ifeq2(notelem(sK1_elem_equals_X(A, B), B), true, ifeq2(notelem(sK1_elem_equals_X(A, B), A), true, A, B), B)=B).
-%cnf(union_commutative, negated_conjecture, union(a, b)!=union(b, a)).
-%cnf(elem_equals_1, axiom, ifeq3(choice(A, B), c1, notelem(sK1_elem_equals_X(A, B), A), true)=true).
-%cnf(elem_equals_2, axiom, ifeq3(choice(A, B), c2, notelem(sK1_elem_equals_X(A, B), B), true)=true).
-%cnf(elem_equals_3, axiom, ifeq4(choice(A, B), c3, A, B)=B).
-cnf(elem_equals_1, axiom, select(c1, a, d, d) = d).
-cnf(elem_equals_1, axiom, select(c2, d, b, d) = d).
-cnf(elem_equals_1, axiom, select(c3, d, d, c) = d).
-cnf(blah, conjecture, a=d | b=d | c=d).
-cnf(select, axiom, select(C, X, X, X)=X).
-cnf(select, axiom, select(c1, X, Y, Z)=X).
-cnf(select, axiom, select(c2, X, Y, Z)=Y).
-cnf(select, axiom, select(c3, X, Y, Z)=Z).
-
-%select(C, X, Y, Z) = select(C, select(c1, X, Y, Z), select(c2, X, Y, Z), select(c3, X, Y, Z)).
-
-%  d
-%= select(
diff --git a/tests/vbool.p b/tests/vbool.p
deleted file mode 100644
--- a/tests/vbool.p
+++ /dev/null
@@ -1,18 +0,0 @@
-fof(associativity, axiom,
-    ![X, Y, Z]:
-    X ⊕ (Y ⊕ Z) = (X ⊕ Y) ⊕ Z).
-
-fof(commutativity, axiom,
-    ![X, Y]:
-    X ⊕ Y = Y ⊕ X).
-
-fof(idempotence, axiom,
-    ![X]:
-    X ⊕ X = X).
-
-fof(non_injectivity, conjecture,
-    ![A, B]: ?[X]: A ⊕ X = B ⊕ X).
-
-% Examples:
-% plus is commutative, associative, and injective, but not idempotent
-% max is idempotent, commutative, and associativity, but not injective
diff --git a/tests/veroff-short.p b/tests/veroff-short.p
deleted file mode 100644
--- a/tests/veroff-short.p
+++ /dev/null
@@ -1,11 +0,0 @@
-cnf(majority, axiom,
-    f(X,X,Y) = X).
-cnf('2a', axiom,
-    f(X,Y,Z) = f(Z,X,Y)).
-cnf('2b', axiom,
-    f(X,Y,Z) = f(X,Z,Y)).
-cnf(associativity, axiom,
-    f(f(X,W,Y),W,Z) = f(X,W,f(Y,W,Z))).
-
-cnf(dist_long, conjecture,
-    f(f(x,y,z),u,w) = f(x,f(y,u,w),f(z,u,w))).
diff --git a/tests/veroff.p b/tests/veroff.p
deleted file mode 100644
--- a/tests/veroff.p
+++ /dev/null
@@ -1,11 +0,0 @@
-cnf(majority, axiom,
-    f(X,X,Y) = X).
-cnf('2a', axiom,
-    f(X,Y,Z) = f(Z,X,Y)).
-cnf('2b', axiom,
-    f(X,Y,Z) = f(X,Z,Y)).
-cnf(associativity, axiom,
-    f(f(X,W,Y),W,Z) = f(X,W,f(Y,W,Z))).
-
-cnf(dist_long, conjecture,
-    f(f(x,y,z),u,w) = f(f(x,u,w),f(y,u,w),f(z,u,w))).
diff --git a/tests/winker-easy.p b/tests/winker-easy.p
deleted file mode 100644
--- a/tests/winker-easy.p
+++ /dev/null
@@ -1,6 +0,0 @@
-% Needs case split on X < c.
-cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(idem, axiom, '+'(X, X) = X).
-cnf(funny, axiom, '-'('+'('-'('+'(X, Y)), '-'('+'(X, '-'(Y))))) = X).
-cnf(conjecture, negated_conjecture, '+'('-'('+'('-'(a), b)), '-'('+'('-'(a), '-'(b)))) != a).
diff --git a/tests/winker.p b/tests/winker.p
deleted file mode 100644
--- a/tests/winker.p
+++ /dev/null
@@ -1,6 +0,0 @@
-% Needs case split on X < c.
-cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(idem_c, axiom, '+'(c, c) = c).
-cnf(funny, axiom, '-'('+'('-'('+'(X, Y)), '-'('+'(X, '-'(Y))))) = X).
-cnf(conjecture, negated_conjecture, '+'('-'('+'('-'(a), b)), '-'('+'('-'(a), '-'(b)))) != a).
diff --git a/tests/winker2.p b/tests/winker2.p
deleted file mode 100644
--- a/tests/winker2.p
+++ /dev/null
@@ -1,6 +0,0 @@
-% Needs case split on X < c.
-cnf(comm, axiom, '+'(X, Y) = '+'(Y, X)).
-cnf(assoc, axiom, '+'(X, '+'(Y, Z)) = '+'('+'(X, Y), Z)).
-cnf(plus_c_d, axiom, '+'(c, d) = c).
-cnf(funny, axiom, '-'('+'('-'('+'(X, Y)), '-'('+'(X, '-'(Y))))) = X).
-cnf(conjecture, negated_conjecture, '+'('-'('+'('-'(a), b)), '-'('+'('-'(a), '-'(b)))) != a).
diff --git a/tests/wos.p b/tests/wos.p
deleted file mode 100644
--- a/tests/wos.p
+++ /dev/null
@@ -1,6 +0,0 @@
-cnf(a, axiom,
-    prod(inv(prod(inv(prod(inv(prod(Xl,X2)),prod(X2,Xl))),prod(inv(prod(Z,Y)), prod(Z,inv(prod(prod(V,inv(X)),inv(Y))))))),X) = V).
-
-%fof(associativity, conjecture, prod(a,prod(b,c)) = prod(prod(a,b),c)).
-fof(identity_and_inverse, conjecture,  ?[X]: (![Y]: prod(X,Y)=Y & ![Y]: prod(Y, inv(Y)) = X)).
-%fof(commutativity, conjecture, prod(a,b) = prod(b,a)).
diff --git a/tests/y-easy.p b/tests/y-easy.p
deleted file mode 100644
--- a/tests/y-easy.p
+++ /dev/null
@@ -1,4 +0,0 @@
-fof(k_def, axiom, ![X, Y]: (k @ X) @ Y = X).
-fof(s_def, axiom, ![X, Y, Z]: ((s @ X) @ Y) @ Z = (X @ Z) @ (Y @ Z)).
-fof(i_def, axiom, ![X]: i @ X = X).
-fof(conjecture, conjecture, ?[Y]: ![F]: Y @ F = F @ (Y @ F)).
diff --git a/tests/y-encoded.p b/tests/y-encoded.p
deleted file mode 100644
--- a/tests/y-encoded.p
+++ /dev/null
@@ -1,5 +0,0 @@
-cnf(ifeq_axiom, axiom, ifeq(A, A, B, C)=B).
-cnf(k_def, axiom, '@'('@'(k, X), Y)=X).
-cnf(s_def, axiom, '@'('@'('@'(s, X), Y), Z)='@'('@'(X, Z), '@'(Y, Z))).
-cnf(conjecture, negated_conjecture, ifeq('@'(Y, f(Y)), '@'(f(Y), '@'(Y, f(Y))), a, b)=b).
-cnf(goal, negated_conjecture, a!=b).
diff --git a/tests/y-i.p b/tests/y-i.p
deleted file mode 100644
--- a/tests/y-i.p
+++ /dev/null
@@ -1,4 +0,0 @@
-fof(k_def, axiom, ![X, Y]: (k @ X) @ Y = X).
-fof(s_def, axiom, ![X, Y, Z]: ((s @ X) @ Y) @ Z = (X @ Z) @ (Y @ Z)).
-fof(i_def, axiom, ![X]: i @ X = X).
-fof(conjecture, conjecture, ?[Y]: ![F]: Y @ F = F @ (Y @ F)).
diff --git a/tests/y.p b/tests/y.p
deleted file mode 100644
--- a/tests/y.p
+++ /dev/null
@@ -1,3 +0,0 @@
-fof(k_def, axiom, ![X, Y]: (k @ X) @ Y = X).
-fof(s_def, axiom, ![X, Y, Z]: ((s @ X) @ Y) @ Z = (X @ Z) @ (Y @ Z)).
-fof(conjecture, conjecture, ?[Y]: ![F]: Y @ F = F @ (Y @ F)).
diff --git a/twee.cabal b/twee.cabal
--- a/twee.cabal
+++ b/twee.cabal
@@ -1,15 +1,15 @@
+cabal-version:       2.2
 name:                twee
-version:             2.6.1
+version:             2.7.1
 synopsis:            An equational theorem prover
-homepage:            http://github.com/nick8325/twee
-license:             BSD3
+homepage:            https://twee.smallbone.se
+license:             BSD-3-Clause
 license-file:        LICENSE
 author:              Nick Smallbone
 maintainer:          nicsma@chalmers.se
 category:            Theorem Provers
 build-type:          Simple
-cabal-version:       >=1.10
-extra-source-files:  README.md tests/*.p misc/*.hs misc/*.pl misc/static-libstdc++
+extra-source-files:  README.md examples/*.p misc/*.hs misc/*.pl
 description:
    Twee is an experimental equational theorem prover based on
    Knuth-Bendix completion.
@@ -20,65 +20,87 @@
    fail to terminate if they are false.
    .
    The input problem should be in TPTP format (see
-   http://www.tptp.org). You can use types and quantifiers, but apart
+   https://www.tptp.org). You can use types and quantifiers, but apart
    from that the problem must be equational.
 
 source-repository head
   type:     git
-  location: https://github.com/nick8325/twee.git
-  branch:   master
+  location: https://codeberg.org/nick8325/twee
+  branch:   main
 
 flag static
   description: Build a static binary.
   default: False
   manual: True
 
-flag static-cxx
-  description: Build a binary which statically links against libstdc++.
-  default: False
-  manual: True
-
 flag parallel
   description: Build a special parallel version of Twee.
   default: False
   manual: True
 
-executable twee
-  --if flag(parallel)
-  --  main-is: ParallelMain.hs
-  --  build-depends: async, unix
-  --  c-sources: executable/link.c
-  --else
-  main-is: Main.hs
+flag rtsopts
+  description: Enable -rtsopts (e.g. for setting maximum memory use.)
+  default: False
+  manual: True
 
+common executable-stuff
   hs-source-dirs:      executable
-  other-modules:       SequentialMain
   default-language:    Haskell2010
   build-depends:       base < 5,
-                       twee-lib == 2.6.1,
+                       twee-lib == 2.7.1,
                        containers,
                        pretty,
                        split,
-                       jukebox >= 0.5.9,
+                       jukebox == 0.5.15,
                        ansi-terminal >= 0.9,
-                       symbol
+                       symbol,
+                       hashable,
+                       bytestring,
+                       binary,
+                       process
+  other-modules:       SequentialMain
   ghc-options:         -W -fno-warn-incomplete-patterns
 
   if flag(static)
     ghc-options: -optl -static
 
-  if flag(static-cxx)
-    ghc-options: -pgml misc/static-libstdc++
+  if flag(rtsopts)
+    ghc-options: -rtsopts
 
+executable twee
+  import: executable-stuff
+  main-is: Main.hs
+
+executable twee-lpo
+  import: executable-stuff
+  main-is: Main.hs
+  cpp-options: -DUSE_LPO
+
+executable parallel-twee
+  import: executable-stuff
+  if !flag(parallel)
+    buildable: False
+
+  main-is: ParallelMain.hs
+  build-depends: async, unix
+  c-sources: executable/link.c
+
 Test-Suite twee-test
     type: exitcode-stdio-1.0
     Default-language: Haskell2010
     hs-source-dirs:
-        misc
-    main-is: Test.hs
-    build-depends: base < 5, QuickCheck, twee-lib == 2.6.1, containers, pretty
+        test
+    main-is: Main.hs
+    build-depends: base < 5, QuickCheck, twee-lib == 2.7, containers, pretty, tasty, tasty-quickcheck, hashable, binary, bytestring
+    other-modules:
+        Common
+        Index
+        Nest
+        Ordering
+        Serial
+        TermOrder
+        Terms
     ghc-options:
       -threaded
-      -rtsopts
       -feager-blackholing
-      -with-rtsopts=-N4
+      -with-rtsopts=-N
