From 8573b097f5f8394dec85957cd725020cee9faed1 Mon Sep 17 00:00:00 2001
From: Felipe Cerqueira <felipec@mpi-sws.org>
Date: Wed, 8 Jun 2016 13:03:28 +0200
Subject: [PATCH] Add tactics to compute [exists] and [forall]

---
 Makefile                                  |   4 +-
 implementation/apa/bertogna_edf_example.v |  56 ++++--------
 implementation/apa/bertogna_fp_example.v  |  55 ++++--------
 util/all.v                                |   2 +-
 util/counting.v                           |   2 +-
 util/exists.v                             |  72 ---------------
 util/ord_quantifier.v                     | 101 ++++++++++++++++++++++
 7 files changed, 135 insertions(+), 157 deletions(-)
 delete mode 100644 util/exists.v
 create mode 100644 util/ord_quantifier.v

diff --git a/Makefile b/Makefile
index f874e7c18..0824af975 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@
 
 #
 # This Makefile was generated by the command line :
-# coq_makefile -f _CoqProject ./util/fixedpoint.v ./util/ssromega.v ./util/bigcat.v ./util/nat.v ./util/seqset.v ./util/notation.v ./util/list.v ./util/powerset.v ./util/all.v ./util/sorting.v ./util/tactics.v ./util/bigord.v ./util/exists.v ./util/induction.v ./util/sum.v ./util/divround.v ./util/counting.v ./implementation/basic/bertogna_edf_example.v ./implementation/basic/task.v ./implementation/basic/schedule.v ./implementation/basic/bertogna_fp_example.v ./implementation/basic/job.v ./implementation/basic/arrival_sequence.v ./implementation/parallel/bertogna_edf_example.v ./implementation/parallel/task.v ./implementation/parallel/schedule.v ./implementation/parallel/bertogna_fp_example.v ./implementation/parallel/job.v ./implementation/parallel/arrival_sequence.v ./implementation/jitter/bertogna_edf_example.v ./implementation/jitter/task.v ./implementation/jitter/schedule.v ./implementation/jitter/bertogna_fp_example.v ./implementation/jitter/job.v ./implementation/jitter/arrival_sequence.v ./implementation/apa/bertogna_edf_example.v ./implementation/apa/task.v ./implementation/apa/schedule.v ./implementation/apa/bertogna_fp_example.v ./implementation/apa/job.v ./implementation/apa/arrival_sequence.v ./analysis/basic/bertogna_fp_theory.v ./analysis/basic/interference_bound_edf.v ./analysis/basic/interference_bound_fp.v ./analysis/basic/interference_bound.v ./analysis/basic/bertogna_edf_comp.v ./analysis/basic/bertogna_fp_comp.v ./analysis/basic/bertogna_edf_theory.v ./analysis/basic/workload_bound.v ./analysis/parallel/bertogna_fp_theory.v ./analysis/parallel/interference_bound_edf.v ./analysis/parallel/interference_bound_fp.v ./analysis/parallel/interference_bound.v ./analysis/parallel/bertogna_edf_comp.v ./analysis/parallel/bertogna_fp_comp.v ./analysis/parallel/bertogna_edf_theory.v ./analysis/parallel/workload_bound.v ./analysis/jitter/bertogna_fp_theory.v ./analysis/jitter/interference_bound_edf.v ./analysis/jitter/interference_bound_fp.v ./analysis/jitter/interference_bound.v ./analysis/jitter/bertogna_edf_comp.v ./analysis/jitter/bertogna_fp_comp.v ./analysis/jitter/bertogna_edf_theory.v ./analysis/jitter/workload_bound.v ./analysis/apa/bertogna_fp_theory.v ./analysis/apa/interference_bound_edf.v ./analysis/apa/interference_bound_fp.v ./analysis/apa/interference_bound.v ./analysis/apa/bertogna_edf_comp.v ./analysis/apa/bertogna_fp_comp.v ./analysis/apa/bertogna_edf_theory.v ./analysis/apa/workload_bound.v ./model/basic/time.v ./model/basic/schedulability.v ./model/basic/task.v ./model/basic/task_arrival.v ./model/basic/platform.v ./model/basic/schedule.v ./model/basic/priority.v ./model/basic/interference_edf.v ./model/basic/interference.v ./model/basic/constrained_deadlines.v ./model/basic/workload.v ./model/basic/job.v ./model/basic/arrival_sequence.v ./model/basic/response_time.v ./model/jitter/time.v ./model/jitter/schedulability.v ./model/jitter/task.v ./model/jitter/task_arrival.v ./model/jitter/platform.v ./model/jitter/schedule.v ./model/jitter/priority.v ./model/jitter/interference_edf.v ./model/jitter/interference.v ./model/jitter/constrained_deadlines.v ./model/jitter/workload.v ./model/jitter/job.v ./model/jitter/arrival_sequence.v ./model/jitter/response_time.v ./model/apa/time.v ./model/apa/schedulability.v ./model/apa/task.v ./model/apa/task_arrival.v ./model/apa/platform.v ./model/apa/schedule.v ./model/apa/priority.v ./model/apa/affinity.v ./model/apa/interference_edf.v ./model/apa/interference.v ./model/apa/constrained_deadlines.v ./model/apa/workload.v ./model/apa/job.v ./model/apa/arrival_sequence.v ./model/apa/response_time.v -o Makefile 
+# coq_makefile -f _CoqProject ./util/fixedpoint.v ./util/ssromega.v ./util/bigcat.v ./util/nat.v ./util/seqset.v ./util/notation.v ./util/list.v ./util/powerset.v ./util/all.v ./util/sorting.v ./util/tactics.v ./util/bigord.v ./util/induction.v ./util/ord_quantifier.v ./util/sum.v ./util/divround.v ./util/counting.v ./implementation/basic/bertogna_edf_example.v ./implementation/basic/task.v ./implementation/basic/schedule.v ./implementation/basic/bertogna_fp_example.v ./implementation/basic/job.v ./implementation/basic/arrival_sequence.v ./implementation/parallel/bertogna_edf_example.v ./implementation/parallel/task.v ./implementation/parallel/schedule.v ./implementation/parallel/bertogna_fp_example.v ./implementation/parallel/job.v ./implementation/parallel/arrival_sequence.v ./implementation/jitter/bertogna_edf_example.v ./implementation/jitter/task.v ./implementation/jitter/schedule.v ./implementation/jitter/bertogna_fp_example.v ./implementation/jitter/job.v ./implementation/jitter/arrival_sequence.v ./implementation/apa/bertogna_edf_example.v ./implementation/apa/task.v ./implementation/apa/schedule.v ./implementation/apa/bertogna_fp_example.v ./implementation/apa/job.v ./implementation/apa/arrival_sequence.v ./analysis/basic/bertogna_fp_theory.v ./analysis/basic/interference_bound_edf.v ./analysis/basic/interference_bound_fp.v ./analysis/basic/interference_bound.v ./analysis/basic/bertogna_edf_comp.v ./analysis/basic/bertogna_fp_comp.v ./analysis/basic/bertogna_edf_theory.v ./analysis/basic/workload_bound.v ./analysis/parallel/bertogna_fp_theory.v ./analysis/parallel/interference_bound_edf.v ./analysis/parallel/interference_bound_fp.v ./analysis/parallel/interference_bound.v ./analysis/parallel/bertogna_edf_comp.v ./analysis/parallel/bertogna_fp_comp.v ./analysis/parallel/bertogna_edf_theory.v ./analysis/parallel/workload_bound.v ./analysis/jitter/bertogna_fp_theory.v ./analysis/jitter/interference_bound_edf.v ./analysis/jitter/interference_bound_fp.v ./analysis/jitter/interference_bound.v ./analysis/jitter/bertogna_edf_comp.v ./analysis/jitter/bertogna_fp_comp.v ./analysis/jitter/bertogna_edf_theory.v ./analysis/jitter/workload_bound.v ./analysis/apa/bertogna_fp_theory.v ./analysis/apa/interference_bound_edf.v ./analysis/apa/interference_bound_fp.v ./analysis/apa/interference_bound.v ./analysis/apa/bertogna_edf_comp.v ./analysis/apa/bertogna_fp_comp.v ./analysis/apa/bertogna_edf_theory.v ./analysis/apa/workload_bound.v ./model/basic/time.v ./model/basic/schedulability.v ./model/basic/task.v ./model/basic/task_arrival.v ./model/basic/platform.v ./model/basic/schedule.v ./model/basic/priority.v ./model/basic/interference_edf.v ./model/basic/interference.v ./model/basic/constrained_deadlines.v ./model/basic/workload.v ./model/basic/job.v ./model/basic/arrival_sequence.v ./model/basic/response_time.v ./model/jitter/time.v ./model/jitter/schedulability.v ./model/jitter/task.v ./model/jitter/task_arrival.v ./model/jitter/platform.v ./model/jitter/schedule.v ./model/jitter/priority.v ./model/jitter/interference_edf.v ./model/jitter/interference.v ./model/jitter/constrained_deadlines.v ./model/jitter/workload.v ./model/jitter/job.v ./model/jitter/arrival_sequence.v ./model/jitter/response_time.v ./model/apa/time.v ./model/apa/schedulability.v ./model/apa/task.v ./model/apa/task_arrival.v ./model/apa/platform.v ./model/apa/schedule.v ./model/apa/priority.v ./model/apa/affinity.v ./model/apa/interference_edf.v ./model/apa/interference.v ./model/apa/constrained_deadlines.v ./model/apa/workload.v ./model/apa/job.v ./model/apa/arrival_sequence.v ./model/apa/response_time.v -o Makefile 
 #
 
 .DEFAULT_GOAL := all
