From Coq Require Import Setoid Morphisms.

Set Implicit Arguments.

Opaque iff.

Ltac morph eq :=
  compute; intros; rewrite !eq;
  repeat match goal with H: _ <-> _ |- _ => rewrite H;clear H end;
  reflexivity.

Inductive or2 ( A1  A2 :Prop) : Prop :=
| or2_1 : A1 -> or2  A1  A2
| or2_2 : A2 -> or2  A1  A2
.

Lemma or2_equiv: forall  A1  A2 , or2  A1  A2  <-> A1  \/ A2 .
Proof. intros.
split.

intros H.
destruct H.
left. assumption.
right.  assumption.
intros H.
destruct H. constructor 1. exact H.
constructor 2. exact H.

Qed.

Inductive or3 ( A1  A2  A3 :Prop) : Prop :=
| or3_1 : A1 -> or3  A1  A2  A3
| or3_2 : A2 -> or3  A1  A2  A3
| or3_3 : A3 -> or3  A1  A2  A3
.

Lemma or3_equiv: forall  A1  A2  A3 , or3  A1  A2  A3  <-> A1  \/ A2  \/ A3 .
Proof. intros.
split.

intros H.
destruct H.
left. assumption.
right. left. assumption.
right. right. assumption.
intros H.
destruct H. constructor 1. exact H.
destruct H. constructor 2. exact H.
constructor 3. exact H.

Qed.

Global Instance or3_morph : Proper (iff ==> iff ==> iff ==> iff) or3.

Proof. morph or3_equiv. Qed.

Inductive or4 ( A1  A2  A3  A4 :Prop) : Prop :=
| or4_1 : A1 -> or4  A1  A2  A3  A4
| or4_2 : A2 -> or4  A1  A2  A3  A4
| or4_3 : A3 -> or4  A1  A2  A3  A4
| or4_4 : A4 -> or4  A1  A2  A3  A4
.

Lemma or4_equiv: forall  A1  A2  A3  A4 , or4  A1  A2  A3  A4  <-> A1  \/ A2  \/ A3  \/ A4 .
Proof. intros.
split.

intros H.
rewrite <- or3_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. left. exact H.
constructor 3. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or3_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.

Qed.

Global Instance or4_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff) or4.

Proof. morph or4_equiv. Qed.

Inductive or5 ( A1  A2  A3  A4  A5 :Prop) : Prop :=
| or5_1 : A1 -> or5  A1  A2  A3  A4  A5
| or5_2 : A2 -> or5  A1  A2  A3  A4  A5
| or5_3 : A3 -> or5  A1  A2  A3  A4  A5
| or5_4 : A4 -> or5  A1  A2  A3  A4  A5
| or5_5 : A5 -> or5  A1  A2  A3  A4  A5
.

Lemma or5_equiv: forall  A1  A2  A3  A4  A5 , or5  A1  A2  A3  A4  A5  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5 .
Proof. intros.
split.

intros H.
rewrite <- or4_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. left. exact H.
constructor 4. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or4_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.

Qed.

Global Instance or5_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff) or5.

Proof. morph or5_equiv. Qed.

Inductive or6 ( A1  A2  A3  A4  A5  A6 :Prop) : Prop :=
| or6_1 : A1 -> or6  A1  A2  A3  A4  A5  A6
| or6_2 : A2 -> or6  A1  A2  A3  A4  A5  A6
| or6_3 : A3 -> or6  A1  A2  A3  A4  A5  A6
| or6_4 : A4 -> or6  A1  A2  A3  A4  A5  A6
| or6_5 : A5 -> or6  A1  A2  A3  A4  A5  A6
| or6_6 : A6 -> or6  A1  A2  A3  A4  A5  A6
.

Lemma or6_equiv: forall  A1  A2  A3  A4  A5  A6 , or6  A1  A2  A3  A4  A5  A6  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6 .
Proof. intros.
split.

intros H.
rewrite <- or5_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. left. exact H.
constructor 5. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or5_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.

Qed.

Global Instance or6_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or6.

Proof. morph or6_equiv. Qed.

Inductive or7 ( A1  A2  A3  A4  A5  A6  A7 :Prop) : Prop :=
| or7_1 : A1 -> or7  A1  A2  A3  A4  A5  A6  A7
| or7_2 : A2 -> or7  A1  A2  A3  A4  A5  A6  A7
| or7_3 : A3 -> or7  A1  A2  A3  A4  A5  A6  A7
| or7_4 : A4 -> or7  A1  A2  A3  A4  A5  A6  A7
| or7_5 : A5 -> or7  A1  A2  A3  A4  A5  A6  A7
| or7_6 : A6 -> or7  A1  A2  A3  A4  A5  A6  A7
| or7_7 : A7 -> or7  A1  A2  A3  A4  A5  A6  A7
.

Lemma or7_equiv: forall  A1  A2  A3  A4  A5  A6  A7 , or7  A1  A2  A3  A4  A5  A6  A7  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7 .
Proof. intros.
split.

intros H.
rewrite <- or6_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. left. exact H.
constructor 6. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or6_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.

Qed.

Global Instance or7_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or7.

Proof. morph or7_equiv. Qed.

Inductive or8 ( A1  A2  A3  A4  A5  A6  A7  A8 :Prop) : Prop :=
| or8_1 : A1 -> or8  A1  A2  A3  A4  A5  A6  A7  A8
| or8_2 : A2 -> or8  A1  A2  A3  A4  A5  A6  A7  A8
| or8_3 : A3 -> or8  A1  A2  A3  A4  A5  A6  A7  A8
| or8_4 : A4 -> or8  A1  A2  A3  A4  A5  A6  A7  A8
| or8_5 : A5 -> or8  A1  A2  A3  A4  A5  A6  A7  A8
| or8_6 : A6 -> or8  A1  A2  A3  A4  A5  A6  A7  A8
| or8_7 : A7 -> or8  A1  A2  A3  A4  A5  A6  A7  A8
| or8_8 : A8 -> or8  A1  A2  A3  A4  A5  A6  A7  A8
.

Lemma or8_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8 , or8  A1  A2  A3  A4  A5  A6  A7  A8  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8 .
Proof. intros.
split.

intros H.
rewrite <- or7_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. left. exact H.
constructor 7. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or7_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.

Qed.

Global Instance or8_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or8.

Proof. morph or8_equiv. Qed.

Inductive or9 ( A1  A2  A3  A4  A5  A6  A7  A8  A9 :Prop) : Prop :=
| or9_1 : A1 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
| or9_2 : A2 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
| or9_3 : A3 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
| or9_4 : A4 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
| or9_5 : A5 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
| or9_6 : A6 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
| or9_7 : A7 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
| or9_8 : A8 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
| or9_9 : A9 -> or9  A1  A2  A3  A4  A5  A6  A7  A8  A9
.

Lemma or9_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9 , or9  A1  A2  A3  A4  A5  A6  A7  A8  A9  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9 .
Proof. intros.
split.

intros H.
rewrite <- or8_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. left. exact H.
constructor 8. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or8_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.

Qed.

Global Instance or9_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or9.

Proof. morph or9_equiv. Qed.

Inductive or10 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10 :Prop) : Prop :=
| or10_1 : A1 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_2 : A2 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_3 : A3 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_4 : A4 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_5 : A5 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_6 : A6 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_7 : A7 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_8 : A8 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_9 : A9 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
| or10_10 : A10 -> or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
.

