Import ListNotations.
Now we are ready to revisit the tautology solver we saw last time. We will
also broaden the scope of the tactic to include formulas whose truth is
not syntactically apparent. We will want to allow injection of arbitrary
formulas, like we allowed arbitrary monoid expressions in the last example.
Since we are working in a richer theory, it is important to be able to use
equalities between different injected formulas. For instance, we cannot
prove P -> P
by translating the formula into a value like
Imp (Var P) (Var P)
, because a Gallina function has no way of comparing the
two P
s for equality.
We introduce a synonym for how we name variables: natural numbers.
Definition propvar := nat. Inductive formula : Set := | Atomic : propvar -> formula | Truth : formula | Falsehood : formula | And : formula -> formula -> formula | Or : formula -> formula -> formula | Imp : formula -> formula -> formula.
Now we can define our denotation function. First, a type of truth-value assignments to propositional variables:
Definition asgn := nat -> Prop. Fixpoint formulaDenote (atomics : asgn) (f : formula) : Prop := match f with | Atomic v => atomics v | Truth => True | Falsehood => False | And f1 f2 => formulaDenote atomics f1 /\ formulaDenote atomics f2 | Or f1 f2 => formulaDenote atomics f1 \/ formulaDenote atomics f2 | Imp f1 f2 => formulaDenote atomics f1 -> formulaDenote atomics f2 end. Require Import ListSet. Section my_tauto. Variable atomics : asgn.
Now we are ready to define some helpful functions based on the ListSet
module of the standard library, which (unsurprisingly) presents a view of
lists as sets.
The eq_nat_dec
below is a richly typed equality test on nat
s.
See SubsetTypes.v for a review.
Definition add (s : set propvar) (v : propvar) := set_add eq_nat_dec v s.
We define what it means for all members of a variable set to represent true propositions, and we prove some lemmas about this notion.
Fixpoint allTrue (s : set propvar) : Prop := match s with | nil => True | v :: s' => atomics v /\ allTrue s' end.atomics: asgnforall (v : nat) (s : set propvar), allTrue s -> atomics v -> allTrue (add s v)induction s; simpl; intuition; match goal with | [ |- context[if ?E then _ else _] ] => destruct E end; simpl; intuition. Qed.atomics: asgnforall (v : nat) (s : set propvar), allTrue s -> atomics v -> allTrue (add s v)atomics: asgnforall (v : propvar) (s : set propvar), allTrue s -> set_In v s -> atomics vinduction s; simpl; intros; intuition congruence. Qed.atomics: asgnforall (v : propvar) (s : set propvar), allTrue s -> set_In v s -> atomics v
Now we can write a function forward
that implements deconstruction of
hypotheses, expanding a compound formula into a set of sets of atomic
formulas covering all possible cases introduced with use of Or
. To
handle consideration of multiple cases, the function takes in a
continuation argument (advanced functional-programming feature that often
puzzles novices, so don't worry if it takes a while to digest!), which will
be called once for each case.
Fixpoint forward (known : set propvar) (hyp : formula) (cont : set propvar -> bool) : bool := match hyp with | Atomic v => cont (add known v) | Truth => cont known | Falsehood => true | And h1 h2 => forward known h1 (fun known' => forward known' h2 cont) | Or h1 h2 => forward known h1 cont && forward known h2 cont | Imp _ _ => cont known end.
Some examples might help get the idea across.
A backward
function implements analysis of the final goal. It calls
forward
to handle implications.
Fixpoint backward (known : set propvar) (f : formula) : bool := match f with | Atomic v => if In_dec eq_nat_dec v known then true else false | Truth => true | Falsehood => false | And f1 f2 => backward known f1 && backward known f2 | Or f1 f2 => backward known f1 || backward known f2 | Imp f1 f2 => forward known f1 (fun known' => backward known' f2) end.
Examples:
End my_tauto. Hint Resolve allTrue_add : core.forall (atomics : asgn) (hyp f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp -> formulaDenote atomics fforall (atomics : asgn) (hyp f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp -> formulaDenote atomics fatomics: asgn
p: propvar
f: formula
known: set propvar
cont: set propvar -> bool
H: cont (add known p) = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: atomics pformulaDenote atomics fatomics: asgn
f: formula
known: set propvar
cont: set propvar -> bool
H: cont known = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: TrueformulaDenote atomics fatomics: asgn
f: formula
known: set propvar
cont: set propvar -> bool
H: true = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: FalseformulaDenote atomics fatomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: forward known hyp1 (fun known' : set propvar => forward known' hyp2 cont) = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: formulaDenote atomics hyp1 /\ formulaDenote atomics hyp2formulaDenote atomics fatomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: forward known hyp1 cont && forward known hyp2 cont = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: formulaDenote atomics hyp1 \/ formulaDenote atomics hyp2formulaDenote atomics fatomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: cont known = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: formulaDenote atomics hyp1 -> formulaDenote atomics hyp2formulaDenote atomics fatomics: asgn
p: propvar
f: formula
known: set propvar
cont: set propvar -> bool
H: cont (add known p) = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: atomics pformulaDenote atomics fatomics: asgn
f: formula
known: set propvar
cont: set propvar -> bool
H: cont known = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: TrueformulaDenote atomics fatomics: asgn
f: formula
known: set propvar
cont: set propvar -> bool
H: true = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: FalseformulaDenote atomics fatomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: forward known hyp1 (fun known' : set propvar => forward known' hyp2 cont) = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: formulaDenote atomics hyp1 /\ formulaDenote atomics hyp2formulaDenote atomics fatomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: forward known hyp1 cont = true
H3: forward known hyp2 cont = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: formulaDenote atomics hyp1 \/ formulaDenote atomics hyp2formulaDenote atomics fatomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: cont known = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H2: formulaDenote atomics hyp1 -> formulaDenote atomics hyp2formulaDenote atomics fatomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: forward known hyp1 (fun known' : set propvar => forward known' hyp2 cont) = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H3: formulaDenote atomics hyp1
H4: formulaDenote atomics hyp2formulaDenote atomics fatomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: forward known hyp1 (fun known' : set propvar => forward known' hyp2 cont) = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H3: formulaDenote atomics hyp1
H4: formulaDenote atomics hyp2formulaDenote atomics fintros; eapply IHhyp2; eauto; eauto. } Qed.atomics: asgn
hyp1, hyp2: formula
IHhyp1: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp1 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp1 -> formulaDenote atomics f
IHhyp2: forall (f : formula) (known : set propvar) (cont : set propvar -> bool), forward known hyp2 cont = true -> (forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f) -> allTrue atomics known -> formulaDenote atomics hyp2 -> formulaDenote atomics f
f: formula
known: set propvar
cont: set propvar -> bool
H: forward known hyp1 (fun known' : set propvar => forward known' hyp2 cont) = true
H0: forall known' : set propvar, allTrue atomics known' -> cont known' = true -> formulaDenote atomics f
H1: allTrue atomics known
H3: formulaDenote atomics hyp1
H4: formulaDenote atomics hyp2forall known' : set propvar, allTrue atomics known' -> (fun known'0 : set propvar => forward known'0 hyp2 cont) known' = true -> formulaDenote atomics fforall (atomics : asgn) (f : formula) (known : set propvar), backward known f = true -> allTrue atomics known -> formulaDenote atomics fforall (atomics : asgn) (f : formula) (known : set propvar), backward known f = true -> allTrue atomics known -> formulaDenote atomics fatomics: asgn
p: propvar
known: set propvar
H: (if in_dec Nat.eq_dec p known then true else false) = true
H0: allTrue atomics knownatomics patomics: asgn
known: set propvar
H: false = true
H0: allTrue atomics knownFalseatomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: backward known f1 && backward known f2 = true
H0: allTrue atomics knownformulaDenote atomics f1atomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: backward known f1 && backward known f2 = true
H0: allTrue atomics knownformulaDenote atomics f2atomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: backward known f1 || backward known f2 = true
H0: allTrue atomics knownformulaDenote atomics f1 \/ formulaDenote atomics f2atomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: forward known f1 (fun known' : set propvar => backward known' f2) = true
H0: allTrue atomics known
H1: formulaDenote atomics f1formulaDenote atomics f2atomics: asgn
p: propvar
known: set propvar
i: In p known
H: true = true
H0: allTrue atomics knownatomics patomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: backward known f1 = true
H1: backward known f2 = true
H0: allTrue atomics knownformulaDenote atomics f1atomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: backward known f1 = true
H1: backward known f2 = true
H0: allTrue atomics knownformulaDenote atomics f2atomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: backward known f1 = true
H0: allTrue atomics knownformulaDenote atomics f1 \/ formulaDenote atomics f2atomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: backward known f2 = true
H0: allTrue atomics knownformulaDenote atomics f1 \/ formulaDenote atomics f2atomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: forward known f1 (fun known' : set propvar => backward known' f2) = true
H0: allTrue atomics known
H1: formulaDenote atomics f1formulaDenote atomics f2atomics: asgn
p: propvar
known: set propvar
i: In p known
H: true = true
H0: allTrue atomics knownatomics patomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: forward known f1 (fun known' : set propvar => backward known' f2) = true
H0: allTrue atomics known
H1: formulaDenote atomics f1formulaDenote atomics f2eapply allTrue_In; unfold set_In; eauto.atomics: asgn
p: propvar
known: set propvar
i: In p known
H: true = true
H0: allTrue atomics knownatomics patomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: forward known f1 (fun known' : set propvar => backward known' f2) = true
H0: allTrue atomics known
H1: formulaDenote atomics f1formulaDenote atomics f2intros; eapply IHf2; eauto; eauto. Qed.atomics: asgn
f1, f2: formula
IHf1: forall known : set propvar, backward known f1 = true -> allTrue atomics known -> formulaDenote atomics f1
IHf2: forall known : set propvar, backward known f2 = true -> allTrue atomics known -> formulaDenote atomics f2
known: set propvar
H: forward known f1 (fun known' : set propvar => backward known' f2) = true
H0: allTrue atomics known
H1: formulaDenote atomics f1forall known' : set propvar, allTrue atomics known' -> (fun known'0 : set propvar => backward known'0 f2) known' = true -> formulaDenote atomics f2forall f : formula, backward [] f = true -> forall atomics : asgn, formulaDenote atomics fforall f : formula, backward [] f = true -> forall atomics : asgn, formulaDenote atomics fapply backward_ok' with (known := []); simpl; eauto. Qed.f: formula
H: backward [] f = true
atomics: asgnformulaDenote atomics f
Find the position of an element in a list.
Ltac position x ls :=
match ls with
| [] => constr:(@None nat)
| x :: _ => constr:(Some 0)
| _ :: ?ls' =>
let p := position x ls' in
match p with
| None => p
| Some ?n => constr:(Some (S n))
end
end.
Compute a duplicate-free list of all variables in P
, combining it with
acc
.
Ltac vars_in P acc :=
match P with
| True => acc
| False => acc
| ?Q1 /\ ?Q2 =>
let acc' := vars_in Q1 acc in
vars_in Q2 acc'
| ?Q1 \/ ?Q2 =>
let acc' := vars_in Q1 acc in
vars_in Q2 acc'
| ?Q1 -> ?Q2 =>
let acc' := vars_in Q1 acc in
vars_in Q2 acc'
| _ =>
let pos := position P acc in
match pos with
| Some _ => acc
| None => constr:(P :: acc)
end
end.
Reification of formula P
, with a pregenerated list vars
of variables it
may mention
Ltac reify_tauto' P vars :=
match P with
| True => Truth
| False => Falsehood
| ?Q1 /\ ?Q2 =>
let q1 := reify_tauto' Q1 vars in
let q2 := reify_tauto' Q2 vars in
constr:(And q1 q2)
| ?Q1 \/ ?Q2 =>
let q1 := reify_tauto' Q1 vars in
let q2 := reify_tauto' Q2 vars in
constr:(Or q1 q2)
| ?Q1 -> ?Q2 =>
let q1 := reify_tauto' Q1 vars in
let q2 := reify_tauto' Q2 vars in
constr:(Imp q1 q2)
| _ =>
let pos := position P vars in
match pos with
| Some ?pos' => constr:(Atomic pos')
end
end.
Our final tactic implementation is now fairly straightforward. First, we
intro
all quantifiers that do not bind Prop
s. Then we reify. Finally,
we call the verified procedure through a lemma.
Ltac my_tauto :=
repeat match goal with
| [ |- forall x : ?P, _ ] =>
match type of P with
| Prop => fail 1
| _ => intro
end
end;
match goal with
| [ |- ?P ] =>
let vars := vars_in P (@nil Prop) in
let p := reify_tauto' P vars in
change (formulaDenote (nth_default False vars) p)
end;
apply backward_ok; reflexivity.
A few examples demonstrate how the tactic works:
Truemy_tauto. Qed.Trueforall x y : nat, x = y -> x = ymy_tauto. Qed.forall x y : nat, x = y -> x = y
Crucially, both instances of x = y
are represented with the same variable
0.
forall x y z : nat, x < y /\ y > z \/ y > z /\ x < S y -> y > z /\ (x < y \/ x < S y)my_tauto. Qed.forall x y z : nat, x < y /\ y > z \/ y > z /\ x < S y -> y > z /\ (x < y \/ x < S y)
Our goal contained three distinct atomic formulas, and we see that a three-element environment is generated.
It can be interesting to observe differences between the level of repetition
in proof terms generated by my_tauto
and tauto
for especially trivial
theorems.
True /\ True /\ True /\ True /\ True /\ True /\ False -> Falsemy_tauto. Qed.True /\ True /\ True /\ True /\ True /\ True /\ False -> FalseTrue /\ True /\ True /\ True /\ True /\ True /\ False -> Falsetauto. Qed.True /\ True /\ True /\ True /\ True /\ True /\ False -> False
The traditional tauto
tactic introduces a quadratic blow-up in the size of
the proof term, whereas proofs produced by my_tauto
always have linear
size.