@@ -106,8 +106,8 @@ VFILES:=util/fixedpoint.v\
   util/sorting.v\
   util/tactics.v\
   util/bigord.v\
-  util/exists.v\
   util/induction.v\
+  util/ord_quantifier.v\
   util/sum.v\
   util/divround.v\
   util/counting.v\
diff --git a/implementation/apa/bertogna_edf_example.v b/implementation/apa/bertogna_edf_example.v
index d8fdf6fe5..c922446a9 100644
--- a/implementation/apa/bertogna_edf_example.v
+++ b/implementation/apa/bertogna_edf_example.v
@@ -107,52 +107,26 @@ Module ResponseTimeAnalysisEDF.
         by rewrite unlock; compute.
       } rewrite STEPS; clear STEPS.
 
-      have cpu0P: 0 < 2 by done.
-      have cpu1P: 1 < 2 by done.
-
-      have cpu_compute :
-        forall (P: processor num_cpus -> bool),
-          [exists x, P x] =
-            if (P (cpu 0 cpu0P)) then true else
-              if P (cpu 1 cpu1P) then true else false.
-      {
-        unfold num_cpus in *; intros P.
-        destruct (P (cpu 0 cpu0P)) eqn:P0;
-          first by apply/existsP; exists (cpu 0 cpu0P).
-        destruct (P (cpu 1 cpu1P)) eqn:P1;
-          first by apply/existsP; exists (cpu 1 cpu1P).
-        apply negbTE; rewrite negb_exists; apply/forallP.
-        intros x; destruct x as [x LE]; apply negbT.
-        have GE0 := leq0n x.
-        rewrite leq_eqVlt in GE0; move: GE0 => /orP [/eqP EQ0 | GE1];
-          first by rewrite -P0; f_equal; apply ord_inj.
-        rewrite leq_eqVlt in GE1; move: GE1 => /orP [/eqP EQ1 | GE2];
-          first by rewrite -P1; f_equal; apply ord_inj.
-        have LE' := LE.
-        apply leq_ltn_trans with (m := 2) in LE'; last by done.
-        by rewrite ltnn in LE'.
-      }
-
-      Ltac f :=
+      Local Ltac f :=
         unfold edf_rta_iteration; simpl;
         unfold edf_response_time_bound, div_floor, total_interference_bound_edf, interference_bound_edf, interference_bound_generic, W, edf_specific_interference_bound, different_task_in, affinity_intersects; simpl;
         rewrite !addnE !set_card !big_cons ?big_nil /=.
 
