Definition checkSubFormulaTrace : nat -> nat :=
  evalStrongRec 0
    (fun trace recs : nat =>
     let v := cTriplePi1 (cTriplePi1 trace) in
     let s := cTriplePi2 (cTriplePi1 trace) in
     let input := cTriplePi3 (cTriplePi1 trace) in
     let output := cTriplePi2 trace in
     let rest := cTriplePi3 trace in
     let type := cPairPi1 input in
     switchPR type
       (switchPR (pred type)
          (switchPR (pred (pred type))
             (switchPR (pred (pred (pred type)))
                (charFunction 2 beq_nat output
                   (cPair type (codeSubTerms (cPairPi2 input) v s)))
                (switchPR
                   (charFunction 2 beq_nat v (cPairPi1 (cPairPi2 input)))
                   (charFunction 2 beq_nat input output)
                   (switchPR
                      (codeIn (cPairPi1 (cPairPi2 input)) (codeFreeVarTerm s))
                      (let nv :=
                         codeNewVar
                           (S
                              (cPair v
                                 (codeApp (codeFreeVarTerm s)
                                    (codeFreeVarFormula
                                       (cPairPi2 (cPairPi2 input)))))) in
                       charFunction 0
                         (beq_nat output
                            (cPair 3 (cPair nv (cTriplePi2 (cPairPi2 rest)))) &&
                          (beq_nat (cTriple v s (cTriplePi2 (cPairPi1 rest)))
                             (cTriplePi1 (cPairPi2 rest)) &&
                           beq_nat
                             (cTriple (cPairPi1 (cPairPi2 input))
                                (cPair 0 nv) (cPairPi2 (cPairPi2 input)))
                             (cTriplePi1 (cPairPi1 rest)))) *
                       (codeNth (trace - S (cPairPi1 rest)) recs *
                        codeNth (trace - S (cPairPi2 rest)) recs))
                      (charFunction 0
                         (beq_nat output
                            (cPair 3
                               (cPair (cPairPi1 (cPairPi2 input))
                                  (cTriplePi2 rest))) &&
                          beq_nat (cTriple v s (cPairPi2 (cPairPi2 input)))
                            (cTriplePi1 rest)) *
                       codeNth (trace - S rest) recs))))
             (charFunction 0
                (beq_nat output (cPair 2 (cTriplePi2 rest)) &&
                 beq_nat (cTriple v s (cPairPi2 input)) (cTriplePi1 rest)) *
              codeNth (trace - S rest) recs))
          (charFunction 0
             (beq_nat output
                (cPair 1
                   (cPair (cTriplePi2 (cPairPi1 rest))
                      (cTriplePi2 (cPairPi2 rest)))) &&
              (beq_nat (cTriple v s (cPairPi1 (cPairPi2 input)))
                 (cTriplePi1 (cPairPi1 rest)) &&
               beq_nat (cTriple v s (cPairPi2 (cPairPi2 input)))
                 (cTriplePi1 (cPairPi2 rest)))) *
           (codeNth (trace - S (cPairPi1 rest)) recs *
            codeNth (trace - S (cPairPi2 rest)) recs)))
       (charFunction 2 beq_nat output
          (cPair 0
             (cPair (codeSubTerm (cPairPi1 (cPairPi2 input)) v s)
                (codeSubTerm (cPairPi2 (cPairPi2 input)) v s))))).Definition makeTraceImp (f1 : fol.Formula L)
  (f1rec : nat * fol.Term L -> nat) (f2 : fol.Formula L)
  (f2rec : nat * fol.Term L -> nat) (p : nat * fol.Term L) : nat :=
  let v := fst p in
  let s := snd p in
  cTriple (cTriple v (codeTerm s) (codeFormula (impH L f1 f2)))
    (codeFormula (substituteFormula L (impH L f1 f2) v s))
    (cPair (f1rec p) (f2rec p)).Definition makeTraceNot (f : fol.Formula L) (frec : nat * fol.Term L -> nat)
  (p : nat * fol.Term L) : nat :=
  let v := fst p in
  let s := snd p in
  cTriple (cTriple v (codeTerm s) (codeFormula (notH L f)))
    (codeFormula (substituteFormula L (notH L f) v s)) 
    (frec p).Definition makeTraceForall (n : nat) (f : fol.Formula L)
  (rec : forall b : fol.Formula L,
         lt_depth L b (forallH L n f) -> nat * fol.Term L -> nat)
  (p : nat * fol.Term L) : nat.Definition makeTrace : fol.Formula L -> nat * fol.Term L -> nat :=
  Formula_depth_rec2 L (fun _ : fol.Formula L => nat * fol.Term L -> nat)
    (fun (t t0 : fol.Term L) (p : nat * fol.Term L) =>
     let v := fst p in
     let s := snd p in
     cTriple (cTriple v (codeTerm s) (codeFormula (equal L t t0)))
       (codeFormula (substituteFormula L (equal L t t0) v s)) 0)
    (fun (r : Relations L) t (p : nat * fol.Term L) =>
     let v := fst p in
     let s := snd p in
     cTriple (cTriple v (codeTerm s) (codeFormula (atomic L r t)))
       (codeFormula (substituteFormula L (atomic L r t) v s)) 0) makeTraceImp
    makeTraceNot makeTraceForall.

(* Specifications: *)
Lemma makeTraceImpNice : forall (f2 g : fol.Formula L) (z1 z2 : nat * fol.Term L -> nat), (forall q : nat * fol.Term L, z1 q = z2 q) -> forall z3 z4 : nat * fol.Term L -> nat, (forall q : nat * fol.Term L, z3 q = z4 q) -> forall q : nat * fol.Term L, makeTraceImp f2 z1 g z3 q = makeTraceImp f2 z2 g z4 q.
Lemma makeTraceNotNice : forall (f2 : fol.Formula L) (z1 z2 : nat * fol.Term L -> nat), (forall q : nat * fol.Term L, z1 q = z2 q) -> forall q : nat * fol.Term L, makeTraceNot f2 z1 q = makeTraceNot f2 z2 q.
Lemma makeTraceForallNice : forall (v0 : nat) (a : fol.Formula L) (z1 z2 : forall b : fol.Formula L, lt_depth L b (forallH L v0 a) -> nat * fol.Term L -> nat), (forall (b : fol.Formula L) (q : lt_depth L b (forallH L v0 a)) (r : nat * fol.Term L), z1 b q r = z2 b q r) -> forall q : nat * fol.Term L, makeTraceForall v0 a z1 q = makeTraceForall v0 a z2 q.