Lemma or10_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10 , or10  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10 .
Proof. intros.
split.

intros H.
rewrite <- or9_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. left. exact H.
constructor 9. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or9_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.

Qed.

Global Instance or10_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or10.

Proof. morph or10_equiv. Qed.

Inductive or11 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11 :Prop) : Prop :=
| or11_1 : A1 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_2 : A2 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_3 : A3 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_4 : A4 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_5 : A5 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_6 : A6 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_7 : A7 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_8 : A8 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_9 : A9 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_10 : A10 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
| or11_11 : A11 -> or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11
.

Lemma or11_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11 , or11  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11 .
Proof. intros.
split.

intros H.
rewrite <- or10_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. left. exact H.
constructor 10. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or10_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.

Qed.

Global Instance or11_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or11.

Proof. morph or11_equiv. Qed.

Inductive or12 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12 :Prop) : Prop :=
| or12_1 : A1 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_2 : A2 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_3 : A3 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_4 : A4 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_5 : A5 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_6 : A6 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_7 : A7 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_8 : A8 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_9 : A9 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_10 : A10 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_11 : A11 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
| or12_12 : A12 -> or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12
.

Lemma or12_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12 , or12  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12 .
Proof. intros.
split.

intros H.
rewrite <- or11_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. left. exact H.
constructor 11. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or11_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.

Qed.

Global Instance or12_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or12.

Proof. morph or12_equiv. Qed.

Inductive or13 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13 :Prop) : Prop :=
| or13_1 : A1 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_2 : A2 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_3 : A3 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_4 : A4 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_5 : A5 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_6 : A6 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_7 : A7 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_8 : A8 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_9 : A9 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_10 : A10 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_11 : A11 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_12 : A12 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
| or13_13 : A13 -> or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13
.

Lemma or13_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13 , or13  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13 .
Proof. intros.
split.

intros H.
rewrite <- or12_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. left. exact H.
constructor 12. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or12_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.

Qed.

Global Instance or13_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or13.

Proof. morph or13_equiv. Qed.

Inductive or14 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14 :Prop) : Prop :=
| or14_1 : A1 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_2 : A2 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_3 : A3 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_4 : A4 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_5 : A5 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_6 : A6 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_7 : A7 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_8 : A8 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_9 : A9 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_10 : A10 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_11 : A11 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_12 : A12 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_13 : A13 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
| or14_14 : A14 -> or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14
.

Lemma or14_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14 , or14  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14 .
Proof. intros.
split.

intros H.
rewrite <- or13_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. left. exact H.
constructor 13. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or13_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.

Qed.

Global Instance or14_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or14.

Proof. morph or14_equiv. Qed.

Inductive or15 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15 :Prop) : Prop :=
| or15_1 : A1 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_2 : A2 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_3 : A3 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_4 : A4 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_5 : A5 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_6 : A6 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_7 : A7 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_8 : A8 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_9 : A9 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_10 : A10 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_11 : A11 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_12 : A12 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_13 : A13 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_14 : A14 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
| or15_15 : A15 -> or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15
.

Lemma or15_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15 , or15  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15 .
Proof. intros.
split.

intros H.
rewrite <- or14_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. left. exact H.
constructor 14. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or14_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.

Qed.

Global Instance or15_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or15.

Proof. morph or15_equiv. Qed.

Inductive or16 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16 :Prop) : Prop :=
| or16_1 : A1 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_2 : A2 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_3 : A3 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_4 : A4 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_5 : A5 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_6 : A6 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_7 : A7 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_8 : A8 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_9 : A9 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_10 : A10 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_11 : A11 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_12 : A12 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_13 : A13 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_14 : A14 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_15 : A15 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
| or16_16 : A16 -> or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16
.

Lemma or16_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16 , or16  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16 .
Proof. intros.
split.

intros H.
rewrite <- or15_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. left. exact H.
constructor 15. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or15_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.

Qed.

Global Instance or16_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or16.

Proof. morph or16_equiv. Qed.

Inductive or17 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17 :Prop) : Prop :=
| or17_1 : A1 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_2 : A2 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_3 : A3 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_4 : A4 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_5 : A5 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_6 : A6 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_7 : A7 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_8 : A8 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_9 : A9 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_10 : A10 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_11 : A11 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_12 : A12 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_13 : A13 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_14 : A14 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_15 : A15 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_16 : A16 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
| or17_17 : A17 -> or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17
.

Lemma or17_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17 , or17  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17 .
Proof. intros.
split.

intros H.
rewrite <- or16_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. left. exact H.
constructor 16. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or16_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.

Qed.

Global Instance or17_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or17.

Proof. morph or17_equiv. Qed.

Inductive or18 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18 :Prop) : Prop :=
| or18_1 : A1 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_2 : A2 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_3 : A3 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_4 : A4 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_5 : A5 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_6 : A6 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_7 : A7 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_8 : A8 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_9 : A9 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_10 : A10 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_11 : A11 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_12 : A12 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_13 : A13 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_14 : A14 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_15 : A15 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_16 : A16 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_17 : A17 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
| or18_18 : A18 -> or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18
.

Lemma or18_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18 , or18  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17  \/ A18 .
Proof. intros.
split.

intros H.
rewrite <- or17_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. left. exact H.
constructor 17. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or17_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.

Qed.

Global Instance or18_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or18.

Proof. morph or18_equiv. Qed.

Inductive or19 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19 :Prop) : Prop :=
| or19_1 : A1 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_2 : A2 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_3 : A3 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_4 : A4 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_5 : A5 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_6 : A6 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_7 : A7 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_8 : A8 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_9 : A9 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_10 : A10 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_11 : A11 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_12 : A12 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_13 : A13 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_14 : A14 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_15 : A15 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_16 : A16 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_17 : A17 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_18 : A18 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
| or19_19 : A19 -> or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19
.

Lemma or19_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19 , or19  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17  \/ A18  \/ A19 .
Proof. intros.
split.

intros H.
rewrite <- or18_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. left. exact H.
constructor 18. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or18_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.

Qed.

Global Instance or19_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or19.

Proof. morph or19_equiv. Qed.

Inductive or20 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20 :Prop) : Prop :=
| or20_1 : A1 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_2 : A2 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_3 : A3 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_4 : A4 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_5 : A5 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_6 : A6 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_7 : A7 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_8 : A8 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_9 : A9 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_10 : A10 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_11 : A11 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_12 : A12 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_13 : A13 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_14 : A14 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_15 : A15 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_16 : A16 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_17 : A17 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_18 : A18 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_19 : A19 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
| or20_20 : A20 -> or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20
.

Lemma or20_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20 , or20  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17  \/ A18  \/ A19  \/ A20 .
Proof. intros.
split.

intros H.
rewrite <- or19_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. left. exact H.
constructor 19. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or19_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.

Qed.

Global Instance or20_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or20.

Proof. morph or20_equiv. Qed.

Inductive or21 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21 :Prop) : Prop :=
| or21_1 : A1 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_2 : A2 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_3 : A3 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_4 : A4 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_5 : A5 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_6 : A6 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_7 : A7 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_8 : A8 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_9 : A9 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_10 : A10 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_11 : A11 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_12 : A12 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_13 : A13 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_14 : A14 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_15 : A15 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_16 : A16 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_17 : A17 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_18 : A18 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_19 : A19 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_20 : A20 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
| or21_21 : A21 -> or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21
.