-      
+      Local Ltac g := destruct master_key; f; simpl_exists_ord.      
       rewrite [edf_rta_iteration]lock; simpl.
-      unfold locked at 13; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 12; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 11; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 10; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 9; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 8; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 7; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 6; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 5; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 4; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 3; destruct master_key; f; rewrite !cpu_compute /=.
-      unfold locked at 2; destruct master_key; f; rewrite !cpu_compute /=.
-      by unfold locked at 1; destruct master_key; f; rewrite !cpu_compute /=.
+      unfold locked at 13; g.
+      unfold locked at 12; g.
+      unfold locked at 11; g.
+      unfold locked at 10; g.
+      unfold locked at 9; g.
+      unfold locked at 8; g.
+      unfold locked at 7; g.
+      unfold locked at 6; g.
+      unfold locked at 5; g.
+      unfold locked at 4; g.
+      unfold locked at 3; g.
+      unfold locked at 2; g.
+      by unfold locked at 1; g.
     Qed.
 
     (* Let arr_seq be the periodic arrival sequence from ts. *)
diff --git a/implementation/apa/bertogna_fp_example.v b/implementation/apa/bertogna_fp_example.v
index 1a1452a67..e2dc3f547 100644
--- a/implementation/apa/bertogna_fp_example.v
+++ b/implementation/apa/bertogna_fp_example.v
@@ -131,32 +131,6 @@ Module ResponseTimeAnalysisFP.
       rewrite big_nil div0n addn0 /=.
       unfold div_floor; rewrite !set_card /=.   
 
