MathClasses.misc.decision
Require Import
canonical_names util.
Class Decision P := decide: sumbool P (¬P).
Arguments decide _ {Decision}.
Instance: ∀ P, Decision P → Stable P.
Proof. firstorder. Qed.
Ltac case_decide := match goal with
| H : context [@decide ?P ?dec] |- _ ⇒ case (@decide P dec) in ×
| |- context [@decide ?P ?dec] ⇒ case (@decide P dec) in ×
end.
Ltac solve_trivial_decision :=
match goal with
| [ |- Decision (?P) ] ⇒ apply _
| [ |- sumbool ?P (¬?P) ] ⇒ change (Decision P); apply _
end.
Ltac solve_decision :=
first [solve_trivial_decision | unfold Decision; decide equality; solve_trivial_decision].
Program Instance decision_proper (P Q : Prop) (PiffQ : P ↔ Q) (P_dec : Decision P) : Decision Q :=
match P_dec with
| left _ ⇒ left _
| right _ ⇒ right _
end.
Solve Obligations using (program_simpl; tauto).
Definition bool_decide (P : Prop) `{dec : !Decision P} : bool := if dec then true else false.
Lemma bool_decide_true `{dec : Decision P} : bool_decide P ≡ true ↔ P.
Proof. unfold bool_decide. split; intro; destruct dec; firstorder. Qed.
Lemma bool_decide_false `{dec : !Decision P} : bool_decide P ≡ false ↔ ¬P.
Proof. unfold bool_decide. split; intro; destruct dec; firstorder. Qed.
Definition decide_rel `(R : A → B → Prop) {dec : ∀ x y, Decision (R x y)} (x : A) (y : B) : Decision (R x y)
:= dec x y.
Definition bool_decide_rel `(R : relation A) {dec : ∀ x y, Decision (R x y)} : A → A → bool
:= λ x y, if dec x y then true else false.
Lemma bool_decide_rel_true `(R : relation A) {dec : ∀ x y, Decision (R x y)} :
∀ x y, bool_decide_rel R x y ≡ true ↔ R x y.
Proof. unfold bool_decide_rel. split; intro; destruct dec; firstorder. Qed.
Lemma bool_decide_rel_false `(R : relation A)`{dec : ∀ x y, Decision (R x y)} :
∀ x y, bool_decide_rel R x y ≡ false ↔ ¬R x y.
Proof. unfold bool_decide_rel. split; intro; destruct dec; firstorder. Qed.
Program Definition decision_from_bool_decide {P b} (prf : b ≡ true ↔ P) :
Decision P := match b with true ⇒ left _ | false ⇒ right _ end.
Next Obligation. now apply prf. Qed.
Next Obligation. rewrite <-prf. discriminate. Qed.
Program Instance prod_eq_dec `(A_dec : ∀ x y : A, Decision (x ≡ y))
`(B_dec : ∀ x y : B, Decision (x ≡ y)) : ∀ x y : A × B, Decision (x ≡ y) := λ x y,
match A_dec (fst x) (fst y) with
| left _ ⇒ match B_dec (snd x) (snd y) with left _ ⇒ left _ | right _ ⇒ right _ end
| right _ ⇒ right _
end.
Solve Obligations using (program_simpl; f_equal; firstorder).
Program Instance and_dec `(P_dec : Decision P) `(Q_dec : Decision Q) : Decision (P ∧ Q) :=
match P_dec with
| left _ ⇒ match Q_dec with left _ ⇒ left _ | right _ ⇒ right _ end
| right _ ⇒ right _
end.
Solve Obligations using (program_simpl; tauto).
Program Instance or_dec `(P_dec : Decision P) `(Q_dec : Decision Q) : Decision (P ∨ Q) :=
match P_dec with
| left _ ⇒ left _
| right _ ⇒ match Q_dec with left _ ⇒ left _ | right _ ⇒ right _ end
end.
Solve Obligations using (program_simpl; firstorder).
Program Instance is_Some_dec `(x : option A) : Decision (is_Some x) :=
match x with
| None ⇒ right _
| Some _ ⇒ left _
end.
Program Instance is_None_dec `(x : option A) : Decision (is_None x) :=
match x with
| None ⇒ left _
| Some _ ⇒ right _
end.
Program Instance option_eq_dec `(A_dec : ∀ x y : A, Decision (x ≡ y))
: ∀ x y : option A, Decision (x ≡ y) := λ x y,
match x with
| Some r ⇒
match y with
| Some s ⇒ match A_dec r s with left _ ⇒ left _ | right _ ⇒ right _ end
| None ⇒ right _
end
| None ⇒
match y with
| Some s ⇒ right _
| None ⇒ left _
end
end.
Program Instance True_dec: Decision True := left _.
Program Instance False_dec: Decision False := right _.
canonical_names util.
Class Decision P := decide: sumbool P (¬P).
Arguments decide _ {Decision}.
Instance: ∀ P, Decision P → Stable P.
Proof. firstorder. Qed.
Ltac case_decide := match goal with
| H : context [@decide ?P ?dec] |- _ ⇒ case (@decide P dec) in ×
| |- context [@decide ?P ?dec] ⇒ case (@decide P dec) in ×
end.
Ltac solve_trivial_decision :=
match goal with
| [ |- Decision (?P) ] ⇒ apply _
| [ |- sumbool ?P (¬?P) ] ⇒ change (Decision P); apply _
end.
Ltac solve_decision :=
first [solve_trivial_decision | unfold Decision; decide equality; solve_trivial_decision].
Program Instance decision_proper (P Q : Prop) (PiffQ : P ↔ Q) (P_dec : Decision P) : Decision Q :=
match P_dec with
| left _ ⇒ left _
| right _ ⇒ right _
end.
Solve Obligations using (program_simpl; tauto).
Definition bool_decide (P : Prop) `{dec : !Decision P} : bool := if dec then true else false.
Lemma bool_decide_true `{dec : Decision P} : bool_decide P ≡ true ↔ P.
Proof. unfold bool_decide. split; intro; destruct dec; firstorder. Qed.
Lemma bool_decide_false `{dec : !Decision P} : bool_decide P ≡ false ↔ ¬P.
Proof. unfold bool_decide. split; intro; destruct dec; firstorder. Qed.
Definition decide_rel `(R : A → B → Prop) {dec : ∀ x y, Decision (R x y)} (x : A) (y : B) : Decision (R x y)
:= dec x y.
Definition bool_decide_rel `(R : relation A) {dec : ∀ x y, Decision (R x y)} : A → A → bool
:= λ x y, if dec x y then true else false.
Lemma bool_decide_rel_true `(R : relation A) {dec : ∀ x y, Decision (R x y)} :
∀ x y, bool_decide_rel R x y ≡ true ↔ R x y.
Proof. unfold bool_decide_rel. split; intro; destruct dec; firstorder. Qed.
Lemma bool_decide_rel_false `(R : relation A)`{dec : ∀ x y, Decision (R x y)} :
∀ x y, bool_decide_rel R x y ≡ false ↔ ¬R x y.
Proof. unfold bool_decide_rel. split; intro; destruct dec; firstorder. Qed.
Program Definition decision_from_bool_decide {P b} (prf : b ≡ true ↔ P) :
Decision P := match b with true ⇒ left _ | false ⇒ right _ end.
Next Obligation. now apply prf. Qed.
Next Obligation. rewrite <-prf. discriminate. Qed.
Program Instance prod_eq_dec `(A_dec : ∀ x y : A, Decision (x ≡ y))
`(B_dec : ∀ x y : B, Decision (x ≡ y)) : ∀ x y : A × B, Decision (x ≡ y) := λ x y,
match A_dec (fst x) (fst y) with
| left _ ⇒ match B_dec (snd x) (snd y) with left _ ⇒ left _ | right _ ⇒ right _ end
| right _ ⇒ right _
end.
Solve Obligations using (program_simpl; f_equal; firstorder).
Program Instance and_dec `(P_dec : Decision P) `(Q_dec : Decision Q) : Decision (P ∧ Q) :=
match P_dec with
| left _ ⇒ match Q_dec with left _ ⇒ left _ | right _ ⇒ right _ end
| right _ ⇒ right _
end.
Solve Obligations using (program_simpl; tauto).
Program Instance or_dec `(P_dec : Decision P) `(Q_dec : Decision Q) : Decision (P ∨ Q) :=
match P_dec with
| left _ ⇒ left _
| right _ ⇒ match Q_dec with left _ ⇒ left _ | right _ ⇒ right _ end
end.
Solve Obligations using (program_simpl; firstorder).
Program Instance is_Some_dec `(x : option A) : Decision (is_Some x) :=
match x with
| None ⇒ right _
| Some _ ⇒ left _
end.
Program Instance is_None_dec `(x : option A) : Decision (is_None x) :=
match x with
| None ⇒ left _
| Some _ ⇒ right _
end.
Program Instance option_eq_dec `(A_dec : ∀ x y : A, Decision (x ≡ y))
: ∀ x y : option A, Decision (x ≡ y) := λ x y,
match x with
| Some r ⇒
match y with
| Some s ⇒ match A_dec r s with left _ ⇒ left _ | right _ ⇒ right _ end
| None ⇒ right _
end
| None ⇒
match y with
| Some s ⇒ right _
| None ⇒ left _
end
end.
Program Instance True_dec: Decision True := left _.
Program Instance False_dec: Decision False := right _.