Lemma or21_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21 , or21  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17  \/ A18  \/ A19  \/ A20  \/ A21 .
Proof. intros.
split.

intros H.
rewrite <- or20_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. left. exact H.
constructor 20. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or20_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. exact H.

Qed.

Global Instance or21_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or21.

Proof. morph or21_equiv. Qed.

Inductive or22 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22 :Prop) : Prop :=
| or22_1 : A1 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_2 : A2 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_3 : A3 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_4 : A4 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_5 : A5 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_6 : A6 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_7 : A7 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_8 : A8 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_9 : A9 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_10 : A10 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_11 : A11 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_12 : A12 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_13 : A13 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_14 : A14 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_15 : A15 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_16 : A16 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_17 : A17 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_18 : A18 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_19 : A19 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_20 : A20 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_21 : A21 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
| or22_22 : A22 -> or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22
.

Lemma or22_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22 , or22  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17  \/ A18  \/ A19  \/ A20  \/ A21  \/ A22 .
Proof. intros.
split.

intros H.
rewrite <- or21_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. left. exact H.
constructor 21. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or21_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. exact H.
constructor 22. exact H.

Qed.

Global Instance or22_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or22.

Proof. morph or22_equiv. Qed.

Inductive or23 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23 :Prop) : Prop :=
| or23_1 : A1 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_2 : A2 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_3 : A3 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_4 : A4 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_5 : A5 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_6 : A6 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_7 : A7 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_8 : A8 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_9 : A9 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_10 : A10 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_11 : A11 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_12 : A12 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_13 : A13 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_14 : A14 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_15 : A15 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_16 : A16 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_17 : A17 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_18 : A18 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_19 : A19 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_20 : A20 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_21 : A21 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_22 : A22 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
| or23_23 : A23 -> or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23
.

Lemma or23_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23 , or23  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17  \/ A18  \/ A19  \/ A20  \/ A21  \/ A22  \/ A23 .
Proof. intros.
split.

intros H.
rewrite <- or22_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. exact H.
constructor 22. left. exact H.
constructor 22. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or22_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. exact H.
constructor 22. exact H.
constructor 23. exact H.

Qed.

Global Instance or23_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or23.

Proof. morph or23_equiv. Qed.

Inductive or24 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24 :Prop) : Prop :=
| or24_1 : A1 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_2 : A2 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_3 : A3 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_4 : A4 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_5 : A5 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_6 : A6 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_7 : A7 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_8 : A8 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_9 : A9 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_10 : A10 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_11 : A11 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_12 : A12 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_13 : A13 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_14 : A14 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_15 : A15 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_16 : A16 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_17 : A17 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_18 : A18 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_19 : A19 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_20 : A20 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_21 : A21 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_22 : A22 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_23 : A23 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
| or24_24 : A24 -> or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24
.

Lemma or24_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24 , or24  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17  \/ A18  \/ A19  \/ A20  \/ A21  \/ A22  \/ A23  \/ A24 .
Proof. intros.
split.

intros H.
rewrite <- or23_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. exact H.
constructor 22. exact H.
constructor 23. left. exact H.
constructor 23. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or23_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. exact H.
constructor 22. exact H.
constructor 23. exact H.
constructor 24. exact H.

Qed.

Global Instance or24_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or24.

Proof. morph or24_equiv. Qed.

Inductive or25 ( A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25 :Prop) : Prop :=
| or25_1 : A1 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_2 : A2 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_3 : A3 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_4 : A4 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_5 : A5 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_6 : A6 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_7 : A7 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_8 : A8 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_9 : A9 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_10 : A10 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_11 : A11 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_12 : A12 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_13 : A13 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_14 : A14 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_15 : A15 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_16 : A16 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_17 : A17 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_18 : A18 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_19 : A19 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_20 : A20 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_21 : A21 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_22 : A22 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_23 : A23 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_24 : A24 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
| or25_25 : A25 -> or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25
.

Lemma or25_equiv: forall  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25 , or25  A1  A2  A3  A4  A5  A6  A7  A8  A9  A10  A11  A12  A13  A14  A15  A16  A17  A18  A19  A20  A21  A22  A23  A24  A25  <-> A1  \/ A2  \/ A3  \/ A4  \/ A5  \/ A6  \/ A7  \/ A8  \/ A9  \/ A10  \/ A11  \/ A12  \/ A13  \/ A14  \/ A15  \/ A16  \/ A17  \/ A18  \/ A19  \/ A20  \/ A21  \/ A22  \/ A23  \/ A24  \/ A25 .
Proof. intros.
split.

intros H.
rewrite <- or24_equiv.
destruct H.
constructor 1. exact H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. exact H.
constructor 22. exact H.
constructor 23. exact H.
constructor 24. left. exact H.
constructor 24. right. exact H.
intros H.
destruct H.
constructor 1. exact H.
rewrite <- or24_equiv in H.
destruct H.
constructor 2. exact H.
constructor 3. exact H.
constructor 4. exact H.
constructor 5. exact H.
constructor 6. exact H.
constructor 7. exact H.
constructor 8. exact H.
constructor 9. exact H.
constructor 10. exact H.
constructor 11. exact H.
constructor 12. exact H.
constructor 13. exact H.
constructor 14. exact H.
constructor 15. exact H.
constructor 16. exact H.
constructor 17. exact H.
constructor 18. exact H.
constructor 19. exact H.
constructor 20. exact H.
constructor 21. exact H.
constructor 22. exact H.
constructor 23. exact H.
constructor 24. exact H.
constructor 25. exact H.

Qed.

Global Instance or25_morph : Proper (iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff ==> iff) or25.

Proof. morph or25_equiv. Qed.


(* week-07_binary-trees.v *)
(* Functional Programming and Proving (YSC3236) 2017-2018, Sem1 *)
(* Olivier Danvy <danvy@yale-nus.edu.sg> *)
(* Version of Tues 10 Oct 2017 *)

(* ********** *)

(*
   name: Jeremy Yew
   student ID number: A0156262H
   e-mail address: jeremy.yew@u.yale-nus.edu.sg
*)

(* ********** *)

(* Paraphernalia: *)

Ltac unfold_tactic name := intros; unfold name; (* fold name; *) reflexivity.

Require Import Arith Bool.

(* ********** *)

Inductive binary_tree : Type :=
| Leaf : binary_tree
| Node : binary_tree -> nat -> binary_tree -> binary_tree.

Fixpoint left_balanced (t : binary_tree) : bool :=
  match t with
  | Leaf =>
    true
  | Node t1 n t2 =>
    match t2 with
    | Leaf =>
      left_balanced t1
    | Node _ _ _ =>
      false
    end
  end.

Lemma unfold_left_balanced_Leaf :
  left_balanced Leaf = true.
Proof.
  unfold_tactic left_balanced.
Qed.

(* generic unfold lemma: *)

Lemma unfold_left_balanced_Node :
  forall (t1 : binary_tree)
         (n : nat)
         (t2 : binary_tree),
    left_balanced (Node t1 n t2) = match t2 with
                                   | Leaf =>
                                     left_balanced t1
                                   | Node _ _ _ =>
                                     false
                                   end.
Proof.
  unfold_tactic left_balanced.
Qed.

(* specific unfold lemmas: *)

Lemma unfold_left_balanced_Node_Leaf :
  forall (t1 : binary_tree)
         (n : nat),
  left_balanced (Node t1 n Leaf) = left_balanced t1.
Proof.
  unfold_tactic left_balanced.