-      have cpu0P: 0 < 2 by done.
-      have cpu1P: 1 < 2 by done.
-
-      have cpu_compute :
-        forall (P: processor num_cpus -> bool),
-          [exists x, P x] =
-            if (P (cpu 0 cpu0P)) then true else
-              if P (cpu 1 cpu1P) then true else false.
-      {
-        unfold num_cpus in *; intros P.
-        destruct (P (cpu 0 cpu0P)) eqn:P0;
-          first by apply/existsP; exists (cpu 0 cpu0P).
-        destruct (P (cpu 1 cpu1P)) eqn:P1;
-          first by apply/existsP; exists (cpu 1 cpu1P).
-        apply negbTE; rewrite negb_exists; apply/forallP.
-        intros x; destruct x as [x LE]; apply negbT.
-        have GE0 := leq0n x.
-        rewrite leq_eqVlt in GE0; move: GE0 => /orP [/eqP EQ0 | GE1];
-          first by rewrite -P0; f_equal; apply ord_inj.
-        rewrite leq_eqVlt in GE1; move: GE1 => /orP [/eqP EQ1 | GE2];
-          first by rewrite -P1; f_equal; apply ord_inj.
-        have LE' := LE.
-        apply leq_ltn_trans with (m := 2) in LE'; last by done.
-        by rewrite ltnn in LE'.
-      }
-
       set I2 := total_interference_bound_fp task_cost task_period
                         task_affinity tsk2 alpha2  [:: (tsk1, 3)].
 
