From Coq Require Export Program.Tactics.From Coq Require Import Eqdep_dec.
Tactic Notation "spec" hyp(H) :=
match type of H with ?a -> _ =>
let H1 := fresh in (assert (H1 : a);
[| generalize (H H1); clear H H1; intro H]) end.
∀ x : bool, x = true ↔ x∀ x : bool, x = true ↔ xx: boolx = true → xx: boolx → x = trueby apply Is_true_eq_left.x: boolx = true → xby apply Is_true_eq_true. Qed.x: boolx → x = trueA, B, C: Prop(A → B ↔ C) → A ∧ B ↔ A ∧ Cby firstorder. Qed.A, B, C: Prop(A → B ↔ C) → A ∧ B ↔ A ∧ CA, B, C: Prop(A → B ↔ C) → (A → B) ↔ (A → C)by firstorder. Qed.A, B, C: Prop(A → B ↔ C) → (A → B) ↔ (A → C)
∀ P Q : Prop, P ↔ Q → Decision P → Decision Qby firstorder. Qed. #[export] Instance bool_decision {b : bool} : Decision b := match b with | true => left I | false => right (fun H => H) end. Notation decide_eq := (fun x y => decide (x = y)).∀ P Q : Prop, P ↔ Q → Decision P → Decision Q
A: Type
R: relation A
H: Transitive R∀ a b : A, R a b ↔ tc R a bA: Type
R: relation A
H: Transitive R∀ a b : A, R a b ↔ tc R a bA: Type
R: relation A
H: Transitive R
a, b: Atc R a b → R a bby etransitivity. Qed.A: Type
R: relation A
H: Transitive R
x, y, z: A
H0: R x y
H1: tc R y z
IHtc: R y zR x z
If a relation
R
reflects a predicate P
, then its transitive
closure will also reflect it.
A: Type
R: relation A
P: A → Prop
Hreflects: ∀ dm m : A, R dm m → P m → P dm∀ dm m : A, tc R dm m → P m → P dmby induction 1; firstorder. Qed.A: Type
R: relation A
P: A → Prop
Hreflects: ∀ dm m : A, R dm m → P m → P dm∀ dm m : A, tc R dm m → P m → P dm
Characterization of tc in terms of the last transitivity step.
A: Type
R: relation A∀ x z : A, tc R x z ↔ R x z ∨ (∃ y : A, tc R x y ∧ R y z)A: Type
R: relation A∀ x z : A, tc R x z ↔ R x z ∨ (∃ y : A, tc R x y ∧ R y z)A: Type
R: relation A
x, z: Atc R x z → R x z ∨ (∃ y : A, tc R x y ∧ R y z)A: Type
R: relation A
x, z: AR x z ∨ (∃ y : A, tc R x y ∧ R y z) → tc R x zA: Type
R: relation A
x, z: Atc R x z → R x z ∨ (∃ y : A, tc R x y ∧ R y z)A: Type
R: relation A
x, z: A
n: nat
Hn: 0 < n
Hsteps: nsteps R n x zR x z ∨ (∃ y : A, tc R x y ∧ R y z)A: Type
R: relation A
n: nat
Hn: 0 < S n
x, y, z: A
H: R x y
Hsteps: nsteps R n y z
IHHsteps: 0 < n → R y z ∨ (∃ y0 : A, tc R y y0 ∧ R y0 z)R x z ∨ (∃ y : A, tc R x y ∧ R y z)A: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
IHHsteps: 0 < S n → R y z ∨ (∃ y0 : A, tc R y y0 ∧ R y0 z)R x z ∨ (∃ y : A, tc R x y ∧ R y z)A: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
Hyz: R y z∃ y : A, tc R x y ∧ R y zA: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
y0: A
Hyy0: tc R y y0
Hy0z: R y0 z∃ y : A, tc R x y ∧ R y zby exists y; split; [constructor |].A: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
Hyz: R y z∃ y : A, tc R x y ∧ R y zA: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
y0: A
Hyy0: tc R y y0
Hy0z: R y0 z∃ y : A, tc R x y ∧ R y zA: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
y0: A
Hyy0: tc R y y0
Hy0z: R y0 ztc R x y0A: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
y0: A
Hyy0: tc R y y0
Hy0z: R y0 z∃ n : nat, 0 < n ∧ nsteps R n x y0A: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
y0: A
m: nat
Hm: 0 < m
Hyy0: nsteps R m y y0
Hy0z: R y0 z∃ n : nat, 0 < n ∧ nsteps R n x y0by econstructor.A: Type
R: relation A
n: nat
Hn: 0 < S (S n)
x, y, z: A
H: R x y
Hsteps: nsteps R (S n) y z
y0: A
m: nat
Hm: 0 < m
Hyy0: nsteps R m y y0
Hy0z: R y0 znsteps R (S m) x y0A: Type
R: relation A
x, z: AR x z ∨ (∃ y : A, tc R x y ∧ R y z) → tc R x zby eapply tc_r. Qed.A: Type
R: relation A
x, z, y: A
Hxy: tc R x y
Hyz: R y ztc R x zA: Type
R1: relation A
B: Type
R2: relation B
Transitive0: Transitive R2
f: A → B(∀ x y : A, R1 x y → R2 (f x) (f y)) → wf R2 → wf (tc R1)A: Type
R1: relation A
B: Type
R2: relation B
Transitive0: Transitive R2
f: A → B(∀ x y : A, R1 x y → R2 (f x) (f y)) → wf R2 → wf (tc R1)A: Type
R1: relation A
B: Type
R2: relation B
Transitive0: Transitive R2
f: A → B
Hpreserve: ∀ x y : A, R1 x y → R2 (f x) (f y)wf R2 → wf (tc R1)A: Type
R1: relation A
B: Type
R2: relation B
Transitive0: Transitive R2
f: A → B
Hpreserve: ∀ x y : A, R1 x y → R2 (f x) (f y)∀ x y : A, tc R1 x y → R2 (f x) (f y)A: Type
R1: relation A
B: Type
R2: relation B
Transitive0: Transitive R2
f: A → B
Hpreserve: ∀ x y : A, R1 x y → R2 (f x) (f y)
x, y, z: A
H: R1 x y
H0: tc R1 y z
IHtc: R2 (f y) (f z)R2 (f x) (f z)by apply Hpreserve. Qed.A: Type
R1: relation A
B: Type
R2: relation B
Transitive0: Transitive R2
f: A → B
Hpreserve: ∀ x y : A, R1 x y → R2 (f x) (f y)
x, y, z: A
H: R1 x y
H0: tc R1 y z
IHtc: R2 (f y) (f z)R2 (f x) (f y)A: Type
R: relation A
Irreflexive0: Irreflexive (tc R)Irreflexive RA: Type
R: relation A
Irreflexive0: Irreflexive (tc R)Irreflexive Rby eapply irreflexivity with (R := tc R); [| constructor]. Qed.A: Type
R: relation A
Irreflexive0: Irreflexive (tc R)
x: A
H: R x xFalseA: Type
R1: relation A
B: Type
R2: relation B
f: A → BProper (R1 ==> R2) f → Irreflexive R2 → Irreflexive R1A: Type
R1: relation A
B: Type
R2: relation B
f: A → BProper (R1 ==> R2) f → Irreflexive R2 → Irreflexive R1by apply Hirreflexive with (f x), Hproper. Qed.A: Type
R1: relation A
B: Type
R2: relation B
f: A → B
Hproper: Proper (R1 ==> R2) f
Hirreflexive: Irreflexive R2
x: A
Hx: R1 x xFalseA: Type
R1: relation A
B: Type
R2: relation B
f: A → B
Transitive0: Transitive R2Proper (R1 ==> R2) f → Proper (tc R1 ==> R2) fA: Type
R1: relation A
B: Type
R2: relation B
f: A → B
Transitive0: Transitive R2Proper (R1 ==> R2) f → Proper (tc R1 ==> R2) fby etransitivity; [apply Hproper |]. Qed.A: Type
R1: relation A
B: Type
R2: relation B
f: A → B
Transitive0: Transitive R2
Hproper: Proper (R1 ==> R2) f
x, y, z: A
H: R1 x y
Hxy: tc R1 y z
IHHxy: R2 (f y) (f z)R2 (f x) (f z)
A: Type
P: A → Prop
a: A(∃ xP : {x : A | P x}, `xP = a) ↔ P aA: Type
P: A → Prop
a: A(∃ xP : {x : A | P x}, `xP = a) ↔ P aA: Type
P: A → Prop
a: A(∃ xP : {x : A | P x}, `xP = a) → P aA: Type
P: A → Prop
a: AP a → ∃ xP : {x : A | P x}, `xP = aby intros [[x Hx] [= ->]].A: Type
P: A → Prop
a: A(∃ xP : {x : A | P x}, `xP = a) → P aby intro Ha; exists (exist _ a Ha). Qed.A: Type
P: A → Prop
a: AP a → ∃ xP : {x : A | P x}, `xP = aA: Type
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
a: dsig P∃ (a' : A) (e : P a'), a = dexist a' eby exists (proj1_sig a), (proj2_dsig a); apply dsig_eq. Qed. Ltac destruct_dec_sig a a' e H := pose proof (dec_sig_to_exist a) as (a' & e & H).A: Type
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
a: dsig P∃ (a' : A) (e : P a'), a = dexist a' eA: Type
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a
pa1:= dexist a e1: dsig P
pa2:= dexist a e2: dsig P
Heqb: b1 = b2existT pa1 b1 = existT pa2 b2A: Type
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a
pa1:= dexist a e1: dsig P
pa2:= dexist a e2: dsig P
Heqb: b1 = b2existT pa1 b1 = existT pa2 b2A: Type
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1: F a
e1, e2: P aexistT (dexist a e1) b1 = existT (dexist a e2) b1A: Type
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1: F a
e1, e2: P aexistT (a ↾ bool_decide_pack (P a) e1) b1 = existT (a ↾ bool_decide_pack (P a) e2) b1by apply proof_irrel. Qed.A: Type
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1: F a
e1, e2: P abool_decide_pack (P a) e2 = bool_decide_pack (P a) e1A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a
pa1:= dexist a e1: dsig P
pa2:= dexist a e2: dsig PexistT pa1 b1 = existT pa2 b2 → b1 = b2A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a
pa1:= dexist a e1: dsig P
pa2:= dexist a e2: dsig PexistT pa1 b1 = existT pa2 b2 → b1 = b2A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P aexistT (dexist a e1) b1 = existT (dexist a e2) b2 → b1 = b2A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P aexistT (a ↾ bool_decide_pack (P a) e1) b1 = existT (a ↾ bool_decide_pack (P a) e2) b2 → b1 = b2A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P aexistT (a ↾ bool_decide_pack (P a) e2) b1 = existT (a ↾ bool_decide_pack (P a) e2) b2 → b1 = b2A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a∀ x y : dsig P, {x = y} + {x ≠ y}A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a
x, y: dsig P
e: `x = `y{x = y} + {x ≠ y}A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a
x, y: dsig P
n: `x ≠ `y{x = y} + {x ≠ y}by left; apply dsig_eq.A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a
x, y: dsig P
e: `x = `y{x = y} + {x ≠ y}by right; intros ->. Qed. (* https://coq.discourse.group/t/writing-equality-decision-that-reduces-dec-x-x-for-opaque-x/551/2 *)A: Type
EqDecision0: EqDecision A
P: A → Prop
P_dec: ∀ x : A, Decision (P x)
F: A → Type
a: A
b1, b2: F a
e1, e2: P a
x, y: dsig P
n: `x ≠ `y{x = y} + {x ≠ y}∀ (A : Type) (eq_dec : ∀ x y : A, {x = y} + {x ≠ y}) (x : A), eq_dec x x = left eq_refl∀ (A : Type) (eq_dec : ∀ x y : A, {x = y} + {x ≠ y}) (x : A), eq_dec x x = left eq_reflA: Type
eq_dec: ∀ x y : A, {x = y} + {x ≠ y}
x: Aeq_dec x x = left eq_reflby rewrite K_dec_type with (P := fun prf => prf = eq_refl). Qed.A: Type
eq_dec: ∀ x y : A, {x = y} + {x ≠ y}
x: A
e: x = xleft e = left eq_refl
A minimal element of a subset
S
(defined by a predicate P
) of some
preordered set is defined as an element of S that is not greater than any other
element in S.
Definition minimal_among `(R : relation A) (P : A -> Prop) (m : A) : Prop := P m /\ (forall m', P m' -> R m' m -> R m m').minimal_among le (const True) 0by split; [| lia]. Qed. Section sec_find_least_among.minimal_among le (const True) 0
Given a decidable property on naturals and a natural number on which the
property holds, we can compute the least natural number on which it holds.
Context (P : nat -> Prop) `{forall n, Decision (P n)} (bound : nat) (Hbound : P bound). #[local] Fixpoint find_least_among_helper (dif : nat) : nat := match dif with | 0 => bound | S dif' => if decide (P (bound - dif)) then bound - dif else find_least_among_helper dif' end. Definition find_least_among : nat := find_least_among_helper bound.P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound∀ n : nat, bound - n <= find_least_among_helper n <= boundby induction n; cbn; [| case_decide]; lia. Qed.P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound∀ n : nat, bound - n <= find_least_among_helper n <= boundP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound∀ n : nat, P (find_least_among_helper n)by induction n; cbn; [| case_decide]. Qed.P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound∀ n : nat, P (find_least_among_helper n)P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound∀ n m : nat, bound - n <= m <= bound → m < find_least_among_helper n → ¬ P mP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound∀ n m : nat, bound - n <= m <= bound → m < find_least_among_helper n → ¬ P mP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: nat
IHn: ∀ m : nat, bound - n <= m <= bound → m < find_least_among_helper n → ¬ P m∀ m : nat, bound - S n <= m <= bound → m < (if decide (P (bound - S n)) then bound - S n else find_least_among_helper n) → ¬ P mP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: nat
IHn: ∀ m : nat, bound - n <= m <= bound → m < find_least_among_helper n → ¬ P m
H0: ¬ P (bound - S n)∀ m : nat, bound - S n <= m <= bound → m < find_least_among_helper n → ¬ P mP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: nat
IHn: ∀ m : nat, bound - n <= m <= bound → m < find_least_among_helper n → ¬ P m
H0: ¬ P (bound - S n)
m: nat
H1: bound - S n <= m <= bound
H2: m < find_least_among_helper n¬ P mby apply IHn; lia. Qed.P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: nat
IHn: ∀ m : nat, bound - n <= m <= bound → m < find_least_among_helper n → ¬ P m
H0: ¬ P (bound - S n)
m: nat
H1: bound - S n <= m <= bound
H2: m < find_least_among_helper n
n0: m ≠ bound - S n¬ P mP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound∀ n : nat, minimal_among le (λ m : nat, bound - n <= m <= bound ∧ P m) (find_least_among_helper n)P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound∀ n : nat, minimal_among le (λ m : nat, bound - n <= m <= bound ∧ P m) (find_least_among_helper n)P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: natbound - n <= find_least_among_helper n <= boundP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: natP (find_least_among_helper n)P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: nat∀ m' : nat, bound - n <= m' <= bound ∧ P m' → m' ≤ find_least_among_helper n → find_least_among_helper n ≤ m'by apply find_least_among_helper_bounded.P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: natbound - n <= find_least_among_helper n <= boundby apply find_least_among_helper_has_property.P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: natP (find_least_among_helper n)P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n: nat∀ m' : nat, bound - n <= m' <= bound ∧ P m' → m' ≤ find_least_among_helper n → find_least_among_helper n ≤ m'P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n, m': nat
Hm': bound - n <= m' <= bound
Hpm': P m'
Hle: m' ≤ find_least_among_helper nfind_least_among_helper n ≤ m'by exfalso; eapply find_least_among_helper_minimal with n m'; [| lia |]. Qed.P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
n, m': nat
Hm': bound - n <= m' <= bound
Hpm': P m'
Hle: m' ≤ find_least_among_helper n
n0: find_least_among_helper n ≠ m'find_least_among_helper n ≤ m'P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P boundminimal_among le P find_least_amongP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P boundminimal_among le P find_least_amongP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
H0: find_least_among_helper bound ≤ bound
H1: P (find_least_among_helper bound)
Hmin': ∀ m' : nat, bound - bound <= m' <= bound ∧ P m' → m' ≤ find_least_among_helper bound → find_least_among_helper bound ≤ m'minimal_among le P find_least_amongP: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
H0: find_least_among_helper bound ≤ bound
H1: P (find_least_among_helper bound)
Hmin': ∀ m' : nat, bound - bound <= m' <= bound ∧ P m' → m' ≤ find_least_among_helper bound → find_least_among_helper bound ≤ m'∀ m' : nat, P m' → m' ≤ find_least_among → find_least_among ≤ m'P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
H0: find_least_among_helper bound ≤ bound
H1: P (find_least_among_helper bound)
Hmin': ∀ m' : nat, bound - bound <= m' <= bound ∧ P m' → m' ≤ find_least_among_helper bound → find_least_among_helper bound ≤ m'
m': nat
H2: P m'
H3: m' ≤ find_least_amongbound - bound <= m' <= bound ∧ P m'P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
H0: find_least_among_helper bound ≤ bound
H1: P (find_least_among_helper bound)
Hmin': ∀ m' : nat, bound - bound <= m' <= bound ∧ P m' → m' ≤ find_least_among_helper bound → find_least_among_helper bound ≤ m'
m': nat
H2: P m'
H3: m' ≤ find_least_amongbound - bound <= m' <= boundby etransitivity. Qed. End sec_find_least_among.P: nat → Prop
H: ∀ n : nat, Decision (P n)
bound: nat
Hbound: P bound
H0: find_least_among_helper bound ≤ bound
H1: P (find_least_among_helper bound)
Hmin': ∀ m' : nat, bound - bound <= m' <= bound ∧ P m' → m' ≤ find_least_among_helper bound → find_least_among_helper bound ≤ m'
m': nat
H2: P m'
H3: m' ≤ find_least_amongm' ≤ bound
A more concise definition of minimality for strict orders.
Definition strict_minimal_among `(R : relation A) (P : A -> Prop) (m : A) : Prop := P m /\ (forall m', P m' -> ~ R m' m).minimal_among lt (const True) 0by split; [| lia]. Qed.minimal_among lt (const True) 0
The minimality definitions are equivalent for Asymmetric relations.
A: Type
R: relation A
Asymmetric0: Asymmetric R
P: A → Prop∀ m : A, minimal_among R P m ↔ strict_minimal_among R P mA: Type
R: relation A
Asymmetric0: Asymmetric R
P: A → Prop∀ m : A, minimal_among R P m ↔ strict_minimal_among R P mby firstorder. Qed.A: Type
R: relation A
Asymmetric0: Asymmetric R
P: A → Prop(∀ x y : A, R x y → R y x → False) → ∀ m : A, P m ∧ (∀ m' : A, P m' → R m' m → R m m') ↔ P m ∧ (∀ m' : A, P m' → ¬ R m' m)
The minimality definitions are equivalent for StrictOrders.
A: Type
R: relation A
StrictOrder0: StrictOrder R
P: A → Prop∀ m : A, minimal_among R P m ↔ strict_minimal_among R P mby apply asymmetric_minimal_among_iff; typeclasses eauto. Qed.A: Type
R: relation A
StrictOrder0: StrictOrder R
P: A → Prop∀ m : A, minimal_among R P m ↔ strict_minimal_among R P m
Dually, a maximal element is a minimal element w.r.t. the inverse relation.
Definition maximal_among `(R : relation A) := minimal_among (flip R). Definition strict_maximal_among `(R : relation A) := strict_minimal_among (flip R).
Class CompareReflexive {A} (compare : A -> A -> comparison) : Prop := compare_eq : forall x y, compare x y = Eq <-> x = y. #[global] Hint Mode CompareReflexive ! - : typeclass_instances.A: Type
compare: A → A → comparison
H: CompareReflexive compare∀ x : A, compare x x = Eqby intros; apply H. Qed.A: Type
compare: A → A → comparison
H: CompareReflexive compare∀ x : A, compare x x = Eq
Class CompareTransitive {A} (compare : A -> A -> comparison) : Prop := compare_transitive : forall x y z c, compare x y = c -> compare y z = c -> compare x z = c. #[global] Hint Mode CompareTransitive ! - : typeclass_instances.
#[global] Hint Mode CompareStrictOrder ! - : typeclass_instances.
Strictly-ordered comparisons entail decidable equality.
A: Type
compare: A → A → comparison
H: CompareStrictOrder compareEqDecision AA: Type
compare: A → A → comparison
H: CompareStrictOrder compareEqDecision AA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hxy: compare x y = EqDecision (x = y)A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hxy: compare x y = LtDecision (x = y)A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hxy: compare x y = GtDecision (x = y)by left; apply compare_eq.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hxy: compare x y = EqDecision (x = y)by right; intros ->; rewrite compare_eq_refl in Hxy.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hxy: compare x y = LtDecision (x = y)by right; intros ->; rewrite compare_eq_refl in Hxy. Qed.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hxy: compare x y = GtDecision (x = y)
Class CompareAsymmetric {A} (compare : A -> A -> comparison) : Prop := compare_asymmetric : forall x y, compare x y = CompOpp (compare y x). #[global] Hint Mode CompareAsymmetric ! - : typeclass_instances.A: Type
compare: A → A → comparison
H: CompareAsymmetric compare∀ x y : A, compare x y = Lt ↔ compare y x = GtA: Type
compare: A → A → comparison
H: CompareAsymmetric compare∀ x y : A, compare x y = Lt ↔ compare y x = GtA: Type
compare: A → A → comparison
H: CompareAsymmetric compare
x, y: Acompare x y = Lt ↔ compare y x = Gtby destruct (compare y x); cbn; firstorder congruence. Qed.A: Type
compare: A → A → comparison
H: CompareAsymmetric compare
x, y: ACompOpp (compare y x) = Lt ↔ compare y x = Gt
Strictly-ordered comparisons are asymmetric.
A: Type
compare: A → A → comparison
H: CompareStrictOrder compareCompareAsymmetric compareA: Type
compare: A → A → comparison
H: CompareStrictOrder compareCompareAsymmetric compareA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Eqcompare x y = CompOpp EqA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Ltcompare x y = CompOpp LtA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Gtcompare x y = CompOpp Gtby rewrite compare_eq in *.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Eqcompare x y = CompOpp EqA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Ltcompare x y = CompOpp LtA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Lt
Hxy: compare x y = EqEq = GtA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Lt
Hxy: compare x y = LtLt = Gtby apply compare_eq in Hxy; subst; rewrite compare_eq_refl in Hyx.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Lt
Hxy: compare x y = EqEq = GtA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Lt
Hxy: compare x y = LtLt = Gtby rewrite compare_eq_refl in Hxx.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Lt
Hxy: compare x y = Lt
Hxx: compare x x = LtLt = GtA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Gtcompare x y = CompOpp GtA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Gt
Hxy: compare x y = EqEq = LtA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Gt
Hxy: compare x y = GtGt = Ltby apply compare_eq in Hxy; subst; rewrite compare_eq_refl in Hyx.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Gt
Hxy: compare x y = EqEq = LtA: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Gt
Hxy: compare x y = GtGt = Ltby rewrite compare_eq_refl in Hxx. Qed.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hyx: compare y x = Gt
Hxy: compare x y = Gt
Hxx: compare x x = GtGt = Lt
compare_lt is the relation that corresponds to
compare
.
Definition compare_lt {A} (compare : A -> A -> comparison) (x y : A) : Prop := compare x y = Lt.A: Type
compare: A → A → comparison
Hord: CompareStrictOrder compareRelDecision (compare_lt compare)A: Type
compare: A → A → comparison
Hord: CompareStrictOrder compareRelDecision (compare_lt compare)by typeclasses eauto. Qed.A: Type
compare: A → A → comparison
Hord: CompareStrictOrder compare
x, y: ADecision (compare x y = Lt)
A: Type
compare: A → A → comparison
H: CompareReflexive compareIrreflexive (compare_lt compare)by intros x; compute; rewrite compare_eq_refl. Qed.A: Type
compare: A → A → comparison
H: CompareReflexive compareIrreflexive (compare_lt compare)A: Type
compare: A → A → comparison
H: CompareTransitive compareTransitive (compare_lt compare)by intros x y z Hxy Hyz; eapply compare_transitive. Qed.A: Type
compare: A → A → comparison
H: CompareTransitive compareTransitive (compare_lt compare)A: Type
compare: A → A → comparison
H: CompareStrictOrder compareStrictOrder (compare_lt compare)A: Type
compare: A → A → comparison
H: CompareStrictOrder compareStrictOrder (compare_lt compare)A: Type
compare: A → A → comparison
H: CompareStrictOrder compareIrreflexive (compare_lt compare)A: Type
compare: A → A → comparison
H: CompareStrictOrder compareTransitive (compare_lt compare)by apply compare_lt_irreflexive.A: Type
compare: A → A → comparison
H: CompareStrictOrder compareIrreflexive (compare_lt compare)by apply compare_lt_transitive. Qed.A: Type
compare: A → A → comparison
H: CompareStrictOrder compareTransitive (compare_lt compare)A: Type
compare: A → A → comparison
H: CompareStrictOrder compareAsymmetric (compare_lt compare)A: Type
compare: A → A → comparison
H: CompareStrictOrder compareAsymmetric (compare_lt compare)A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hxy: compare x y = Lt
Hyx: compare y x = LtFalseby rewrite compare_eq_refl in Hxx. Qed.A: Type
compare: A → A → comparison
H: CompareStrictOrder compare
x, y: A
Hxy: compare x y = Lt
Hyx: compare y x = Lt
Hxx: compare x x = LtFalse
#[global] Hint Mode StrictlyComparable ! : typeclass_instances. Definition comparable `(R : relation A) : relation A := fun x y => exists c, CompSpec (=) R x y c.∀ (A : Type) (Peq Plt : relation A) (a b : A) (c : comparison), CompSpec Peq Plt a b c → CompSpec Peq (tc Plt) a b cby intros *; inversion 1; subst; repeat constructor. Qed.∀ (A : Type) (Peq Plt : relation A) (a b : A) (c : comparison), CompSpec Peq Plt a b c → CompSpec Peq (tc Plt) a b c∀ (A : Type) (R : relation A) (a b : A), comparable R a b → comparable (tc R) a bby intros *; inversion 1; subst; econstructor; apply tc_CompSpec. Qed.∀ (A : Type) (R : relation A) (a b : A), comparable R a b → comparable (tc R) a bA: Type
R: A → A → PropSymmetric (comparable R)A: Type
R: A → A → PropSymmetric (comparable R)A: Type
R: A → A → Prop
b: A
Hc: CompSpec eq R b b Eqcomparable R b bA: Type
R: A → A → Prop
a, b: A
Hc: CompSpec eq R a b Lt
H: R a bcomparable R b aA: Type
R: A → A → Prop
a, b: A
Hc: CompSpec eq R a b Gt
H: R b acomparable R b aby eexists.A: Type
R: A → A → Prop
b: A
Hc: CompSpec eq R b b Eqcomparable R b bby exists Gt; constructor.A: Type
R: A → A → Prop
a, b: A
Hc: CompSpec eq R a b Lt
H: R a bcomparable R b aby exists Lt; constructor. Qed.A: Type
R: A → A → Prop
a, b: A
Hc: CompSpec eq R a b Gt
H: R b acomparable R b aA: Type
R: A → A → PropReflexive (comparable R)by intro; exists Eq; constructor. Qed.A: Type
R: A → A → PropReflexive (comparable R)A: Type
R: relation A
EqDecision0: EqDecision A
RelDecision0: RelDecision RRelDecision (comparable R)A: Type
R: relation A
EqDecision0: EqDecision A
RelDecision0: RelDecision RRelDecision (comparable R)A: Type
R: relation A
EqDecision0: EqDecision A
RelDecision0: RelDecision R
a, b: ADecision (comparable R a b)A: Type
R: relation A
EqDecision0: EqDecision A
RelDecision0: RelDecision R
a, b: A
n: a ≠ bDecision (comparable R a b)A: Type
R: relation A
EqDecision0: EqDecision A
RelDecision0: RelDecision R
a, b: A
n: a ≠ b
n0: ¬ R a bDecision (comparable R a b)by right; intros [c Hc]; inversion Hc. Qed.A: Type
R: relation A
EqDecision0: EqDecision A
RelDecision0: RelDecision R
a, b: A
n: a ≠ b
n0: ¬ R a b
n1: ¬ R b aDecision (comparable R a b)
Definition dsig_compare {X} `{StrictlyComparable X} (P : X -> Prop) {Pdec : forall x, Decision (P x)} (x y : dsig P) : comparison := compare (`x) (`y).X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareReflexive (dsig_compare P)by intros x y; unfold dsig_compare; rewrite dsig_eq, compare_eq. Qed.X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareReflexive (dsig_compare P)X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareTransitive (dsig_compare P)by intros x y z; unfold dsig_compare; apply compare_transitive. Qed.X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareTransitive (dsig_compare P)X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareStrictOrder (dsig_compare P)X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareStrictOrder (dsig_compare P)X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareReflexive (dsig_compare P)X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareTransitive (dsig_compare P)by apply dsig_compare_reflexive.X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareReflexive (dsig_compare P)by apply dsig_compare_transitive. Qed. #[export] Instance StrictlyComparable_dsig {X} `{StrictlyComparable X} (P : X -> Prop) {Pdec : forall x, Decision (P x)} {Inh : Inhabited (dsig P)} : StrictlyComparable (dsig P) := { compare := dsig_compare P; compare_strictorder := CompareStrictOrder_dsig_compare P }.X: Type
H: StrictlyComparable X
P: X → Prop
Pdec: ∀ x : X, Decision (P x)CompareTransitive (dsig_compare P)
Definition option_compare (X : Type) `{StrictlyComparable X} (ox oy : option X) : comparison := match ox, oy with | None, None => Eq | None, _ => Lt | _, None => Gt | Some x, Some y => compare x y end.X: Type
H: StrictlyComparable XCompareReflexive (option_compare X)by intros [x |] [y |]; cbn; rewrite ?compare_eq; firstorder congruence. Qed.X: Type
H: StrictlyComparable XCompareReflexive (option_compare X)X: Type
H: StrictlyComparable XCompareTransitive (option_compare X)X: Type
H: StrictlyComparable XCompareTransitive (option_compare X)X: Type
H: StrictlyComparable X
x, y, z: X
Hxy: compare x y = Eq
Hyz: compare y z = Eqcompare x z = EqX: Type
H: StrictlyComparable X
x, y, z: X
Hxy: compare x y = Lt
Hyz: compare y z = Ltcompare x z = LtX: Type
H: StrictlyComparable X
x, y, z: X
Hxy: compare x y = Gt
Hyz: compare y z = Gtcompare x z = Gtby apply (compare_transitive x y z).X: Type
H: StrictlyComparable X
x, y, z: X
Hxy: compare x y = Eq
Hyz: compare y z = Eqcompare x z = Eqby apply (compare_transitive x y z).X: Type
H: StrictlyComparable X
x, y, z: X
Hxy: compare x y = Lt
Hyz: compare y z = Ltcompare x z = Ltby apply (compare_transitive x y z). Qed.X: Type
H: StrictlyComparable X
x, y, z: X
Hxy: compare x y = Gt
Hyz: compare y z = Gtcompare x z = GtX: Type
H: StrictlyComparable XCompareStrictOrder (option_compare X)X: Type
H: StrictlyComparable XCompareStrictOrder (option_compare X)X: Type
H: StrictlyComparable XCompareReflexive (option_compare X)X: Type
H: StrictlyComparable XCompareTransitive (option_compare X)by apply option_compare_reflexive.X: Type
H: StrictlyComparable XCompareReflexive (option_compare X)by apply option_compare_transitive. Qed. #[export] Instance StrictlyComparable_option (X : Type) `{StrictlyComparable X} : StrictlyComparable (option X) := { compare := option_compare X; compare_strictorder := CompareStrictOrder_option_compare _; }.X: Type
H: StrictlyComparable XCompareTransitive (option_compare X)
Definition pair_compare (X Y : Type) `{StrictlyComparable X} `{StrictlyComparable Y} : (X * Y) -> (X * Y) -> comparison := fun '(x1, y1) '(x2, y2) => match compare x1 x2 with | Eq => compare y1 y2 | c => c end.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareReflexive (pair_compare X Y)X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareReflexive (pair_compare X Y)X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Ymatch compare x1 x2 with | Eq => compare y1 y2 | Lt => Lt | Gt => Gt end = Eq → (x1, y1) = (x2, y2)X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y(x1, y1) = (x2, y2) → match compare x1 x2 with | Eq => compare y1 y2 | Lt => Lt | Gt => Gt end = EqX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Ymatch compare x1 x2 with | Eq => compare y1 y2 | Lt => Lt | Gt => Gt end = Eq → (x1, y1) = (x2, y2)by apply compare_eq in Hx, Hy; subst.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
Hx: compare x1 x2 = Eq
Hy: compare y1 y2 = Eq(x1, y1) = (x2, y2)by intros [= -> ->]; cbn; rewrite !compare_eq_refl. Qed.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y(x1, y1) = (x2, y2) → match compare x1 x2 with | Eq => compare y1 y2 | Lt => Lt | Gt => Gt end = EqX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y∀ (x1 x2 : X) (y1 y2 : Y) (c : comparison), pair_compare X Y (x1, y1) (x2, y2) = c → compare x1 x2 = c ∨ x1 = x2 ∧ compare y1 y2 = cX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y∀ (x1 x2 : X) (y1 y2 : Y) (c : comparison), pair_compare X Y (x1, y1) (x2, y2) = c → compare x1 x2 = c ∨ x1 = x2 ∧ compare y1 y2 = cX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1, x2: X
y1, y2: Y
c: comparison
Hcmp: match compare x1 x2 with | Eq => compare y1 y2 | Lt => Lt | Gt => Gt end = ccompare x1 x2 = c ∨ x1 = x2 ∧ compare y1 y2 = cby destruct (compare x1 x2), (compare y1 y2); auto. Qed.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1, x2: X
y1, y2: Y
c: comparison
Hcmp: match compare x1 x2 with | Eq => compare y1 y2 | Lt => Lt | Gt => Gt end = ccompare x1 x2 = c ∨ compare x1 x2 = Eq ∧ compare y1 y2 = cX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareTransitive (pair_compare X Y)X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareTransitive (pair_compare X Y)X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H12: pair_compare X Y (x1, y1) (x2, y2) = comp
H23: pair_compare X Y (x2, y2) (x3, y3) = comppair_compare X Y (x1, y1) (x3, y3) = compX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Eq
H12: pair_compare X Y (x1, y1) (x2, y2) = Eq
H23: pair_compare X Y (x2, y2) (x3, y3) = Eqpair_compare X Y (x1, y1) (x3, y3) = EqX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
H12: pair_compare X Y (x1, y1) (x2, y2) = Lt
H23: pair_compare X Y (x2, y2) (x3, y3) = Ltpair_compare X Y (x1, y1) (x3, y3) = LtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
H12: pair_compare X Y (x1, y1) (x2, y2) = Gt
H23: pair_compare X Y (x2, y2) (x3, y3) = Gtpair_compare X Y (x1, y1) (x3, y3) = Gtby apply pair_compare_reflexive; apply pair_compare_reflexive in H12, H23; congruence.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Eq
H12: pair_compare X Y (x1, y1) (x2, y2) = Eq
H23: pair_compare X Y (x2, y2) (x3, y3) = Eqpair_compare X Y (x1, y1) (x3, y3) = EqX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
H12: pair_compare X Y (x1, y1) (x2, y2) = Lt
H23: pair_compare X Y (x2, y2) (x3, y3) = Ltpair_compare X Y (x1, y1) (x3, y3) = LtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
H12: pair_compare X Y (x1, y1) (x2, y2) = Lt
H23: pair_compare X Y (x2, y2) (x3, y3) = Lt
left: compare x1 x2 = Lt
left': compare x2 x3 = Ltmatch compare x1 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = LtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1, y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
left: compare x1 x3 = Lt
H23: pair_compare X Y (x3, y2) (x3, y3) = Lt
H12: pair_compare X Y (x1, y1) (x3, y2) = Lt
right': compare y2 y3 = Ltmatch compare x1 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = LtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
H12: pair_compare X Y (x2, y1) (x2, y2) = Lt
H23: pair_compare X Y (x2, y2) (x3, y3) = Lt
right: compare y1 y2 = Lt
left': compare x2 x3 = Ltmatch compare x2 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = LtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
y1, y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
H23: pair_compare X Y (x3, y2) (x3, y3) = Lt
H12: pair_compare X Y (x3, y1) (x3, y2) = Lt
right: compare y1 y2 = Lt
right': compare y2 y3 = Ltmatch compare x3 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = Ltby replace (compare x1 x3) with Lt by (symmetry; eapply compare_transitive; done).X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
H12: pair_compare X Y (x1, y1) (x2, y2) = Lt
H23: pair_compare X Y (x2, y2) (x3, y3) = Lt
left: compare x1 x2 = Lt
left': compare x2 x3 = Ltmatch compare x1 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = Ltby rewrite left.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1, y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
left: compare x1 x3 = Lt
H23: pair_compare X Y (x3, y2) (x3, y3) = Lt
H12: pair_compare X Y (x1, y1) (x3, y2) = Lt
right': compare y2 y3 = Ltmatch compare x1 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = Ltby rewrite left'.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
H12: pair_compare X Y (x2, y1) (x2, y2) = Lt
H23: pair_compare X Y (x2, y2) (x3, y3) = Lt
right: compare y1 y2 = Lt
left': compare x2 x3 = Ltmatch compare x2 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = Ltby rewrite compare_eq_refl; eapply compare_transitive.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
y1, y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Lt
H23: pair_compare X Y (x3, y2) (x3, y3) = Lt
H12: pair_compare X Y (x3, y1) (x3, y2) = Lt
right: compare y1 y2 = Lt
right': compare y2 y3 = Ltmatch compare x3 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = LtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
H12: pair_compare X Y (x1, y1) (x2, y2) = Gt
H23: pair_compare X Y (x2, y2) (x3, y3) = Gtpair_compare X Y (x1, y1) (x3, y3) = GtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
H12: pair_compare X Y (x1, y1) (x2, y2) = Gt
H23: pair_compare X Y (x2, y2) (x3, y3) = Gt
left: compare x1 x2 = Gt
left': compare x2 x3 = Gtmatch compare x1 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = GtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1, y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
left: compare x1 x3 = Gt
H23: pair_compare X Y (x3, y2) (x3, y3) = Gt
H12: pair_compare X Y (x1, y1) (x3, y2) = Gt
right': compare y2 y3 = Gtmatch compare x1 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = GtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
H12: pair_compare X Y (x2, y1) (x2, y2) = Gt
H23: pair_compare X Y (x2, y2) (x3, y3) = Gt
right: compare y1 y2 = Gt
left': compare x2 x3 = Gtmatch compare x2 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = GtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
y1, y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
H23: pair_compare X Y (x3, y2) (x3, y3) = Gt
H12: pair_compare X Y (x3, y1) (x3, y2) = Gt
right: compare y1 y2 = Gt
right': compare y2 y3 = Gtmatch compare x3 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = Gtby replace (compare x1 x3) with Gt by (symmetry; eapply compare_transitive; done).X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
H12: pair_compare X Y (x1, y1) (x2, y2) = Gt
H23: pair_compare X Y (x2, y2) (x3, y3) = Gt
left: compare x1 x2 = Gt
left': compare x2 x3 = Gtmatch compare x1 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = Gtby rewrite left.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
x1: X
y1, y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
left: compare x1 x3 = Gt
H23: pair_compare X Y (x3, y2) (x3, y3) = Gt
H12: pair_compare X Y (x1, y1) (x3, y2) = Gt
right': compare y2 y3 = Gtmatch compare x1 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = Gtby rewrite left'.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
y1: Y
x2: X
y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
H12: pair_compare X Y (x2, y1) (x2, y2) = Gt
H23: pair_compare X Y (x2, y2) (x3, y3) = Gt
right: compare y1 y2 = Gt
left': compare x2 x3 = Gtmatch compare x2 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = Gtby rewrite compare_eq_refl; eapply compare_transitive. Qed.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable Y
y1, y2: Y
x3: X
y3: Y
comp: comparison
H_comp: comp = Gt
H23: pair_compare X Y (x3, y2) (x3, y3) = Gt
H12: pair_compare X Y (x3, y1) (x3, y2) = Gt
right: compare y1 y2 = Gt
right': compare y2 y3 = Gtmatch compare x3 x3 with | Eq => compare y1 y3 | Lt => Lt | Gt => Gt end = GtX, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareStrictOrder (pair_compare X Y)X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareStrictOrder (pair_compare X Y)X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareReflexive (pair_compare X Y)X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareTransitive (pair_compare X Y)by apply pair_compare_reflexive.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareReflexive (pair_compare X Y)by apply pair_compare_transitive. Qed. #[export] Instance StrictlyComparable_pair (X Y : Type) `{StrictlyComparable X} `{StrictlyComparable Y} : StrictlyComparable (X * Y) := { compare := pair_compare X Y; compare_strictorder := CompareStrictOrder_pair_compare; }. #[export] Instance TripleStrictlyComparable (X Y Z : Type) `{StrictlyComparable X} `{StrictlyComparable Y} `{StrictlyComparable Z} : StrictlyComparable (X * Y * Z) := { compare := pair_compare (X * Y) Z; compare_strictorder := CompareStrictOrder_pair_compare; }.X, Y: Type
H: StrictlyComparable X
H0: StrictlyComparable YCompareTransitive (pair_compare X Y)
Fixpoint list_compare (A : Type) `{StrictlyComparable A} (l1 l2 : list A) : comparison := match l1, l2 with | [], [] => Eq | [], _ => Lt | _, [] => Gt | h1 :: t1, h2 :: t2 => match compare h1 h2 with | Eq => list_compare A t1 t2 | cmp => cmp end end.A: Type
H: StrictlyComparable ACompareReflexive (list_compare A)A: Type
H: StrictlyComparable ACompareReflexive (list_compare A)A: Type
H: StrictlyComparable A
h1: A
t1: list A
IHt1: ∀ y : list A, list_compare A t1 y = Eq ↔ t1 = y
h2: A
t2: list Alist_compare A (h1 :: t1) (h2 :: t2) = Eq ↔ h1 :: t1 = h2 :: t2A: Type
H: StrictlyComparable A
h1: A
t1: list A
IHt1: ∀ y : list A, list_compare A t1 y = Eq ↔ t1 = y
h2: A
t2: list Amatch compare h1 h2 with | Eq => list_compare A t1 t2 | Lt => Lt | Gt => Gt end = Eq → h1 :: t1 = h2 :: t2A: Type
H: StrictlyComparable A
h1: A
t1: list A
IHt1: ∀ y : list A, list_compare A t1 y = Eq ↔ t1 = y
h2: A
t2: list Ah1 :: t1 = h2 :: t2 → match compare h1 h2 with | Eq => list_compare A t1 t2 | Lt => Lt | Gt => Gt end = EqA: Type
H: StrictlyComparable A
h1: A
t1: list A
IHt1: ∀ y : list A, list_compare A t1 y = Eq ↔ t1 = y
h2: A
t2: list Amatch compare h1 h2 with | Eq => list_compare A t1 t2 | Lt => Lt | Gt => Gt end = Eq → h1 :: t1 = h2 :: t2A: Type
H: StrictlyComparable A
h1: A
t1: list A
IHt1: ∀ y : list A, list_compare A t1 y = Eq ↔ t1 = y
h2: A
t2: list A
Heq: match compare h1 h2 with | Eq => list_compare A t1 t2 | Lt => Lt | Gt => Gt end = Eqh1 :: t1 = h2 :: t2A: Type
H: StrictlyComparable A
h1: A
t1: list A
IHt1: ∀ y : list A, list_compare A t1 y = Eq ↔ t1 = y
h2: A
t2: list A
Hcmp: compare h1 h2 = Eq
Heq: list_compare A t1 t2 = Eqh1 :: t1 = h2 :: t2by apply IHt1 in Heq as ->.A: Type
H: StrictlyComparable A
t1: list A
IHt1: ∀ y : list A, list_compare A t1 y = Eq ↔ t1 = y
h2: A
t2: list A
Heq: list_compare A t1 t2 = Eqh2 :: t1 = h2 :: t2A: Type
H: StrictlyComparable A
h1: A
t1: list A
IHt1: ∀ y : list A, list_compare A t1 y = Eq ↔ t1 = y
h2: A
t2: list Ah1 :: t1 = h2 :: t2 → match compare h1 h2 with | Eq => list_compare A t1 t2 | Lt => Lt | Gt => Gt end = Eqby rewrite compare_eq_refl, IHt1. Qed.A: Type
H: StrictlyComparable A
t2: list A
h2: A
H0: h2 :: t2 = h2 :: t2
IHt1: ∀ y : list A, list_compare A t2 y = Eq ↔ t2 = ymatch compare h2 h2 with | Eq => list_compare A t2 t2 | Lt => Lt | Gt => Gt end = EqA: Type
H: StrictlyComparable ACompareTransitive (list_compare A)A: Type
H: StrictlyComparable ACompareTransitive (list_compare A)A: Type
H: StrictlyComparable A
l2: list A∀ (l1 l3 : list A) (c : comparison), list_compare A l1 l2 = c → list_compare A l2 l3 = c → list_compare A l1 l3 = cA: Type
H: StrictlyComparable A
h2: A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c∀ (l1 l3 : list A) (c : comparison), list_compare A l1 (h2 :: t2) = c → match l3 with | [] => Gt | h3 :: t3 => match compare h2 h3 with | Eq => list_compare A t2 t3 | Lt => Lt | Gt => Gt end end = c → list_compare A l1 l3 = cA: Type
H: StrictlyComparable A
h2: A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c
h1: A
t1: list A
h3: A
t3: list A∀ c : comparison, match compare h1 h2 with | Eq => list_compare A t1 t2 | Lt => Lt | Gt => Gt end = c → match compare h2 h3 with | Eq => list_compare A t2 t3 | Lt => Lt | Gt => Gt end = c → match compare h1 h3 with | Eq => list_compare A t1 t3 | Lt => Lt | Gt => Gt end = cA: Type
H: StrictlyComparable A
h2: A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c
h1: A
t1: list A
h3: A
t3: list A
c: comparisonmatch compare h1 h2 with | Eq => list_compare A t1 t2 | Lt => Lt | Gt => Gt end = c → match compare h2 h3 with | Eq => list_compare A t2 t3 | Lt => Lt | Gt => Gt end = c → match compare h1 h3 with | Eq => list_compare A t1 t3 | Lt => Lt | Gt => Gt end = cA: Type
H: StrictlyComparable A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c
t1: list A
h3: A
t3: list A
c: comparisonlist_compare A t1 t2 = c → list_compare A t2 t3 = c → list_compare A t1 t3 = cA: Type
H: StrictlyComparable A
h2: A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c
h1: A
t1: list A
h3: A
t3: list A
c: comparison
H12: compare h1 h2 = Lt
H23: compare h2 h3 = LtLt = c → Lt = c → match compare h1 h3 with | Eq => list_compare A t1 t3 | Lt => Lt | Gt => Gt end = cA: Type
H: StrictlyComparable A
h2: A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c
h1: A
t1: list A
h3: A
t3: list A
c: comparison
H12: compare h1 h2 = Gt
H23: compare h2 h3 = GtGt = c → Gt = c → match compare h1 h3 with | Eq => list_compare A t1 t3 | Lt => Lt | Gt => Gt end = cby apply IHt2.A: Type
H: StrictlyComparable A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c
t1: list A
h3: A
t3: list A
c: comparisonlist_compare A t1 t2 = c → list_compare A t2 t3 = c → list_compare A t1 t3 = cby rewrite (StrictOrder_Transitive _ _ _ _ H12 H23).A: Type
H: StrictlyComparable A
h2: A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c
h1: A
t1: list A
h3: A
t3: list A
c: comparison
H12: compare h1 h2 = Lt
H23: compare h2 h3 = LtLt = c → Lt = c → match compare h1 h3 with | Eq => list_compare A t1 t3 | Lt => Lt | Gt => Gt end = cby rewrite (StrictOrder_Transitive _ _ _ _ H12 H23). Qed.A: Type
H: StrictlyComparable A
h2: A
t2: list A
IHt2: ∀ (l1 l3 : list A) (c : comparison), list_compare A l1 t2 = c → list_compare A t2 l3 = c → list_compare A l1 l3 = c
h1: A
t1: list A
h3: A
t3: list A
c: comparison
H12: compare h1 h2 = Gt
H23: compare h2 h3 = GtGt = c → Gt = c → match compare h1 h3 with | Eq => list_compare A t1 t3 | Lt => Lt | Gt => Gt end = cA: Type
H: StrictlyComparable ACompareStrictOrder (list_compare A)A: Type
H: StrictlyComparable ACompareStrictOrder (list_compare A)A: Type
H: StrictlyComparable ACompareReflexive (list_compare A)A: Type
H: StrictlyComparable ACompareTransitive (list_compare A)by apply list_compare_reflexive.A: Type
H: StrictlyComparable ACompareReflexive (list_compare A)by apply list_compare_transitive. Qed. #[export] Instance StrictlyComparable_list {A : Type} `{StrictlyComparable A} : StrictlyComparable (list A) := { compare := list_compare A; compare_strictorder := CompareStrictOrder_list_compare; }.A: Type
H: StrictlyComparable ACompareTransitive (list_compare A)
Definition bounding (P : nat -> Prop) := {n1 : nat | forall (n2 : nat), n1 <= n2 -> ~ P n2}. Definition liveness (P : nat -> Prop) := forall (n1 : nat), { n2 : nat | n1 <= n2 /\ P n2}. Definition liveness_dec (P : nat -> Prop) := forall (n1 : nat), { n2 : nat | n1 <= n2 /\ P n2} + {~ exists n2 : nat, n1 <= n2 /\ P n2}. Definition min_liveness (P : nat -> Prop) := forall (n1 : nat), { n2 : nat | n1 <= n2 /\ P n2 /\ forall (n3 : nat), n2 <= n3 /\ P n3 -> n2 <= n3}.P: nat → Prop
Hdec: liveness_dec P
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2)liveness PP: nat → Prop
Hdec: liveness_dec P
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2)liveness PP: nat → Prop
Hdec: liveness_dec P
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2)
n1: nat{n2 : nat | n1 ≤ n2 ∧ P n2}P: nat → Prop
n1: nat
Hdec: {n2 : nat | n1 ≤ n2 ∧ P n2} + {¬ (∃ n2 : nat, n1 ≤ n2 ∧ P n2)}
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2){n2 : nat | n1 ≤ n2 ∧ P n2}P: nat → Prop
n1: nat
Hnex: ¬ (∃ n2 : nat, n1 ≤ n2 ∧ P n2)
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2){n2 : nat | n1 ≤ n2 ∧ P n2}P: nat → Prop
n1: nat
Hnex: ¬ (∃ n2 : nat, n1 ≤ n2 ∧ P n2)
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2)∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2P: nat → Prop
n1: nat
Hnex: ¬ (∃ n2 : nat, n1 ≤ n2 ∧ P n2)
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2)∀ n2 : nat, n1 ≤ n2 → ¬ P n2P: nat → Prop
n1: nat
Hnex: ¬ (∃ n2 : nat, n1 ≤ n2 ∧ P n2)
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2)
n2: nat
Hleq: n1 ≤ n2
HnP: P n2Falseby exists n2. Qed.P: nat → Prop
n1: nat
Hnex: ¬ (∃ n2 : nat, n1 ≤ n2 ∧ P n2)
Hnbound: ¬ (∃ n1 : nat, ∀ n2 : nat, n1 ≤ n2 → ¬ P n2)
n2: nat
Hleq: n1 ≤ n2
HnP: P n2∃ n2 : nat, n1 ≤ n2 ∧ P n2
Extracts the left element from a sum, if possible.
Definition sum_project_left {A B : Type} (x : A + B) : option A :=
match x with
| inl a => Some a
| inr _ => None
end.
Extracts the right element from a sum, if possible.
Definition sum_project_right {A B : Type} (x : A + B) : option B := match x with | inl _ => None | inr b => Some b end. Program Definition not_lt_plus_dec {m n} (Hnlt : ~ n < m) : {k | k + m = n} := exist _ (n - m) _.∀ m n : nat, ¬ n < m → (λ k : nat, k + m = n) (n - m)by cbn; lia. Qed. Definition update `{EqDecision A} `(f : A -> B) (a : A) (b : B) : A -> B := fun a' : A => if decide (a = a') then b else f a'.∀ m n : nat, ¬ n < m → (λ k : nat, k + m = n) (n - m)A: Type
EqDecision0: EqDecision A
B: Type
f: A → B
a: A
b: Bupdate f a b a = bby unfold update; rewrite decide_True. Qed.A: Type
EqDecision0: EqDecision A
B: Type
f: A → B
a: A
b: Bupdate f a b a = bA: Type
EqDecision0: EqDecision A
B: Type
f: A → B
a: A
b: B
a': Aa ≠ a' → update f a b a' = f a'by intros; unfold update; rewrite decide_False. Qed.A: Type
EqDecision0: EqDecision A
B: Type
f: A → B
a: A
b: B
a': Aa ≠ a' → update f a b a' = f a'