Qed.

Lemma unfold_left_balanced_Node_Node :
  forall (t1 : binary_tree)
         (n : nat)
         (t1': binary_tree)
         (n' : nat)
         (t2': binary_tree),
  left_balanced (Node t1 n (Node t1' n' t2')) =  false.
Proof.
  unfold_tactic left_balanced.
Qed.

(* ********** *)

Inductive left_binary_tree : Type :=
| Left_Leaf : left_binary_tree
| Left_Node : left_binary_tree -> nat -> left_binary_tree.

Fixpoint embed_left_binary_tree_into_binary_tree (lt : left_binary_tree) : binary_tree :=
  match lt with
  | Left_Leaf =>
    Leaf
  | Left_Node lt n =>
    Node (embed_left_binary_tree_into_binary_tree lt) n Leaf
  end.

Fixpoint project_binary_tree_into_left_binary_tree (t : binary_tree) : option left_binary_tree :=
  match t with
  | Leaf =>
    Some Left_Leaf
  | Node t1 n t2 =>
    match t2 with
    | Leaf =>
      (match project_binary_tree_into_left_binary_tree t1 with
       | Some lt1 =>
         Some (Left_Node lt1 n)
       | None =>
         None
       end)
    | Node _ _ _ =>
      None
    end
  end.

(* ********** *)

Lemma unfold_embed_Left_Leaf :
  embed_left_binary_tree_into_binary_tree Left_Leaf = Leaf.
Proof.
  unfold_tactic embed_left_binary_tree_into_binary_tree.
Qed.

Lemma unfold_embed_Left_Node :
   forall (lt : left_binary_tree) (n : nat),
     embed_left_binary_tree_into_binary_tree (Left_Node lt n)
     = Node (embed_left_binary_tree_into_binary_tree lt) n Leaf.
Proof.
  unfold_tactic embed_left_binary_tree_into_binary_tree.
Qed.

Lemma unfold_project_Leaf :
  project_binary_tree_into_left_binary_tree Leaf = Some Left_Leaf.
Proof.
  unfold_tactic project_binary_tree_into_left_binary_tree.
Qed.

(* generic unfold lemma: *)

Lemma unfold_project_Node :
  forall (t1 t2 : binary_tree) (n: nat),
    project_binary_tree_into_left_binary_tree (Node t1 n t2) =
    match t2 with
    | Leaf =>
      (match project_binary_tree_into_left_binary_tree t1 with
       | Some lt1 =>
         Some (Left_Node lt1 n)
       | None =>
         None
       end)
    | Node _ _ _ =>
      None
    end.
Proof.
  unfold_tactic project_binary_tree_into_left_binary_tree.
Qed.

(*specific unfold_lemma*)
Lemma unfold_project_Node_Leaf_Leaf :
  forall (n : nat),
    project_binary_tree_into_left_binary_tree (Node Leaf n Leaf)
    = Some (Left_Node Left_Leaf n).
Proof.
  unfold_tactic project_binary_tree_into_left_binary_tree.
Qed.

Lemma unfold_project_Node_Tree_Leaf :
  forall (t1 : binary_tree) (n: nat),
    project_binary_tree_into_left_binary_tree (Node t1 n Leaf)
    = match project_binary_tree_into_left_binary_tree t1 with
       | Some lt1 =>
         Some (Left_Node lt1 n)
       | None =>
         None
       end.
Proof.
  unfold_tactic project_binary_tree_into_left_binary_tree.
Qed.

(***************)
Proposition projecting_an_embedded_binary_tree :
  forall lt : left_binary_tree,
    project_binary_tree_into_left_binary_tree
      (embed_left_binary_tree_into_binary_tree lt)
    = Some lt.
Proof.
  intro lt.
  induction lt as [ | lt IH_lt].
  rewrite -> unfold_embed_Left_Leaf.
  rewrite -> unfold_project_Leaf.
  reflexivity.

  rewrite -> (unfold_embed_Left_Node lt n).
  rewrite -> (unfold_project_Node_Tree_Leaf).

  rewrite -> IH_lt.
  reflexivity.
  Qed.

(************)
Lemma about_left_balanced_Node:
  forall (t1 t2 : binary_tree) (n : nat),
  left_balanced (Node t1 n t2) = true -> t2 = Leaf.
Proof.
  intros t1 t2 n.
  case t2.
  intro A.
  reflexivity.

  intros b n0 b0.
  rewrite -> (unfold_left_balanced_Node_Node t1 n b n0 b0).
  intro A.
  discriminate A.
Qed.

(******)
(*For posterity.*)
Lemma project_t1_with_existential_lt1_initial :
  forall (t1 : binary_tree) (n: nat),
    exists lt1 : left_binary_tree,
      project_binary_tree_into_left_binary_tree t1 = Some lt1
      ->
      project_binary_tree_into_left_binary_tree (Node t1 n Leaf)
      = Some (Left_Node lt1 n).
Proof.
  Abort.
(*****)

Lemma project_t1_with_existential_lt1 :
  forall (t1 : binary_tree) (n: nat),
    (exists lt1 : left_binary_tree,
      project_binary_tree_into_left_binary_tree t1 = Some lt1)
      ->
      (exists lt : left_binary_tree,
      project_binary_tree_into_left_binary_tree (Node t1 n Leaf)
      = Some lt).
Proof.
  intros t n H.
  destruct H.
  rewrite -> (unfold_project_Node_Tree_Leaf).
  rewrite -> H.
  exists (Left_Node x n).
  reflexivity.
Qed.

Proposition projectable :
  forall t : binary_tree,
    left_balanced t = true ->
    exists lt : left_binary_tree,
      project_binary_tree_into_left_binary_tree t = Some lt.
Proof.
  intros t H_lb.
  induction t.

  rewrite -> unfold_project_Leaf.
  exists Left_Leaf.
  reflexivity.

  assert (H_A := about_left_balanced_Node).
  assert (H_t2_Leaf := H_lb).
  apply H_A in H_t2_Leaf.
  rewrite -> (H_t2_Leaf).
  rewrite -> H_t2_Leaf in H_lb.
  rewrite -> unfold_left_balanced_Node_Leaf in H_lb.
  apply IHt1 in H_lb.
  assert (H_e_lt1 := project_t1_with_existential_lt1).
  apply (H_e_lt1 t1 n) in H_lb.
  apply H_lb.
Qed.
(* ********** *)

(* end of week-07_binary-trees.v *)


Set Implicit Arguments.
Set Strict Implicit.
Require Export Setoid.
Require Omega.

(** * Sets.v: Definition of sets as predicates over a type A *)

Section sets.
Variable A : Type.
Variable decA : forall x y :A, {x=y}+{x<>y}.

Definition set := A -> Prop.
Definition full : set := fun (x:A) => True.
Definition empty : set := fun (x:A) => False.
Definition add (a:A) (P:set) : set := fun (x:A) => x=a \/ (P x).
Definition singl (a:A) :set := fun (x:A) => x=a.
Definition union (P Q:set) :set := fun (x:A) => (P x) \/ (Q x).
Definition compl (P:set) :set := fun (x:A) => ~P x.
Definition inter (P Q:set) :set := fun (x:A) => (P x) /\ (Q x).
Definition rem (a:A) (P:set) :set := fun (x:A) => x<>a /\ (P x).

(** ** Equivalence *)
Definition eqset (P Q:set) := forall (x:A), P x <-> Q x.

Implicit Arguments full [].
Implicit Arguments empty [].

Lemma eqset_refl : forall P:set, eqset P P.
unfold eqset; intuition.
Save.

Lemma eqset_sym : forall P Q:set, eqset P Q -> eqset Q P.
unfold eqset; firstorder.
Save.

Lemma eqset_trans : forall P Q R:set,
   eqset P Q -> eqset Q R -> eqset P R.
unfold eqset; firstorder.
Save.

Hint Resolve eqset_refl.
Hint Immediate eqset_sym.

(** ** Setoid structure *)
Lemma set_setoid : Setoid_Theory set eqset.
split; red; auto.
exact eqset_trans.
Qed.

Add Setoid set eqset set_setoid as Set_setoid.

Add Morphism add : eqset_add.
unfold eqset,add; firstorder.
Save.

Add Morphism rem : eqset_rem.
unfold eqset,rem; firstorder.
Save.
Hint Resolve eqset_add eqset_rem.

Add Morphism union : eqset_union.
unfold eqset,union; firstorder.
Save.
Hint Immediate eqset_union.

Lemma eqset_union_left :
  forall P1 Q P2,
   eqset P1 P2 -> eqset (union P1 Q) (union P2 Q).
auto.
Save.

Lemma eqset_union_right :
  forall P Q1 Q2 ,
   eqset Q1 Q2 -> eqset (union P Q1) (union P Q2).
auto.
Save.

Hint Resolve eqset_union_left eqset_union_right.

Add Morphism inter : eqset_inter.
unfold eqset,inter; firstorder.
Save.
Hint Immediate eqset_inter.

Add Morphism compl : eqset_compl.
unfold eqset,compl; firstorder.
Save.
Hint Resolve eqset_compl.

Lemma eqset_add_empty : forall (a:A) (P:set), ~eqset (add a P) empty.
red; unfold eqset,empty,add; intros a P eqH; assert (H:=eqH a);  intuition.
Save.

(** ** Finite sets given as an enumeration of elements *)

Inductive finite (P: set) : Type :=
   fin_eq_empty : eqset P empty -> finite P
 | fin_eq_add : forall (x:A)(Q:set),
             ~ Q x-> finite Q -> eqset P (add x Q) -> finite P.
Hint Constructors finite.

Lemma fin_empty : (finite empty).
auto.
Defined.

Lemma fin_add : forall (x:A)(P:set),
             ~ P x -> finite P -> finite (add x P).
eauto.
Defined.

Lemma fin_eqset: forall (P Q : set), (eqset P Q)->(finite P)->(finite Q).
induction 2.
apply fin_eq_empty.
apply eqset_trans with P; auto.
apply fin_eq_add with x Q0; auto.
apply eqset_trans with P; auto.
Defined.

Hint Resolve fin_empty fin_add.

(** *** Emptyness is decidable for finite sets *)
Definition isempty (P:set) := eqset P empty.
Definition notempty (P:set) := not (eqset P empty).

Lemma isempty_dec : forall P, finite P -> {isempty P}+{notempty P}.
unfold isempty,notempty; destruct 1; auto.
right; red; intros.
apply (@eqset_add_empty x Q); auto.
apply eqset_trans with P; auto.
Save.

(** *** Size of a finite set *)
Fixpoint size (P:set) (f:finite P) {struct f}: nat :=
   match f with fin_eq_empty _ => 0%nat
              | fin_eq_add _ Q _ f' _ => S (size f')
   end.

Lemma size_eqset : forall P Q  (f:finite P) (e:eqset P Q),
    (size (fin_eqset e f)) = (size f).
induction f; simpl; intros; auto.
Save.

(** ** Inclusion *)
Definition incl (P Q:set) := forall x, P x -> Q x.

Lemma incl_refl : forall (P:set), incl P P.
unfold incl; intuition.
Save.

Lemma incl_trans : forall (P Q R:set),
incl P Q -> incl Q R -> incl P R.
unfold incl; intuition.
Save.

Lemma eqset_incl : forall (P Q : set),  eqset P Q -> incl P Q.
unfold eqset, incl; firstorder.
Save.

Lemma eqset_incl_sym : forall (P Q : set), eqset P Q -> incl Q P.
unfold eqset, incl; firstorder.
Save.

Lemma eqset_incl_intro :
forall (P Q : set), incl P Q -> incl Q P -> eqset P Q.
unfold eqset, incl; firstorder.
Save.

Hint Resolve incl_refl incl_trans eqset_incl_intro.
Hint Immediate eqset_incl eqset_incl_sym.

(** ** Properties of operations on sets *)

Lemma incl_empty : forall P, incl empty P.
unfold incl,empty; intuition.
Save.

Lemma incl_empty_false : forall P a, incl P empty -> ~ P a.
unfold incl; firstorder.
Save.

Lemma incl_add_empty : forall (a:A) (P:set), ~ incl (add a P) empty.
red; unfold incl,empty,add; intros a P eqH; assert (H:=eqH a);  intuition.
Save.

Lemma eqset_empty_false : forall P a, eqset P empty -> P a -> False.
unfold eqset; firstorder.
Save.

Hint Immediate incl_empty_false eqset_empty_false incl_add_empty.

Lemma incl_rem_stable :   forall a P Q, incl P Q -> incl (rem a P) (rem a Q).
unfold incl,rem;intuition.
Save.

Lemma incl_add_stable :   forall a P Q, incl P Q -> incl (add a P) (add a Q).
unfold incl,add;intuition.
Save.

Lemma incl_rem_add_iff :
  forall a P Q, incl (rem a P) Q <-> incl P (add a Q).
unfold rem, add, incl; intuition.
case (decA x a); auto.
case (H x); intuition.
Save.

Lemma incl_rem_add:
  forall (a:A) (P Q:set),
     (P a) -> incl Q (rem a P) -> incl (add a Q) P.
unfold rem, add, incl; intros; auto.
case H1; intro; subst; auto.
case (H0 x); auto.
Save.

Lemma incl_add_rem :
  forall (a:A) (P Q:set),
     ~ Q a -> incl (add a Q) P -> incl Q (rem a P) .
unfold rem, add, incl; intros; auto.
case (decA x a); intros; auto.
subst; case H; auto.
Save.

Hint Immediate incl_rem_add incl_add_rem.

Lemma eqset_rem_add :
 forall (a:A) (P Q:set),
     (P a) -> eqset Q (rem a P)  -> eqset (add a Q) P.
intros; assert (incl Q (rem a P)); auto.
assert (incl (rem a P) Q); auto.
case (incl_rem_add_iff a P Q); auto.
Save.

Lemma eqset_add_rem :
 forall (a:A) (P Q:set),
     ~ Q a -> eqset (add a Q) P -> eqset Q (rem a P).
intros; assert (incl (add a Q) P); auto.
assert (incl P (add a Q)); auto.
case (incl_rem_add_iff a P Q); auto.
Save.

Hint Immediate eqset_rem_add eqset_add_rem.

Lemma add_rem_eq_eqset :
  forall x (P:set), eqset (add x (rem x P)) (add x P).
unfold eqset, add, rem; intuition.
case (decA x0 x); intuition.
Save.

Lemma add_rem_diff_eqset :
  forall x y (P:set),
  x<>y -> eqset (add x (rem y P)) (rem y (add x P)).
unfold eqset, add, rem; intuition.
subst; auto.
Save.

Lemma add_eqset_in :
  forall x (P:set), P x -> eqset (add x P) P.
unfold eqset, add; intuition.
subst;auto.
Save.

Hint Resolve add_rem_eq_eqset add_rem_diff_eqset add_eqset_in.

Lemma add_rem_eqset_in :
  forall x (P:set), P x -> eqset (add x (rem x P)) P.
intros; apply eqset_trans with (add x P); auto.
Save.

Hint Resolve add_rem_eqset_in.

Lemma rem_add_eq_eqset :
  forall x (P:set), eqset (rem x (add x P)) (rem x P).
unfold eqset, add, rem; intuition.
Save.

Lemma rem_add_diff_eqset :
  forall x y (P:set),
  x<>y -> eqset (rem x (add y P)) (add y (rem x P)).
intros; apply eqset_sym; auto.
Save.

Lemma rem_eqset_notin :
  forall x (P:set), ~P x -> eqset (rem x P) P.
unfold eqset, rem; intuition.
subst;auto.
Save.

Hint Resolve rem_add_eq_eqset rem_add_diff_eqset rem_eqset_notin.

Lemma rem_add_eqset_notin :
  forall x (P:set), ~P x -> eqset (rem x (add x P)) P.
intros; apply eqset_trans with (rem x P); auto.
Save.

Hint Resolve rem_add_eqset_notin.

Lemma rem_not_in : forall x (P:set), ~ rem x P x.
unfold rem; intuition.
Save.

Lemma add_in : forall x (P:set), add x P x.
unfold add; intuition.
Save.

Lemma add_in_eq : forall x y P, x=y -> add x P y.
unfold add; intuition.
Save.

Lemma add_intro : forall x (P:set) y, P y -> add x P y.
unfold add; intuition.
Save.

Lemma add_incl : forall x (P:set), incl P (add x P).
unfold incl,add; intuition.
Save.

Lemma add_incl_intro : forall x (P Q:set), (Q x) -> (incl P Q) -> (incl (add x P) Q).
unfold incl,add; intuition; subst; intuition.
Save.

Lemma rem_incl : forall x (P:set), incl (rem x P) P.
unfold incl, rem; intuition.
Save.

Hint Resolve rem_not_in add_in rem_incl add_incl.

Lemma union_sym : forall P Q : set,
      eqset (union P Q) (union Q P).
unfold eqset, union; intuition.
Save.

Lemma union_empty_left : forall P : set,
      eqset P (union P empty).
unfold eqset, union, empty; intuition.
Save.

Lemma union_empty_right : forall P : set,
      eqset P (union empty P).
unfold eqset, union, empty; intuition.
Save.

Lemma union_add_left : forall (a:A) (P Q: set),
      eqset (add a (union P Q)) (union P (add a Q)).
unfold eqset, union, add; intuition.
Save.

Lemma union_add_right : forall (a:A) (P Q: set),
      eqset (add a (union P Q)) (union (add a P) Q).
unfold eqset, union, add; intuition.
Save.

Hint Resolve union_sym union_empty_left union_empty_right
union_add_left union_add_right.

Lemma union_incl_left : forall P Q, incl P (union P Q).
unfold incl,union; intuition.
Save.

Lemma union_incl_right : forall P Q, incl Q (union P Q).
unfold incl,union; intuition.
Save.

Lemma union_incl_intro : forall P Q R, incl P R -> incl Q R -> incl (union P Q) R.
unfold incl,union; intuition.
Save.

Hint Resolve union_incl_left union_incl_right union_incl_intro.

Lemma incl_union_stable : forall P1 P2 Q1 Q2,
	incl P1 P2 -> incl Q1 Q2 -> incl (union P1 Q1) (union P2 Q2).
intros; apply union_incl_intro; unfold incl,union; intuition.
Save.
Hint Immediate incl_union_stable.

Lemma inter_sym : forall P Q : set,
      eqset (inter P Q) (inter Q P).
unfold eqset, inter; intuition.
Save.

Lemma inter_empty_left : forall P : set,
      eqset empty (inter P empty).
unfold eqset, inter, empty; intuition.
Save.

Lemma inter_empty_right : forall P : set,
      eqset empty (inter empty P).
unfold eqset, inter, empty; intuition.
Save.

Lemma inter_add_left_in : forall (a:A) (P Q: set),
      (P a) -> eqset (add a (inter P Q)) (inter P (add a Q)).
unfold eqset, inter, add; split; intuition.
subst; auto.
Save.

Lemma inter_add_left_out : forall (a:A) (P Q: set),
      ~ P a -> eqset (inter P Q) (inter P (add a Q)).
unfold eqset, inter, add; split; intuition.
subst; case H; auto.
Save.

Lemma inter_add_right_in : forall (a:A) (P Q: set),
      Q a -> eqset (add a (inter P Q)) (inter (add a P) Q).
unfold eqset, inter, add; split; intuition.
subst; auto.
Save.

Lemma inter_add_right_out : forall (a:A) (P Q: set),
      ~ Q a -> eqset (inter P Q) (inter (add a P) Q).
unfold eqset, inter, add; split; intuition.
subst; case H; auto.
Save.

Hint Resolve inter_sym inter_empty_left inter_empty_right
inter_add_left_in inter_add_left_out inter_add_right_in inter_add_right_out.

(** ** Generalized union *)
Definition gunion (I:Type)(F:I->set) : set := fun z => exists i, F i z.

Lemma gunion_intro : forall I (F:I->set) i, incl (F i) (gunion F).
red; intros; exists i; auto.
Save.

Lemma gunion_elim : forall I (F:I->set) (P:set), (forall i, incl (F i) P) -> incl (gunion F) P.
red; intros I F P H x (i,Hi).
apply (H i x); auto.
Save.

Lemma gunion_monotonic : forall I (F G : I -> set),
      (forall i, incl (F i) (G i))-> incl (gunion F) (gunion G).
intros I F G H x (i,Hi).
exists i; apply (H i x); trivial.
Save.

(** ** Decidable sets *)
Definition dec (P:set) := forall x, {P x}+{ ~ P x}.

Definition dec2bool (P:set) : dec P -> A -> bool :=
   fun p x => if p x then true else false.

Lemma compl_dec : forall P, dec P -> dec (compl P).
intros P dP x; destruct (dP x); auto.
Defined.

Lemma inter_dec : forall P Q, dec P -> dec Q -> dec (inter P Q).
intros P Q dP dQ x; unfold inter; destruct (dP x).
destruct (dQ x); intuition.
right; intuition.
Defined.

Lemma union_dec : forall P Q, dec P -> dec Q -> dec (union P Q).
intros P Q dP dQ x; unfold union; destruct (dP x); auto.
destruct (dQ x); intuition.
Defined.

Hint Resolve compl_dec inter_dec union_dec.

(** ** Removing an element from a finite set *)

Lemma finite_rem :  forall (P:set) (a:A),
   finite P -> finite (rem a P).
induction 1; intuition.
apply fin_eq_empty.
unfold rem,empty,eqset; intuition.
apply (eqset_empty_false x e); auto.
case (decA x a); intros.
apply fin_eqset with Q; subst; auto.
apply eqset_add_rem; auto.
apply fin_eq_add with x (rem a Q); auto.
subst; unfold rem; intuition.
apply eqset_trans with (rem a (add x Q)); auto.
Defined.

Lemma size_finite_rem:
   forall (P:set) (a:A) (f:finite P),
    (P a) -> size f = S (size (finite_rem a f)).
induction f;  intros.
case (eqset_empty_false a e H).
simpl; case (decA x a); simpl; intros.
case e0; unfold eq_rect_r;simpl; auto.
rewrite size_eqset; auto.
rewrite IHf; auto.
case (e a); unfold add; intuition.
case n0; auto.
Save.

(* bug lie a intuition
Lemma size_finite_rem:
   forall (P:set) (a:A) (f:finite P),
    (P a) -> size f = S (size (finite_rem a f)).
induction f;  intuition.
case (eqset_empty_false a e H).
simpl; case (decA x a); simpl; intros.
case e0; unfold eq_rect_r;simpl; auto.
rewrite size_eqset; auto.
rewrite IHf; auto.
case (e a); unfold add; intuition.
case f0; auto.
Save.
*)
Require Import Arith.

Lemma size_incl :
  forall (P:set)(f:finite P) (Q:set)(g:finite Q),
  (incl P Q)-> size f <= size g.
induction f; simpl; intros; auto with arith.
apply le_trans with (S (size (finite_rem x g))).
apply le_n_S.
apply IHf with (g:= finite_rem x g); auto.
apply incl_trans with (rem x P); auto.
apply incl_add_rem; auto.
apply incl_rem_stable; auto.
rewrite <- size_finite_rem; auto.
case (e x); intuition.
Save.

Lemma size_unique :
  forall (P:set)(f:finite P) (Q:set)(g:finite Q),
  (eqset P Q)-> size f = size g.
intros; apply le_antisym; apply size_incl; auto.
Save.

Lemma finite_incl : forall P:set,
   finite P -> forall Q:set, dec Q -> incl Q P -> finite Q.
intros P FP; elim FP; intros; auto.
apply fin_eq_empty.
unfold empty,eqset in *|-*; intuition.
case (e x); auto.
case (X0 x); intros.
apply fin_eq_add with (x:=x) (Q:=(rem x Q0)); auto.
apply X.
unfold dec,rem.
intro y; case (decA x y); intro.
case (X0 y); subst; intuition.
case (X0 y); intuition.
case (incl_rem_add_iff x Q0 Q); intuition.
apply H1; apply incl_trans with P0; auto.
apply eqset_sym; auto.
apply X; auto.
red; intros.
case (e x0); intuition.
case H1; intuition; subst; auto.
case n0; auto.
Save.

Lemma finite_dec : forall P:set, finite P -> dec P.
red; intros P FP; elim FP; intros.
right; intro; apply (eqset_empty_false x e); auto.
case (e x0); unfold add; intuition.
case (X x0); intuition.
case (decA x0 x); intuition.
Save.

Lemma fin_add_in : forall (a:A) (P:set), finite P -> finite (add a P).
intros a P FP; case (finite_dec FP a); intro.
apply fin_eqset with P; auto.
apply eqset_sym; auto.
apply fin_add; auto.
Defined.

Lemma finite_union :
     forall P Q, finite P -> finite Q -> finite (union P Q).
intros P Q FP FQ; elim FP; intros.
apply fin_eqset with Q; auto.
apply eqset_trans with (union empty Q); auto.
apply fin_eqset with (add x (union Q0 Q)); auto.
apply eqset_trans with (union (add x Q0) Q); auto.
apply fin_add_in; auto.
Defined.

Lemma finite_full_dec : forall P:set, finite full -> dec P -> finite P.
intros; apply finite_incl with full; auto.
unfold full,incl; auto.
Save.

Require Import Lt.

(** *** Filter operation *)

Lemma finite_inter : forall P Q, dec P -> finite Q -> finite (inter P Q).
intros P Q decP FQ.
induction FQ.
constructor 1.
apply eqset_trans with (inter P empty); auto.
case (decP x); intro.
constructor 2 with x (inter P Q); auto.
unfold inter; intuition.
rewrite e.
unfold add,inter; red; intuition.
subst; auto.
apply fin_eqset with (inter P Q); auto.
rewrite e.
unfold add,inter; red; intuition.
subst; intuition.
Defined.

Lemma size_inter_empty : forall P Q (decP:dec P) (e:eqset Q empty),
   size (finite_inter decP (fin_eq_empty e))=O.
trivial.
Save.

Lemma size_inter_add_in :
     forall P Q R (decP:dec P)(x:A)(nq:~Q x)(FQ:finite Q)(e:eqset R (add x Q)),
      P x ->size (finite_inter decP (fin_eq_add nq FQ e))=S (size (finite_inter decP FQ)).
intros; simpl.
case (decP x); intro; trivial; contradiction.
Save.

Lemma size_inter_add_notin :
     forall P Q R (decP:dec P)(x:A)(nq:~Q x)(FQ:finite Q)(e:eqset R (add x Q)),
   ~ P x -> size (finite_inter decP (fin_eq_add nq FQ e))=size (finite_inter decP FQ).
intros; simpl.
case (decP x); intro; try contradiction.
rewrite size_eqset; trivial.
Save.

Lemma size_inter_incl : forall P Q (decP:dec P)(FP:finite P)(FQ:finite Q),
    (incl P Q) -> size (finite_inter decP FQ)=size FP.
intros; apply size_unique.
unfold inter; intro.
generalize (H x); intuition.
Save.

(** *** Selecting elements in a finite set *)

Fixpoint nth_finite (P:set) (k:nat) (PF : finite P) {struct PF}: (k < size PF) -> A :=
  match PF as F return (k < size F) -> A with
       fin_eq_empty H => (fun (e : k<0) => match lt_n_O k e with end)
     | fin_eq_add x Q nqx fq eqq =>
           match k as k0 return k0<S (size fq)->A with
                O => fun e => x
         | (S k1) => fun (e:S k1<S (size fq)) => nth_finite fq (lt_S_n k1 (size fq) e)
           end
  end.

(** A set with size > 1 contains at least 2 different elements **)

Lemma select_non_empty : forall (P:set), finite P -> notempty P -> sigT P.
destruct 1; intros.
case H; auto.
exists x; case (e x); intuition.
Defined.

Lemma select_diff : forall (P:set) (FP:finite P),
     (1 < size FP)%nat -> sigT (fun x => sigT (fun y => P x /\ P y /\ x<>y)).
destruct FP; simpl; intros.
absurd (1<0); omega.
exists x; destruct FP; simpl in H.
absurd (1<1); omega.
exists x0; intuition.
case (e x); auto.
case (e0 x0); case (e x0); unfold add; intuition.
subst; case (e0 x0); intuition.
Save.

End sets.

Hint Resolve eqset_refl.
Hint Resolve eqset_add eqset_rem.
Hint Immediate eqset_sym finite_dec finite_full_dec eqset_incl eqset_incl_sym eqset_incl_intro.

Hint Resolve incl_refl.
Hint Immediate incl_union_stable.
Hint Resolve union_incl_left union_incl_right union_incl_intro incl_empty rem_incl
incl_rem_stable incl_add_stable.

Hint Constructors finite.
Hint Resolve add_in add_in_eq add_intro add_incl add_incl_intro union_sym union_empty_left union_empty_right
union_add_left union_add_right finite_union eqset_union_left
eqset_union_right.
Implicit Arguments full [].
Implicit Arguments empty [].

Add Parametric Relation (A:Type) : (set A) (eqset (A:=A))
      reflexivity proved by (eqset_refl (A:=A))
      symmetry proved by (eqset_sym (A:=A))
      transitivity proved by (eqset_trans (A:=A))
as eqset_rel.

Add Parametric Relation (A:Type) : (set A) (incl (A:=A))
      reflexivity proved by (incl_refl (A:=A))
      transitivity proved by (incl_trans (A:=A))
as incl_rel.


(* Copyright (c) 2008-2009, Adam Chlipala
 *
 * This work is licensed under a
 * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0
 * Unported License.
 * The license text is available at:
 *   http://creativecommons.org/licenses/by-nc-nd/3.0/
 *)

(* Dependent list types presented in Chapter 9 *)

Require Import Arith List.
Load "CpdtTactics.v".

Set Implicit Arguments.

Section ilist.
  Variable A : Type.

  Inductive ilist : nat -> Type :=
  | INil : ilist O
  | ICons : forall n, A -> ilist n -> ilist (S n).

  Definition hd n (ls : ilist (S n)) :=
    match ls in ilist n' return match n' with
                                  | O => unit
                                  | S _ => A
                                end with
      | INil => tt
      | ICons _ x _ => x
    end.
  Definition tl n (ls : ilist (S n)) :=
    match ls in ilist n' return match n' with
                                  | O => unit
                                  | S n => ilist n
                                end with
      | INil => tt
      | ICons _ _ ls' => ls'
    end.

  Inductive fin : nat -> Set :=
  | First : forall n, fin (S n)
  | Next : forall n, fin n -> fin (S n).

  Fixpoint get n (ls : ilist n) : fin n -> A :=
    match ls with
      | INil => fun idx =>
        match idx in fin n' return (match n' with
                                        | O => A
                                        | S _ => unit
                                      end) with
          | First _ => tt
          | Next _ _ => tt
        end
      | ICons _ x ls' => fun idx =>
        match idx in fin n' return (fin (pred n') -> A) -> A with
          | First _ => fun _ => x
          | Next _ idx' => fun get_ls' => get_ls' idx'
        end (get ls')
    end.

  Section everywhere.
    Variable x : A.

    Fixpoint everywhere (n : nat) : ilist n :=
      match n with
        | O => INil
        | S n' => ICons x (everywhere n')
      end.
  End everywhere.

  Section singleton.
    Variables x default : A.

    Fixpoint singleton (n m : nat) : ilist n :=
      match n with
        | O => INil
        | S n' =>
          match m with
            | O => ICons x (everywhere default n')
            | S m' => ICons default (singleton n' m')
          end
      end.
  End singleton.

  Section map2.
    Variable f : A -> A -> A.

    Fixpoint map2 n (il1 : ilist n) : ilist n -> ilist n :=
      match il1 in ilist n return ilist n -> ilist n with
        | INil => fun _ => INil
        | ICons _ x il1' => fun il2 => ICons (f x (hd il2)) (map2 il1' (tl il2))
      end.
  End map2.

  Section fold.
    Variable B : Type.
    Variable f : A -> B -> B.
    Variable i : B.

    Fixpoint foldr n (il : ilist n) : B :=
      match il with
        | INil => i
        | ICons _ x il' => f x (foldr il')
      end.
  End fold.