@@ -164,28 +138,28 @@ Module ResponseTimeAnalysisFP.
       {
         unfold I2, total_interference_bound_fp; rewrite big_cons big_nil.
         unfold higher_priority_task_in; simpl.
-        by rewrite /affinity_intersects cpu_compute /= addn0; compute.
+        by rewrite /affinity_intersects; simpl_exists_ord; compute.
       }
       rewrite H1 !divn1 !addn1; clear H1.
       assert (H1: I2 3 (RM task_period) = 2).
       {
         unfold I2, total_interference_bound_fp; rewrite big_cons big_nil.
         unfold higher_priority_task_in; simpl.
-        by rewrite /affinity_intersects cpu_compute /= addn0; compute.
+        by rewrite /affinity_intersects; simpl_exists_ord; compute.
       }
       rewrite H1 !addn2; clear H1.
       assert (H1: I2 4 (RM task_period) = 3).
       {
         unfold I2, total_interference_bound_fp; rewrite big_cons big_nil.
         unfold higher_priority_task_in; simpl.
-        by rewrite /affinity_intersects cpu_compute /= addn0; compute.
+        by rewrite /affinity_intersects; simpl_exists_ord; compute.
       }
       rewrite H1 !addn3; clear H1.
       assert (H1: I2 5 (RM task_period) = 3).
       {
         unfold I2, total_interference_bound_fp; rewrite big_cons big_nil.
         unfold higher_priority_task_in; simpl.
-        by rewrite /affinity_intersects cpu_compute /= addn0; compute.
+        by rewrite /affinity_intersects; simpl_exists_ord; compute.
       }
       rewrite H1 !addn3; clear H1.
       have H2: 4 < 5 by compute.
@@ -206,35 +180,36 @@ Module ResponseTimeAnalysisFP.
             rewrite /total_interference_bound_fp /interference_bound_generic
                     /W /max_jobs /div_floor !big_cons big_nil /= /higher_priority_task_in /=
                     /affinity_intersects.
+
         set x9 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I9: x9 = 1 by unfold x9; g; rewrite ?cpu_compute /=; compute.
+        have I9: x9 = 1 by unfold x9; g; simpl_exists_ord; compute.
         rewrite I9 iterSr.
         set x8 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I8: x8 = 2 by unfold x8; g; rewrite ?cpu_compute /=; compute.
+        have I8: x8 = 2 by unfold x8; g; simpl_exists_ord; compute.
         rewrite I8 iterSr.
         set x7 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I7: x7 = 3 by unfold x7; g; rewrite ?cpu_compute /=; compute.
+        have I7: x7 = 3 by unfold x7; g; simpl_exists_ord; compute.
         rewrite I7 iterSr.
         set x6 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I6: x6 = 3 by unfold x6; g; rewrite ?cpu_compute /=; compute.
+        have I6: x6 = 3 by unfold x6; g; simpl_exists_ord; compute.
         rewrite I6 iterSr.
         set x5 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I5: x5 = 3 by unfold x5; g; rewrite ?cpu_compute /=; compute.
+        have I5: x5 = 3 by unfold x5; g; simpl_exists_ord; compute.
         rewrite I5 iterSr.
         set x4 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I4: x4 = 3 by unfold x4; g; rewrite ?cpu_compute /=; compute.
+        have I4: x4 = 3 by unfold x4; g; simpl_exists_ord; compute.
         rewrite I4 iterSr.
         set x3 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I3: x3 = 3 by unfold x3; g; rewrite ?cpu_compute /=; compute.
+        have I3: x3 = 3 by unfold x3; g; simpl_exists_ord; compute.
         rewrite I3 iterSr.
         set x2 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I2: x2 = 3 by unfold x2; g; rewrite ?cpu_compute /=; compute.
+        have I2: x2 = 3 by unfold x2; g; simpl_exists_ord; compute.
         rewrite I2 iterSr.
         set x1 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I1: x1 = 3 by unfold x1; g; rewrite ?cpu_compute /=; compute.
+        have I1: x1 = 3 by unfold x1; g; simpl_exists_ord; compute.
         rewrite I1 iterSr /=.
         set x0 := total_interference_bound_fp _ _ _ _ _ _ _ _.
