Section PROPOSITONAL_LOGIC.
Definition propLetter : Set := nat.
Inductive formula : Set :=
| AtomF (i : propLetter) : formula
| ContradictionF : formula
| NegationF (p1 : formula) : formula
| ConjunctionF (p1 : formula) (p2 : formula) : formula
| DisjunctionF (p1 : formula) (p2 : formula) : formula
| ImplicationF (p1 : formula) (p2 : formula) : formula
| BiconditionalF (p1 : formula) (p2 : formula) : formula.
#[global]
Instance propLetter_hasEqDec : hasEqDec propLetter :=
Nat.eq_dec.
#[global]
Instance formula_hasEqDec
: hasEqDec formula.
Definition is_structure (Gamma : ensemble formula) : Prop :=
forall p : formula, p \in Gamma <-> evalFormula (E.preimage AtomF Gamma) p.
Proof with repeat ((now left) || right).
eapply NegationE, ContradictionI.
- eapply DisjunctionI2, NegationI, ContradictionI.
+ eapply DisjunctionI1, ByAssumption...
+ eapply ByAssumption...
- eapply ByAssumption...
Qed.
Proof with eauto.
revert Gamma' SUBSET. induction INFERS; ii.
- eapply ByAssumption with (C := C)...
- eapply ContradictionI with (A := A)...
- eapply ContradictionE with (A := A)...
- eapply NegationI with (A := A)...
- eapply NegationE with (A := A)...
- eapply ConjunctionI with (A := A) (B := B)...
- eapply ConjunctionE1 with (A := A) (B := B)...
- eapply ConjunctionE2 with (A := A) (B := B)...
- eapply DisjunctionI1 with (A := A) (B := B)...
- eapply DisjunctionI2 with (A := A) (B := B)...
- eapply DisjunctionE with (A := A) (B := B) (C := C)...
- eapply ImplicationI with (A := A) (B := B)...
- eapply ImplicationE with (A := A) (B := B)...
- eapply BiconditionalI with (A := A) (B := B)...
- eapply BiconditionalE1 with (A := A) (B := B)...
- eapply BiconditionalE2 with (A := A) (B := B)...
Qed.
Fixpoint depth (p : formula) {struct p} : nat :=
match p with
| AtomF i => 0
| ContradictionF => 1
| NegationF p1 => S (depth p1)
| ConjunctionF p1 p2 => S (max (depth p1) (depth p2))
| DisjunctionF p1 p2 => S (max (depth p1) (depth p2))
| ImplicationF p1 p2 => S (max (depth p1) (depth p2))
| BiconditionalF p1 p2 => S (max (depth p1) (depth p2))
end.
#[local] Notation plus6 i := (S (S (S (S (S (S i)))))).
Fixpoint enumFormula' (rk : nat) (seed0 : nat) {struct rk} : formula :=
match rk with
| O => AtomF seed0
| S rk' =>
let seed1 := fst (cp seed0) in
let piece := snd (cp seed0) in
let seed2 := fst (cp seed1) in
let seed3 := snd (cp seed1) in
match piece with
| 0 => ContradictionF
| 1 => NegationF (enumFormula' rk' seed1)
| 2 => ConjunctionF (enumFormula' rk' seed2) (enumFormula' rk' seed3)
| 3 => DisjunctionF (enumFormula' rk' seed2) (enumFormula' rk' seed3)
| 4 => ImplicationF (enumFormula' rk' seed2) (enumFormula' rk' seed3)
| 5 => BiconditionalF (enumFormula' rk' seed2) (enumFormula' rk' seed3)
| plus6 i => AtomF i
end
end.
#[local]
Tactic Notation "tac_aux1" :=
match goal with
| [ H : cp ?seed = ?rhs |- _ ] => rewrite H; simpl
end.
#[local]
Tactic Notation "tac_aux2" :=
match goal with
| [ H : enumFormula' ?rk ?seed = ?p |- _ ] => rewrite <- H
end.
#[local]
Tactic Notation "tac" :=
unfold enumFormula'; repeat tac_aux1; repeat tac_aux2; eauto.
Proof with tac.
revert p rk RANK_LE.
pose proof (claim1 := fun x: nat => fun y: nat => fun z: nat => proj2 (cp_spec x y z)).
induction p as [i | | p1 IH1 | p1 IH1 p2 IH2 | p1 IH1 p2 IH2 | p1 IH1 p2 IH2 | p1 IH1 p2 IH2]; simpl.
{ intros [ | r'] H.
- exists (i)...
- assert (H0: cp (sum_from_0_to (0 + plus6 i) + plus6 i) = (0, plus6 i)) by now apply claim1.
exists (sum_from_0_to (0 + plus6 i) + plus6 i)...
}
all: intros r H; set (rk := pred r); (assert (H0: S rk = r) by lia); rewrite <- H0.
{ set (piece := 0).
exists (piece)...
}
{ set (piece := 1).
assert (H1: depth p1 <= rk) by lia.
pose proof (IH1 rk H1) as [seed2 H2].
assert (H3: cp (sum_from_0_to (seed2 + piece) + piece) = (seed2, piece)) by now apply claim1.
exists (sum_from_0_to (seed2 + piece) + piece)...
}
{ set (piece := 2).
assert (H1: max (depth p1) (depth p2) <= rk) by lia.
assert (H2: depth p1 <= rk) by lia.
assert (H3: depth p2 <= rk) by lia.
pose proof (IH1 rk H2) as [seed2 H4].
pose proof (IH2 rk H3) as [seed3 H5].
assert (H6: cp (sum_from_0_to ((sum_from_0_to (seed2 + seed3) + seed3) + piece) + piece) = (sum_from_0_to (seed2 + seed3) + seed3, piece)) by now apply claim1.
assert (H7: cp (sum_from_0_to (seed2 + seed3) + seed3) = (seed2, seed3)) by now apply claim1.
exists (sum_from_0_to ((sum_from_0_to (seed2 + seed3) + seed3) + piece) + piece)...
}
{ set (piece := 3).
assert (H1: max (depth p1) (depth p2) <= rk) by lia.
assert (H2: depth p1 <= rk) by lia.
assert (H3: depth p2 <= rk) by lia.
pose proof (IH1 rk H2) as [seed2 H4].
pose proof (IH2 rk H3) as [seed3 H5].
assert (H6: cp (sum_from_0_to ((sum_from_0_to (seed2 + seed3) + seed3) + piece) + piece) = (sum_from_0_to (seed2 + seed3) + seed3, piece)) by now apply claim1.
assert (H7: cp (sum_from_0_to (seed2 + seed3) + seed3) = (seed2, seed3)) by now apply claim1.
exists (sum_from_0_to ((sum_from_0_to (seed2 + seed3) + seed3) + piece) + piece)...
}
{ set (piece := 4).
assert (H1: max (depth p1) (depth p2) <= rk) by lia.
assert (H2: depth p1 <= rk) by lia.
assert (H3: depth p2 <= rk) by lia.
pose proof (IH1 rk H2) as [seed2 H4].
pose proof (IH2 rk H3) as [seed3 H5].
assert (H6: cp (sum_from_0_to ((sum_from_0_to (seed2 + seed3) + seed3) + piece) + piece) = (sum_from_0_to (seed2 + seed3) + seed3, piece)) by now apply claim1.
assert (H7: cp (sum_from_0_to (seed2 + seed3) + seed3) = (seed2, seed3)) by now apply claim1.
exists (sum_from_0_to ((sum_from_0_to (seed2 + seed3) + seed3) + piece) + piece)...
}
{ set (piece := 5).
assert (H1: max (depth p1) (depth p2) <= rk) by lia.
assert (H2: depth p1 <= rk) by lia.
assert (H3: depth p2 <= rk) by lia.
pose proof (IH1 rk H2) as [seed2 H4].
pose proof (IH2 rk H3) as [seed3 H5].
assert (H6: cp (sum_from_0_to ((sum_from_0_to (seed2 + seed3) + seed3) + piece) + piece) = (sum_from_0_to (seed2 + seed3) + seed3, piece)) by now apply claim1.
assert (H7: cp (sum_from_0_to (seed2 + seed3) + seed3) = (seed2, seed3)) by now apply claim1.
exists (sum_from_0_to ((sum_from_0_to (seed2 + seed3) + seed3) + piece) + piece)...
}
Qed.
Definition enumFormula (seed : nat) : formula :=
let rk := fst (cp seed) in
let seed0 := snd (cp seed) in
enumFormula' rk seed0.

Theorem enumFormula_good (p : formula)
: { seed : nat | enumFormula seed = p }.