End ilist.

Implicit Arguments INil [A].
Implicit Arguments First [n].

Section imap.
  Variables A B : Type.
  Variable f : A -> B.

  Fixpoint imap n (il : ilist A n) : ilist B n :=
    match il with
      | INil => INil
      | ICons _ x il' => ICons (f x) (imap il')
    end.
End imap.

Section hlist.
  Variable A : Type.
  Variable B : A -> Type.

  Inductive hlist : list A -> Type :=
  | HNil : hlist nil
  | HCons : forall (x : A) (ls : list A), B x -> hlist ls -> hlist (x :: ls).

  Definition hhd ls (hl : hlist ls) :=
    match hl in hlist ls return match ls with
                                  | nil => unit
                                  | x :: _ => B x
                                end with
      | HNil => tt
      | HCons _ _ v _ => v
    end.

  Definition htl ls (hl : hlist ls) :=
    match hl in hlist ls return match ls with
                                  | nil => unit
                                  | _ :: ls' => hlist ls'
                                end with
      | HNil => tt
      | HCons _ _ _ hl' => hl'
    end.

  Variable elm : A.

  Inductive member : list A -> Type :=
  | HFirst : forall ls, member (elm :: ls)
  | HNext : forall x ls, member ls -> member (x :: ls).

  Fixpoint hget ls (mls : hlist ls) : member ls -> B elm :=
    match mls with
      | HNil => fun mem =>
        match mem in member ls' return (match ls' with
                                          | nil => B elm
                                          | _ :: _ => unit
                                        end) with
          | HFirst _ => tt
          | HNext _ _ _ => tt
        end
      | HCons _ _ x mls' => fun mem =>
        match mem in member ls' return (match ls' with
                                          | nil => Empty_set
                                          | x' :: ls'' =>
                                            B x' -> (member ls'' -> B elm) -> B elm
                                        end) with
          | HFirst _ => fun x _ => x
          | HNext _ _ mem' => fun _ get_mls' => get_mls' mem'
        end x (hget mls')
    end.

  Fixpoint happ (ls1 : list A) (hl1 : hlist ls1) : forall ls2, hlist ls2 -> hlist (ls1 ++ ls2) :=
    match hl1 in hlist ls1 return forall ls2, hlist ls2 -> hlist (ls1 ++ ls2) with
      | HNil => fun _ hl2 => hl2
      | HCons _ _ x hl1' => fun _ hl2 => HCons x (happ hl1' hl2)
    end.

  Variable f : forall x, B x.

  Fixpoint hmake (ls : list A) : hlist ls :=
    match ls with
      | nil => HNil
      | x :: ls' => HCons (f x) (hmake ls')
    end.

  Theorem hget_hmake : forall ls (m : member ls),
    hget (hmake ls) m = f elm.
    induction ls; crush;
      match goal with
        | [ |- context[match ?E with HFirst _ => _ | HNext _ _ _ => _ end] ] => dep_destruct E
      end; crush.
  Qed.