-        have I0: x0 = 3 by unfold x0; g; rewrite ?cpu_compute /=; compute.
+        have I0: x0 = 3 by unfold x0; g; simpl_exists_ord; compute.
         by rewrite I0; compute.
       }
       by rewrite H4.
diff --git a/util/all.v b/util/all.v
index 886d33c93..0bb353a09 100644
--- a/util/all.v
+++ b/util/all.v
@@ -6,7 +6,7 @@ Require Export rt.util.bigcat.
 Require Export rt.util.bigord.
 Require Export rt.util.counting.
 Require Export rt.util.divround.
-Require Export rt.util.exists.
+Require Export rt.util.ord_quantifier.
 Require Export rt.util.fixedpoint.
 Require Export rt.util.induction.
 Require Export rt.util.list.
diff --git a/util/counting.v b/util/counting.v
index 3e6fe473a..e087732f8 100644
--- a/util/counting.v
+++ b/util/counting.v
@@ -1,4 +1,4 @@
-Require Import rt.util.tactics rt.util.exists.
+Require Import rt.util.tactics rt.util.ord_quantifier.
 From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop.
 
 (* Additional lemmas about counting. *)
diff --git a/util/exists.v b/util/exists.v
deleted file mode 100644
index 1376b4dfb..000000000
--- a/util/exists.v
+++ /dev/null
@@ -1,72 +0,0 @@
-Require Import rt.util.tactics.
-From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype.
-
-(* Lemmas about the finite existential for Ordinals: [exists x, P x]. *)
-Section OrdExists.
-
-  Lemma exists_ord0:
-    forall (T: eqType) P,
-      [exists x in 'I_0, P x] = false.
-  Proof.
-    intros T P.
-    apply negbTE; rewrite negb_exists; apply/forall_inP.
-    intros x; destruct x as [x LT].
-    by exfalso; rewrite ltn0 in LT.
-  Qed.
-
-  Lemma exists_recr:
-    forall (T: eqType) n P,
-      [exists x in 'I_n.+1, P x] =
-      [exists x in 'I_n, P (widen_ord (leqnSn n) x)] || P (ord_max).
-  Proof.
-    intros t n P.
-    apply/idP/idP.
-    {
-      move => /exists_inP EX; destruct EX as [x IN Px].
-      destruct x as [x LT].
-      remember LT as LT'; clear HeqLT'. 
-      rewrite ltnS leq_eqVlt in LT; move: LT => /orP [/eqP EQ | LT].
-      {
-        apply/orP; right.
-        unfold ord_max; subst x.
-        apply eq_trans with (y := P (Ordinal LT')); last by done.
-        by f_equal; apply ord_inj.
-      }
-      {
-        apply/orP; left.
-        apply/exists_inP; exists (Ordinal LT); first by done.
-        apply eq_trans with (y := P (Ordinal LT')); last by done.
-        by f_equal; apply ord_inj.
-      }
-    }
-    {
-      intro OR; apply/exists_inP.
-      move: OR => /orP [/exists_inP EX | MAX].
-      {
-        by destruct EX as [x IN Px]; exists (widen_ord (leqnSn n) x).
-      }
-      by exists ord_max.
-    }
-  Qed.
-
-End OrdExists.
-
-(*Section Computation.
-
-  Variable m: nat.
-  Hypothesis H_m_positive: m > 0.
-
-  Variable P: 'I_m -> bool.
-
-  Program Fixpoint compute_exists n (Q: n < m) :=
-    match n with
-    | 0 => P (@Ordinal m 0 _)
-    | S n => P (@Ordinal m (S n) _) || compute_exists n _
-    end.
-
-  Program Definition compute_exists_ordinal := compute_exists (m.-1) _.
-  Next Obligation.
-    by rewrite -(ltn_add2r 1) 2!addn1 prednK //.
-  Qed.
-
-End Computation.*)
\ No newline at end of file
diff --git a/util/ord_quantifier.v b/util/ord_quantifier.v
new file mode 100644
index 000000000..26aa8af30
--- /dev/null
+++ b/util/ord_quantifier.v
@@ -0,0 +1,101 @@
+Require Import rt.util.tactics.
+From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype.
+
+(* Lemmas about the exists for Ordinals: [exists x, P x]. *)
+Section OrdExists.
+
+  Lemma exists_ord0:
+    forall P,
+      [exists x in 'I_0, P x] = false.
+  Proof.
+    intros P.
+    apply negbTE; rewrite negb_exists; apply/forall_inP.
+    intros x; destruct x as [x LT].
+    by exfalso; rewrite ltn0 in LT.
+  Qed.
+
+  Lemma exists_recr:
+    forall n P,
+      [exists x in 'I_n.+1, P x] =
+      [exists x in 'I_n, P (widen_ord (leqnSn n) x)] || P (ord_max).
+  Proof.
+    intros n P.
+    apply/idP/idP.
+    {
+      move => /exists_inP EX; destruct EX as [x IN Px].
+      destruct x as [x LT].
+      remember LT as LT'; clear HeqLT'. 
+      rewrite ltnS leq_eqVlt in LT; move: LT => /orP [/eqP EQ | LT].
+      {
+        apply/orP; right.
+        unfold ord_max; subst x.
+        apply eq_trans with (y := P (Ordinal LT')); last by done.
+        by f_equal; apply ord_inj.
+      }
+      {
+        apply/orP; left.
+        apply/exists_inP; exists (Ordinal LT); first by done.
+        apply eq_trans with (y := P (Ordinal LT')); last by done.
+        by f_equal; apply ord_inj.
+      }
+    }
+    {
+      intro OR; apply/exists_inP.
+      move: OR => /orP [/exists_inP EX | MAX].
+      {
+        by destruct EX as [x IN Px]; exists (widen_ord (leqnSn n) x).
+      }
+      by exists ord_max.
+    }
+  Qed.
+
+End OrdExists.
+
+(* Lemmas about the forall for Ordinals: [exists x, P x]. *)
+Section OrdForall.
+
+  Lemma forall_ord0:
+    forall P,
+      [forall x in 'I_0, P x].
+  Proof.
+    intros P; apply/forall_inP.
+    by intros x IN0; destruct x.
+  Qed.
+
+  Lemma forall_recr:
+    forall n P,
+      [forall x in 'I_n.+1, P x] =
+      [forall x in 'I_n, P (widen_ord (leqnSn n) x)] && P (ord_max).
+  Proof.
+    intros n P.
+    apply/idP/idP.
+    {
+      move => /forall_inP ALL.
+      apply/andP; split; last by apply ALL.
+      by apply/forall_inP; intros x IN; apply ALL.
+    }
+    {
+      move => /andP [/forall_inP ALL MAX].
+      apply/forall_inP; intros x IN.
+      destruct x as [x LT].
+      unfold ord_max in *.
+      remember LT as LT'; clear HeqLT'.
+      rewrite ltnS leq_eqVlt in LT; move: LT => /orP [/eqP EQ | LT].
+      {
+        subst n.
+        apply/eqP; rewrite -MAX; apply/eqP.
+        by unfold ord_max; apply f_equal, ord_inj.
+      }
+      {
+        feed (ALL (Ordinal LT)); first by done.
+        apply/eqP; rewrite -ALL; apply/eqP.
+        by apply f_equal, ord_inj.
+      }
+    }
+  Qed.
+
+End OrdForall.
+
+(* Tactics for simplifying exists and forall. *)
+Ltac simpl_exists_ord := rewrite !exists_recr !exists_ord0 /=.
+Ltac simpl_forall_ord := rewrite !forall_recr !forall_ord0 /=.
\ No newline at end of file
-- 
GitLab