End hlist.

Implicit Arguments HNil [A B].
Implicit Arguments HCons [A B x ls].
Implicit Arguments hmake [A B].

Implicit Arguments HFirst [A elm ls].
Implicit Arguments HNext [A elm x ls].

Infix ":::" := HCons (right associativity, at level 60).
Infix "+++" := happ (right associativity, at level 60).

Section hmap.
  Variable A : Type.
  Variables B1 B2 : A -> Type.

  Variable f : forall x, B1 x -> B2 x.

  Fixpoint hmap (ls : list A) (hl : hlist B1 ls) : hlist B2 ls :=
    match hl with
      | HNil => HNil
      | HCons _ _ x hl' => f x ::: hmap hl'
    end.

  Theorem hmap_happ : forall ls2 (h2 : hlist B1 ls2) ls1 (h1 : hlist B1 ls1),
    hmap h1 +++ hmap h2 = hmap (h1 +++ h2).
    induction h1; crush.
  Qed.

  Theorem hget_hmap : forall elm ls (hls : hlist B1 ls) (m : member elm ls),
    hget (hmap hls) m = f (hget hls m).
    induction hls; crush;
      match goal with
        | [ |- context[match ?E with HFirst _ => _ | HNext _ _ _ => _ end] ] => dep_destruct E
      end; crush.
  Qed.
End hmap.

Implicit Arguments hmap [A B1 B2 ls].