Impressum ssrbool.v
Interaktion und PortierbarkeitCoq
(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************)
(* This file is (C) Copyright 2006-2015 Microsoft Corporation and Inria. *)
Reserved Notation"~~ b" (at level 35, right associativity).
Reserved Notation"b ==> c" (at level 55, right associativity).
Reserved Notation"b1 (+) b2" (at level 50, left associativity).
Reserved Notation"x \in A" (at level 70, no associativity,
format "'[hv' x '/ ' \in A ']'").
Reserved Notation"x \notin A" (at level 70, no associativity,
format "'[hv' x '/ ' \notin A ']'").
Reserved Notation"x \is A" (at level 70, no associativity,
format "'[hv' x '/ ' \is A ']'").
Reserved Notation"x \isn't A" (at level 70, no associativity,
format "'[hv' x '/ ' \isn't A ']'").
Reserved Notation"x \is 'a' A" (at level 70, no associativity,
format "'[hv' x '/ ' \is 'a' A ']'").
Reserved Notation"x \isn't 'a' A" (at level 70, no associativity,
format "'[hv' x '/ ' \isn't 'a' A ']'").
Reserved Notation"x \is 'an' A" (at level 70, no associativity,
format "'[hv' x '/ ' \is 'an' A ']'").
Reserved Notation"x \isn't 'an' A" (at level 70, no associativity,
format "'[hv' x '/ ' \isn't 'an' A ']'").
Reserved Notation"p1 =i p2" (at level 70, no associativity,
format "'[hv' p1 '/ ' =i p2 ']'").
Reserved Notation"{ 'subset' A <= B }" (at level 0, A, B at level 69,
format "'[hv' { 'subset' A '/ ' <= B } ']'").
Reserved Notation"{ : T }" (at level 0, format "{ : T }").
Reserved Notation"{ 'pred' T }" (at level 0, format "{ 'pred' T }").
Reserved Notation"[ 'predType' 'of' T ]" (at level 0,
format "[ 'predType' 'of' T ]").
Reserved Notation"[ 'pred' : T | E ]" (at level 0,
format "'[hv' [ 'pred' : T | '/ ' E ] ']'").
Reserved Notation"[ 'pred' x | E ]" (at level 0, x name,
format "'[hv' [ 'pred' x | '/ ' E ] ']'").
Reserved Notation"[ 'pred' x : T | E ]" (at level 0, x name,
format "'[hv' [ 'pred' x : T | '/ ' E ] ']'").
Reserved Notation"[ 'pred' x | E1 & E2 ]" (at level 0, x name,
format "'[hv' [ 'pred' x | '/ ' E1 & '/ ' E2 ] ']'").
Reserved Notation"[ 'pred' x : T | E1 & E2 ]" (at level 0, x name,
format "'[hv' [ 'pred' x : T | '/ ' E1 & E2 ] ']'").
Reserved Notation"[ 'pred' x 'in' A ]" (at level 0, x name,
format "'[hv' [ 'pred' x 'in' A ] ']'").
Reserved Notation"[ 'pred' x 'in' A | E ]" (at level 0, x name,
format "'[hv' [ 'pred' x 'in' A | '/ ' E ] ']'").
Reserved Notation"[ 'pred' x 'in' A | E1 & E2 ]" (at level 0, x name,
format "'[hv' [ 'pred' x 'in' A | '/ ' E1 & '/ ' E2 ] ']'").
Reserved Notation"[ 'qualify' x | P ]" (at level 0, x at level 99,
format "'[hv' [ 'qualify' x | '/ ' P ] ']'").
Reserved Notation"[ 'qualify' x : T | P ]" (at level 0, x at level 99,
format "'[hv' [ 'qualify' x : T | '/ ' P ] ']'").
Reserved Notation"[ 'qualify' 'a' x | P ]" (at level 0, x at level 99,
format "'[hv' [ 'qualify' 'a' x | '/ ' P ] ']'").
Reserved Notation"[ 'qualify' 'a' x : T | P ]" (at level 0, x at level 99,
format "'[hv' [ 'qualify' 'a' x : T | '/ ' P ] ']'").
Reserved Notation"[ 'qualify' 'an' x | P ]" (at level 0, x at level 99,
format "'[hv' [ 'qualify' 'an' x | '/ ' P ] ']'").
Reserved Notation"[ 'qualify' 'an' x : T | P ]" (at level 0, x at level 99,
format "'[hv' [ 'qualify' 'an' x : T | '/ ' P ] ']'").
Reserved Notation"[ 'rel' x y | E ]" (at level 0, x name, y name,
format "'[hv' [ 'rel' x y | '/ ' E ] ']'").
Reserved Notation"[ 'rel' x y : T | E ]" (at level 0, x name, y name,
format "'[hv' [ 'rel' x y : T | '/ ' E ] ']'").
Reserved Notation"[ 'rel' x y 'in' A & B | E ]" (at level 0, x name, y name,
format "'[hv' [ 'rel' x y 'in' A & B | '/ ' E ] ']'").
Reserved Notation"[ 'rel' x y 'in' A & B ]" (at level 0, x name, y name,
format "'[hv' [ 'rel' x y 'in' A & B ] ']'").
Reserved Notation"[ 'rel' x y 'in' A | E ]" (at level 0, x name, y name,
format "'[hv' [ 'rel' x y 'in' A | '/ ' E ] ']'").
Reserved Notation"[ 'rel' x y 'in' A ]" (at level 0, x name, y name,
format "'[hv' [ 'rel' x y 'in' A ] ']'").
Reserved Notation"[ 'mem' A ]" (at level 0, format "[ 'mem' A ]").
Reserved Notation"[ 'predI' A & B ]" (at level 0,
format "[ 'predI' A & B ]").
Reserved Notation"[ 'predU' A & B ]" (at level 0,
format "[ 'predU' A & B ]").
Reserved Notation"[ 'predD' A & B ]" (at level 0,
format "[ 'predD' A & B ]").
Reserved Notation"[ 'predC' A ]" (at level 0,
format "[ 'predC' A ]").
Reserved Notation"[ 'preim' f 'of' A ]" (at level 0,
format "[ 'preim' f 'of' A ]").
Reserved Notation"\unless C , P" (at level 200, C at level 100,
format "'[hv' \unless C , '/ ' P ']'").
Reserved Notation"{ 'for' x , P }" (at level 0,
format "'[hv' { 'for' x , '/ ' P } ']'").
Reserved Notation"{ 'in' d , P }" (at level 0,
format "'[hv' { 'in' d , '/ ' P } ']'").
Reserved Notation"{ 'in' d1 & d2 , P }" (at level 0,
format "'[hv' { 'in' d1 & d2 , '/ ' P } ']'").
Reserved Notation"{ 'in' d & , P }" (at level 0,
format "'[hv' { 'in' d & , '/ ' P } ']'").
Reserved Notation"{ 'in' d1 & d2 & d3 , P }" (at level 0,
format "'[hv' { 'in' d1 & d2 & d3 , '/ ' P } ']'").
Reserved Notation"{ 'in' d1 & & d3 , P }" (at level 0,
format "'[hv' { 'in' d1 & & d3 , '/ ' P } ']'").
Reserved Notation"{ 'in' d1 & d2 & , P }" (at level 0,
format "'[hv' { 'in' d1 & d2 & , '/ ' P } ']'").
Reserved Notation"{ 'in' d & & , P }" (at level 0,
format "'[hv' { 'in' d & & , '/ ' P } ']'").
Reserved Notation"{ 'on' cd , P }" (at level 0,
format "'[hv' { 'on' cd , '/ ' P } ']'").
Reserved Notation"{ 'on' cd & , P }" (at level 0,
format "'[hv' { 'on' cd & , '/ ' P } ']'").
Reserved Notation"{ 'on' cd , P & g }" (at level 0, g at level 8,
format "'[hv' { 'on' cd , '/ ' P & g } ']'").
Reserved Notation"{ 'in' d , 'bijective' f }" (at level 0, f at level 8,
format "'[hv' { 'in' d , '/ ' 'bijective' f } ']'").
Reserved Notation"{ 'on' cd , 'bijective' f }" (at level 0, f at level 8,
format "'[hv' { 'on' cd , '/ ' 'bijective' f } ']'").
(** Weintroduceanumberofn-ary"list-style"notationsthatshareacommon format,namely #[#oparg1,arg2,...last_separatorlast_arg#]# Thisusuallydenotesaright-associativeapplicationsofop,e.g., #[#&&a,b,c&d#]#denotesa&&(b&&(c&&d)) Thelast_separatormustbeanon-operatortoken.Hereweuse&,|or=>; ourdefaultis&,butwetrytomatchtheintendedmeaningofop.The separatorisaworkaroundforlimitationsoftheparsingengine;thesame limitationsmeantheseparatorcannotbeomittedevenwhenlast_argcan. TheNotationdeclarationsarecomplicatedbytheseparatetreatmentfor somefixedarities(binaryforbooloperators,andallaritiesforProp operators). Wealsousethesquarebracketsincomprehension-stylenotations #[#typevarseparatorexpr#]# where"type"isthetypeofthecomprehension(e.g.,pred)and"separator" is|or=>.Itisimportantthatinothernotationsaleadingsquare
bracket #[# is always followed by an operator symbol or a fixed identifier. **)
(** WegenerallytakeNEGATIONasthestandardformofafalsecondition: negativebooleanhypothesesshouldbeoftheform~~b,ratherthan~bor
b = false, as much as possible. **)
Lemma negbT b : b = false -> ~~ b. Proof. bycase: b. Qed. Lemma negbTE b : ~~ b -> b = false. Proof. bycase: b. Qed. Lemma negbF b : (b : bool) -> ~~ b = false. Proof. bycase: b. Qed. Lemma negbFE b : ~~ b = false -> b. Proof. bycase: b. Qed. Lemma negbK : involutive negb. Proof. bycase. Qed. Lemma negbNE b : ~~ ~~ b -> b. Proof. bycase: b. Qed.
Lemma negb_inj : injective negb. Proof. exact: can_inj negbK. Qed. Lemma negbLR b c : b = ~~ c -> ~~ b = c. Proof. exact: canLR negbK. Qed. Lemma negbRL b c : ~~ b = c -> b = ~~ c. Proof. exact: canRL negbK. Qed.
Lemma contra (c b : bool) : (c -> b) -> ~~ b -> ~~ c. Proof. bycase: b => //; case: c. Qed. Definition contraNN := contra.
Lemma contraL (c b : bool) : (c -> ~~ b) -> b -> ~~ c. Proof. bycase: b => //; case: c. Qed. Definition contraTN := contraL.
Lemma contraR (c b : bool) : (~~ c -> b) -> ~~ b -> c. Proof. bycase: b => //; case: c. Qed. Definition contraNT := contraR.
Lemma contraLR (c b : bool) : (~~ c -> ~~ b) -> b -> c. Proof. bycase: b => //; case: c. Qed. Definition contraTT := contraLR.
Lemma contraT b : (~~ b -> false) -> b. Proof. bycase: b => // ->. Qed.
Lemma wlog_neg b : (~~ b -> b) -> b. Proof. bycase: b => // ->. Qed.
Lemma contraFT (c b : bool) : (~~ c -> b) -> b = false -> c. Proof. by move/contraR=> notb_c /negbT. Qed.
Lemma contraFN (c b : bool) : (c -> b) -> b = false -> ~~ c. Proof. by move/contra=> notb_notc /negbT. Qed.
Lemma contraTF (c b : bool) : (c -> ~~ b) -> b -> c = false. Proof. by move/contraL=> b_notc /b_notc/negbTE. Qed.
Lemma contraNF (c b : bool) : (c -> b) -> ~~ b -> c = false. Proof. by move/contra=> notb_notc /notb_notc/negbTE. Qed.
Lemma contraFF (c b : bool) : (c -> b) -> b = false -> c = false. Proof. by move/contraFN=> bF_notc /bF_notc/negbTE. Qed.
Lemma contraFnot (P : Prop) (b : bool) : (P -> b) -> b = false -> ~ P. Proof. bycase: b => //; auto. Qed.
Lemma contraPF (P : Prop) (b : bool) : (b -> ~ P) -> P -> b = false. Proof. bycase: b => // /(_ isT). Qed.
Lemma contra_notF (P : Prop) (b : bool) : (b -> P) -> ~ P -> b = false. Proof. bycase: b => // /(_ isT). Qed.
(** Coercionofsum-styledatatypesintobool,whichmakesitpossible
to use ssr's boolean if rather than Rocq's "generic" if. **)
Coercion isSome T (u : option T) := if u is Some _ then true else false.
Coercion is_inl A B (u : A + B) := if u is inl _ then true else false.
Coercion is_left A B (u : {A} + {B}) := if u is left _ then true else false.
Coercion is_inleft A B (u : A + {B}) := if u is inleft _ then true else false.
Prenex Implicits isSome is_inl is_left is_inleft.
Definition decidable P := {P} + {~ P}.
(** Lemmasforifswithlargeconditions,whichallowreasoningaboutthe conditionwithoutrepeatingitinsidetheproof(thelatterIS preferablewhentheconditionisshort). Usage: ifthegoalcontains(ifcondthen...)=... case:ifP=>Hcond. generatestwosubgoal,withtheassumptionHcond:cond=true/false Rewriteif_sameeliminatesredundantifs Rewrite(fun_iff)movesafunctionfinsideanif
Rewrite if_arg moves an argument inside a function-valued if **)
Section BoolIf.
Variables (A B : Type) (x : A) (f : A -> B) (b : bool) (vT vF : A).
Variant if_spec (not_b : Prop) : bool -> A -> Set :=
| IfSpecTrue of b : if_spec not_b true vT
| IfSpecFalse of not_b : if_spec not_b false vF.
Lemma ifP : if_spec (b = false) b (if b then vT else vF). Proof. bycase def_b: b; constructor. Qed.
Lemma ifPn : if_spec (~~ b) b (if b then vT else vF). Proof. bycase def_b: b; constructor; rewrite ?def_b. Qed.
Lemma ifT : b -> (if b then vT else vF) = vT. Proof. by move->. Qed. Lemma ifF : b = false -> (if b then vT else vF) = vF. Proof. by move->. Qed. Lemma ifN : ~~ b -> (if b then vT else vF) = vF. Proof. by move/negbTE->. Qed.
Lemma if_same : (if b then vT else vT) = vT. Proof. bycase b. Qed.
Lemma if_neg : (if ~~ b then vT else vF) = if b then vF else vT. Proof. bycase b. Qed.
Lemma fun_if : f (if b then vT else vF) = if b then f vT else f vF. Proof. bycase b. Qed.
Lemma if_arg (fT fF : A -> B) :
(if b then fT else fF) x = if b then fT x else fF x. Proof. bycase b. Qed.
(** Turning a boolean "if" form into an application. **) Definition if_expr := if b then vT else vF. Lemma ifE : (if b then vT else vF) = if_expr. Proof. by []. Qed.
End BoolIf.
(** Core (internal) reflection lemmas, used for the three kinds of views. **)
Section ReflectCore.
Variables (P Q : Prop) (b c : bool).
Hypothesis Hb : reflect P b.
Lemma introNTF : (if c then ~ P else P) -> ~~ b = c. Proof. bycase c; case Hb. Qed.
Lemma introTF : (if c then P else ~ P) -> b = c. Proof. bycase c; case Hb. Qed.
Lemma elimNTF : ~~ b = c -> if c then ~ P else P. Proof. by move <-; case Hb. Qed.
Lemma elimTF : b = c -> if c then P else ~ P. Proof. by move <-; case Hb. Qed.
Lemma equivPif : (Q -> P) -> (P -> Q) -> if b then Q else ~ Q. Proof. bycase Hb; auto. Qed.
Lemma xorPif : Q \/ P -> ~ (Q /\ P) -> if b then ~ Q else Q. Proof. bycase Hb => [? _ H ? | ? H _]; case: H. Qed.
(** Predicate family to reflect excluded middle in bool. **)
Variant alt_spec : bool -> Type :=
| AltTrue of P : alt_spec true
| AltFalse of ~~ b : alt_spec false.
Lemma altP : alt_spec b. Proof. bycase def_b: b / Pb; constructor; rewrite ?def_b. Qed.
Lemma unless_contra b C : implies (~~ b -> C) (\unless C, b). Proof. bysplit; case: b => [_ | hC]; [apply/unlessR | apply/unlessL/hC]. Qed.
(** Classicalreasoningbecomesdirectlyaccessibleforanyboolsubgoal.
Note that we cannot use "unless" here for lack of universe polymorphism. **) Definition classically P : Prop := forall b : bool, (P -> b) -> b.
Lemma classicP (P : Prop) : classically P <-> ~ ~ P. Proof. split=> [cP nP | nnP [] // nP]; last bycase nnP; move/nP. by have: P -> false; [move/nP | move/cP]. Qed.
Lemma classicW P : P -> classically P. Proof. by move=> hP _ ->. Qed.
Lemma classic_bind P Q : (P -> classically Q) -> classically P -> classically Q. Proof. by move=> iPQ cP b /iPQ-/cP. Qed.
Lemma classic_sigW T (P : T -> Prop) :
classically (exists x, P x) <-> classically ({x | P x}). Proof. bysplit; apply: classic_bind => -[x Px]; apply/classicW; exists x. Qed.
Lemma classic_ex T (P : T -> Prop) :
~ (forall x, ~ P x) -> classically (exists x, P x). Proof.
move=> NfNP; apply/classicP => exPF; apply: NfNP => x Px. byapply: exPF; exists x. Qed.
(** Listnotationsforwiderconnectives;thePropconnectiveshaveafixed widthsoastoavoiditerateddestruction(wegouptowidth5for/\,and width4foror).Theboolconnectiveshavearbitrarywidths,butdenote expressionsthatassociatetotheRIGHT.Thisisconsistentwiththeright
associativity of list expressions and thus more convenient in most proofs. **)
Lemma or3P : reflect [\/ b1, b2 | b3] [|| b1, b2 | b3]. Proof. case b1; first by constructor; constructor 1. case b2; first by constructor; constructor 2. case b3; first by constructor; constructor 3. by constructor; case. Qed.
Lemma or4P : reflect [\/ b1, b2, b3 | b4] [|| b1, b2, b3 | b4]. Proof. case b1; first by constructor; constructor 1. case b2; first by constructor; constructor 2. case b3; first by constructor; constructor 3. case b4; first by constructor; constructor 4. by constructor; case. Qed.
End ReflectCombinators. Arguments negPP {P p}. Arguments andPP {P Q p q}. Arguments orPP {P Q p q}. Arguments implyPP {P Q p q}.
Prenex Implicits negPP andPP orPP implyPP.
(** Shorter, more systematic names for the boolean connectives laws. **)
Lemma andTb : left_id true andb. Proof. by []. Qed. Lemma andFb : left_zero false andb. Proof. by []. Qed. Lemma andbT : right_id true andb. Proof. bycase. Qed. Lemma andbF : right_zero false andb. Proof. bycase. Qed. Lemma andbb : idempotent_op andb. Proof. bycase. Qed. Lemma andbC : commutative andb. Proof. by do 2!case. Qed. Lemma andbA : associative andb. Proof. by do 3!case. Qed. Lemma andbCA : left_commutative andb. Proof. by do 3!case. Qed. Lemma andbAC : right_commutative andb. Proof. by do 3!case. Qed. Lemma andbACA : interchange andb andb. Proof. by do 4!case. Qed.
Lemma orTb : forall b, true || b. Proof. by []. Qed. Lemma orFb : left_id false orb. Proof. by []. Qed. Lemma orbT : forall b, b || true. Proof. bycase. Qed. Lemma orbF : right_id false orb. Proof. bycase. Qed. Lemma orbb : idempotent_op orb. Proof. bycase. Qed. Lemma orbC : commutative orb. Proof. by do 2!case. Qed. Lemma orbA : associative orb. Proof. by do 3!case. Qed. Lemma orbCA : left_commutative orb. Proof. by do 3!case. Qed. Lemma orbAC : right_commutative orb. Proof. by do 3!case. Qed. Lemma orbACA : interchange orb orb. Proof. by do 4!case. Qed.
Lemma andbN b : b && ~~ b = false. Proof. bycase: b. Qed. Lemma andNb b : ~~ b && b = false. Proof. bycase: b. Qed. Lemma orbN b : b || ~~ b = true. Proof. bycase: b. Qed. Lemma orNb b : ~~ b || b = true. Proof. bycase: b. Qed.
Lemma andb_orl : left_distributive andb orb. Proof. by do 3!case. Qed. Lemma andb_orr : right_distributive andb orb. Proof. by do 3!case. Qed. Lemma orb_andl : left_distributive orb andb. Proof. by do 3!case. Qed. Lemma orb_andr : right_distributive orb andb. Proof. by do 3!case. Qed.
Lemma andb_idl (a b : bool) : (b -> a) -> a && b = b. Proof. bycase: a; case: b => // ->. Qed. Lemma andb_idr (a b : bool) : (a -> b) -> a && b = a. Proof. bycase: a; case: b => // ->. Qed. Lemma andb_id2l (a b c : bool) : (a -> b = c) -> a && b = a && c. Proof. bycase: a; case: b; case: c => // ->. Qed. Lemma andb_id2r (a b c : bool) : (b -> a = c) -> a && b = c && b. Proof. bycase: a; case: b; case: c => // ->. Qed.
Lemma orb_idl (a b : bool) : (a -> b) -> a || b = b. Proof. bycase: a; case: b => // ->. Qed. Lemma orb_idr (a b : bool) : (b -> a) -> a || b = a. Proof. bycase: a; case: b => // ->. Qed. Lemma orb_id2l (a b c : bool) : (~~ a -> b = c) -> a || b = a || c. Proof. bycase: a; case: b; case: c => // ->. Qed. Lemma orb_id2r (a b c : bool) : (~~ b -> a = c) -> a || b = c || b. Proof. bycase: a; case: b; case: c => // ->. Qed.
Lemma negb_and (a b : bool) : ~~ (a && b) = ~~ a || ~~ b. Proof. bycase: a; case: b. Qed.
Lemma negb_or (a b : bool) : ~~ (a || b) = ~~ a && ~~ b. Proof. bycase: a; case: b. Qed.
(** Pseudo-cancellation -- i.e, absorption **)
Lemma andbK a b : a && b || a = a. Proof. bycase: a; case: b. Qed. Lemma andKb a b : a || b && a = a. Proof. bycase: a; case: b. Qed. Lemma orbK a b : (a || b) && a = a. Proof. bycase: a; case: b. Qed. Lemma orKb a b : a && (b || a) = a. Proof. bycase: a; case: b. Qed.
(** Imply **)
Lemma implybT b : b ==> true. Proof. bycase: b. Qed. Lemma implybF b : (b ==> false) = ~~ b. Proof. bycase: b. Qed. Lemma implyFb b : false ==> b. Proof. by []. Qed. Lemma implyTb b : (true ==> b) = b. Proof. by []. Qed. Lemma implybb b : b ==> b. Proof. bycase: b. Qed.
Lemma negb_imply a b : ~~ (a ==> b) = a && ~~ b. Proof. bycase: a; case: b. Qed.
Lemma implybE a b : (a ==> b) = ~~ a || b. Proof. bycase: a; case: b. Qed.
Lemma implyNb a b : (~~ a ==> b) = a || b. Proof. bycase: a; case: b. Qed.
Lemma implybN a b : (a ==> ~~ b) = (b ==> ~~ a). Proof. bycase: a; case: b. Qed.
Lemma implybNN a b : (~~ a ==> ~~ b) = b ==> a. Proof. bycase: a; case: b. Qed.
Lemma implyb_idl (a b : bool) : (~~ a -> b) -> (a ==> b) = b. Proof. bycase: a; case: b => // ->. Qed. Lemma implyb_idr (a b : bool) : (b -> ~~ a) -> (a ==> b) = ~~ a. Proof. bycase: a; case: b => // ->. Qed. Lemma implyb_id2l (a b c : bool) : (a -> b = c) -> (a ==> b) = (a ==> c). Proof. bycase: a; case: b; case: c => // ->. Qed.
(** Addition (xor) **)
Lemma addFb : left_id false addb. Proof. by []. Qed. Lemma addbF : right_id false addb. Proof. bycase. Qed. Lemma addbb : self_inverse false addb. Proof. bycase. Qed. Lemma addbC : commutative addb. Proof. by do 2!case. Qed. Lemma addbA : associative addb. Proof. by do 3!case. Qed. Lemma addbCA : left_commutative addb. Proof. by do 3!case. Qed. Lemma addbAC : right_commutative addb. Proof. by do 3!case. Qed. Lemma addbACA : interchange addb addb. Proof. by do 4!case. Qed. Lemma andb_addl : left_distributive andb addb. Proof. by do 3!case. Qed. Lemma andb_addr : right_distributive andb addb. Proof. by do 3!case. Qed. Lemma addKb : left_loop id addb. Proof. by do 2!case. Qed. Lemma addbK : right_loop id addb. Proof. by do 2!case. Qed. Lemma addIb : left_injective addb. Proof. by do 3!case. Qed. Lemma addbI : right_injective addb. Proof. by do 3!case. Qed.
Lemma addTb b : true (+) b = ~~ b. Proof. by []. Qed. Lemma addbT b : b (+) true = ~~ b. Proof. bycase: b. Qed.
Lemma addbN a b : a (+) ~~ b = ~~ (a (+) b). Proof. bycase: a; case: b. Qed. Lemma addNb a b : ~~ a (+) b = ~~ (a (+) b). Proof. bycase: a; case: b. Qed.
Lemma addbP a b : reflect (~~ a = b) (a (+) b). Proof. bycase: a; case: b; constructor. Qed. Arguments addbP {a b}.
(** Resolutiontacticforblindlyweedingoutcommontermsfromboolean equalities.Whenfacedwithagoaloftheform(andb/orb/addbb1b2)=b3
they will try to locate b1 in b3 and remove it. This can fail! **)
Definition pred T := T -> bool.
Identity Coercion fun_of_pred : pred >-> Funclass.
Definition subpred T (p1 p2 : pred T) := forall x : T, p1 x -> p2 x.
(* Notation for some manifest predicates. *)
Notation xpred0 := (fun=> false). Notation xpredT := (fun=> true). Notation xpredI := (fun (p1 p2 : pred _) x => p1 x && p2 x). Notation xpredU := (fun (p1 p2 : pred _) x => p1 x || p2 x). Notation xpredC := (fun (p : pred _) x => ~~ p x). Notation xpredD := (fun (p1 p2 : pred _) x => ~~ p2 x && p1 x). Notation xpreim := (fun f (p : pred _) x => p (f x)).
(** The packed class interface for pred-like types. **)
Structure predType T :=
PredType {pred_sort :> Type; topred : pred_sort -> pred T}.
Definition clone_pred T U := fun pT & @pred_sort T pT -> U => fun toP (pT' := @PredType T U toP) & phant_id pT' pT => pT'. Notation"[ 'predType' 'of' T ]" := (@clone_pred _ T _ id _ id) : form_scope.
Canonical predPredType T := PredType (@id (pred T)). Set Warnings "-redundant-canonical-projection".
Canonical boolfunPredType T := PredType (@id (T -> bool)). Set Warnings "redundant-canonical-projection".
(** The type of abstract collective predicates. While{predT}isconvertibletopredT,itpresentsthepred_sortcoercion class,whichcruciallydoes_not_coercetoFunclass.TermwhosetypePcoerces to{predT}cannotbeappliedtoarguments,butthey_can_beusedasifP hadacanonicalpredTypeinstance,asthecoercionwillbeinsertedifthe unificationP=~=pred_sort?pTfails,changingtheproblemintothetrivial {predT}=~=pred_sort?pT(solution?pT:=predPredTypeP). AdditionalbenefitsofthisapproacharethatanytypecoercingtoPwill alsoinheritthisbehaviour,andthatthecoercionwillbeapparentinthe elaboratedexpression.Thelattermaybeimportantifthecoercionisalso acanonicalstructureprojector-seemathcomp/fingroup/fingroup.v.The maindrawbackofimplementingpredTypebycoercioninthiswayisthatthe typeofthevaluemustbeknownwhentheunificationconstraintisimposed: ifweonlyregistertheconstraintandthenlaterdiscoverlaterthatthe expressionhadtypePitwillbetoolatetoinsertacoercion,whereasa canonicalinstanceofpredTypeforPwouldhavesolvedthedeferredconstraint. Finally,definitions,lemmasandsectionsshouldusetype{predT}for theirgenericcollectivetypeparameters,asthiswillmakeitpossibleto applysuchdefinitionsandlemmasdirectlytovaluesoftypesthatimplement predTypebycoercionto{predT}(valuesoftypesthatimplementpredType withoutcoercingto{predT}willhavetobecoercedexplicitlyusingtopred).
**) Notation"{ 'pred' T }" := (pred_sort (predPredType T)) : type_scope.
(** The type of self-simplifying collective predicates. **) Definition simpl_pred T := simpl_fun T bool. Definition SimplPred {T} (p : pred T) : simpl_pred T := SimplFun p.
(** Some simpl_pred constructors. **)
Definition pred0 {T} := @SimplPred T xpred0. Definition predT {T} := @SimplPred T xpredT. Definition predI {T} (p1 p2 : pred T) := SimplPred (xpredI p1 p2). Definition predU {T} (p1 p2 : pred T) := SimplPred (xpredU p1 p2). Definition predC {T} (p : pred T) := SimplPred (xpredC p). Definition predD {T} (p1 p2 : pred T) := SimplPred (xpredD p1 p2). Definition preim {aT rT} (f : aT -> rT) (d : pred rT) := SimplPred (xpreim f d).
Notation"[ 'pred' : T | E ]" := (SimplPred (fun _ : T => E%B)) :
function_scope. Notation"[ 'pred' x | E ]" := (SimplPred (fun x => E%B)) : function_scope. Notation"[ 'pred' x | E1 & E2 ]" := [pred x | E1 && E2 ] : function_scope. Notation"[ 'pred' x : T | E ]" :=
(SimplPred (fun x : T => E%B)) (only parsing) : function_scope. Notation"[ 'pred' x : T | E1 & E2 ]" :=
[pred x : T | E1 && E2 ] (only parsing) : function_scope.
(** Coercions for simpl_pred. Assimpl_predTvaluesareusedbothapplicativelyandcollectivelywe needsimpl_predtocoercetobothpredT_and_{predT}.Howeveritis undesirabletohavetwodistinctconstantsforwhatareessentiallyidentical coercionfunctions,asthisconfusestheSSReflectkeyedmatchingalgorithm. WhiletheRocqCoerciondeclarationsappeartodisallowsuchCoercionaliasing, itispossibletoworkaroundthislimitationwithacombinationofmodules andfunctors,whichwedobelow. InadditionwealsogiveapredTypeinstanceforsimpl_pred,whichwill bepreferredtothe{predT}coerciontosolvesimpl_predT=~=pred_sort?pT constraints;notehoweverthatthepred_of_simplcoercion_will_beused whenasimpl_predTispassedasa{predT},sincethesimplPredTypeT
structure for simpl_pred T is _not_ convertible to predPredType T. **)
Module PredOfSimpl. Definition coerce T (sp : simpl_pred T) : pred T := fun_of_simpl sp. End PredOfSimpl. Notation pred_of_simpl := PredOfSimpl.coerce.
Coercion pred_of_simpl : simpl_pred >-> pred.
Canonical simplPredType T := PredType (@pred_of_simpl T).
Definition rel T := T -> pred T.
Identity Coercion fun_of_rel : rel >-> Funclass.
Definition subrel T (r1 r2 : rel T) := forall x y : T, r1 x y -> r2 x y.
Definition simpl_rel T := T -> simpl_pred T.
Coercion rel_of_simpl T (sr : simpl_rel T) : rel T := fun x : T => sr x. Arguments rel_of_simpl {T} sr x /.
Notation xrelU := (fun (r1 r2 : rel _) x y => r1 x y || r2 x y). Notation xrelpre := (fun f (r : rel _) x y => r (f x) (f y)).
Definition SimplRel {T} (r : rel T) : simpl_rel T := fun x => SimplPred (r x). Definition relU {T} (r1 r2 : rel T) := SimplRel (xrelU r1 r2). Definition relpre {aT rT} (f : aT -> rT) (r : rel rT) := SimplRel (xrelpre f r).
Notation"[ 'rel' x y | E ]" := (SimplRel (fun x y => E%B))
(only parsing) : function_scope. Notation"[ 'rel' x y : T | E ]" :=
(SimplRel (fun x y : T => E%B)) (only parsing) : function_scope.
Lemma subrelUl T (r1 r2 : rel T) : subrel r1 (relU r1 r2). Proof. by move=> x y r1xy; apply/orP; left. Qed.
Lemma subrelUr T (r1 r2 : rel T) : subrel r2 (relU r1 r2). Proof. by move=> x y r2xy; apply/orP; right. Qed.
(** Variant of simpl_pred specialised to the membership operator. **)
Variant mem_pred T := Mem of pred T.
(** Wemainlydeclarepred_of_memasacoercionsothatitisnotdisplayed. Similarlytopred_of_simpl,itwillusuallynotbeinsertedbytype inference,asallmem_predmp=~=pred_sort?pTunificationproblemswill besolvebythememPredTypeinstancebelow;pred_of_memwillhowever beusedifamem_predTisusedasa{predT},whichisdesirableasit willavoidaredundantmeminacollective,e.g.,passing(memA)toalemma exceptionagenericcollectivepredicatep:{predT}andpremisex\inP willdisplayasubgoalx\inAratherthanx\inmemA. Conversely,pred_of_memwill_not_ifitisusedid(memA)isused applicativelyorasapredT;therethesimpl_of_memcoerciondefinedbelow willbeused,resultinginasubgoalthatdisplaysasmemAxbysimplifies tox\inA.
**)
Coercion pred_of_mem {T} mp : {pred T} := let: Mem p := mp in [eta p].
Canonical memPredType T := PredType (@pred_of_mem T).
Definition in_mem {T} (x : T) mp := pred_of_mem mp x. Definition eq_mem {T} mp1 mp2 := forall x : T, in_mem x mp1 = in_mem x mp2. Definition sub_mem {T} mp1 mp2 := forall x : T, in_mem x mp1 -> in_mem x mp2.
Arguments in_mem {T} x mp : simpl never. Global Typeclasses Opaque eq_mem sub_mem.
(** The [simpl_of_mem; pred_of_simpl] path provides a new mem_pred >-> pred coercion,butdoes_not_overridethepred_of_mem:mem_pred>->pred_sort explicitcoerciondeclarationabove.
**)
Coercion simpl_of_mem {T} mp := SimplPred (fun x : T => in_mem x mp).
(** ItisessentialtointerlocktheproductionoftheMemconstructorinside thebranchofthepredTypematch,toensurethatunifyingmemAwith Mem[eta?p]sets?p:=toPA(or?p:=PiftoP=idandA=[etaP]), ratherthantopredpTA,hadweputmemA:=Mem(topredA).
**) Definition mem T (pT : predType T) : pT -> mem_pred T := let: PredType toP := pT in fun A => Mem [eta toP A]. Arguments mem {T pT} A : rename, simpl never.
Notation"x \in A" := (in_mem x (mem A)) (only parsing) : bool_scope. Notation"x \in A" := (in_mem x (mem A)) (only printing) : bool_scope. Notation"x \notin A" := (~~ (x \in A)) : bool_scope. Notation"A =i B" := (eq_mem (mem A) (mem B)) : type_scope. Notation"{ 'subset' A <= B }" := (sub_mem (mem A) (mem B)) : type_scope.
Notation"[ 'in' A ]" := (in_mem^~ (mem A))
(at level 0, format "[ 'in' A ]") : function_scope.
Notation"[ 'predI' A & B ]" := (predI [in A] [in B]) : function_scope. Notation"[ 'predU' A & B ]" := (predU [in A] [in B]) : function_scope. Notation"[ 'predD' A & B ]" := (predD [in A] [in B]) : function_scope. Notation"[ 'predC' A ]" := (predC [in A]) : function_scope. Notation"[ 'preim' f 'of' A ]" := (preim f [in A]) : function_scope.
Notation"[ 'pred' x 'in' A ]" := [pred x | x \in A] : function_scope. Notation"[ 'pred' x 'in' A | E ]" := [pred x | x \in A & E] : function_scope. Notation"[ 'pred' x 'in' A | E1 & E2 ]" :=
[pred x | x \in A & E1 && E2 ] : function_scope.
Notation"[ 'rel' x y 'in' A & B | E ]" :=
[rel x y | (x \in A) && (y \in B) && E] : function_scope. Notation"[ 'rel' x y 'in' A & B ]" :=
[rel x y | (x \in A) && (y \in B)] : function_scope. Notation"[ 'rel' x y 'in' A | E ]" := [rel x y in A & A | E] : function_scope. Notation"[ 'rel' x y 'in' A ]" := [rel x y in A & A] : function_scope.
(** Aliases of pred T that let us tag instances of simpl_pred as applicative orcollective,viabespokecoercions.Thistaggingwillgivecontrolover thesimplificationbehaviourofinEandotherrewritinglemmasbelow. Forthiscontroltoworkitiscrucialthatcollective_of_simpl_not_ beconvertibletoeitherapplicative_of_simplorpred_of_simpl.Indeed theydifferherebyacommutativeconversion(ofthematchandlambda).
**) Definition applicative_pred T := pred T. Definition collective_pred T := pred T.
Coercion applicative_pred_of_simpl T (sp : simpl_pred T) : applicative_pred T :=
fun_of_simpl sp.
Coercion collective_pred_of_simpl T (sp : simpl_pred T) : collective_pred T := let: SimplFun p := sp in p.
(** Explicit simplification rules for predicate application and membership. **) Section PredicateSimplification.
Structure registered_applicative_pred p := RegisteredApplicativePred {
applicative_pred_value :> pred T;
_ : applicative_pred_value = p
}. Definition ApplicativePred p := RegisteredApplicativePred (erefl p).
Canonical applicative_pred_applicative sp :=
ApplicativePred (applicative_pred_of_simpl sp).
Structure manifest_simpl_pred p := ManifestSimplPred {
simpl_pred_value :> simpl_pred T;
_ : simpl_pred_value = SimplPred p
}.
Canonical expose_simpl_pred p := ManifestSimplPred (erefl (SimplPred p)).
Structure manifest_mem_pred p := ManifestMemPred {
mem_pred_value :> mem_pred T;
_ : mem_pred_value = Mem [eta p]
}.
Canonical expose_mem_pred p := ManifestMemPred (erefl (Mem [eta p])).
Structure applicative_mem_pred p :=
ApplicativeMemPred {applicative_mem_pred_value :> manifest_mem_pred p}.
Canonical check_applicative_mem_pred p (ap : registered_applicative_pred p) :=
[eta @ApplicativeMemPred ap].
Lemma mem_topred pT (pp : pT) : mem (topred pp) = mem pp. Proof. bycase: pT pp. Qed.
Lemma topredE pT x (pp : pT) : topred pp x = (x \in pp). Proof. byrewrite -mem_topred. Qed.
Lemma app_predE x p (ap : registered_applicative_pred p) : ap x = (x \in p). Proof. bycase: ap => _ /= ->. Qed.
Lemma in_applicative x p (amp : applicative_mem_pred p) : in_mem x amp = p x. Proof. bycase: amp => -[_ /= ->]. Qed.
Lemma in_collective x p (msp : manifest_simpl_pred p) :
(x \in collective_pred_of_simpl msp) = p x. Proof. bycase: msp => _ /= ->. Qed.
Lemma in_simpl x p (msp : manifest_simpl_pred p) :
in_mem x (Mem [eta pred_of_simpl msp]) = p x. Proof. bycase: msp => _ /= ->. Qed.
(** Becauseoftheexplicitetaexpansionintheleft-handside,thislemma shouldonlybeusedintheleft-to-rightdirection.
**) Lemma unfold_in x p : (x \in ([eta p] : pred T)) = p x. Proof. by []. Qed.
Lemma simpl_predE p : SimplPred p =1 p. Proof. by []. Qed.
Definition inE := (in_applicative, in_simpl, simpl_predE). (* to be extended *)
Lemma mem_simpl sp : mem sp = sp :> pred T. Proof. by []. Qed.
Definition memE := mem_simpl. (* could be extended *)
Canonical default_keyed_pred T p := KeyedPred (@DefaultPredKey T p).
Canonical default_keyed_qualifier T n (q : qualifier n T) :=
KeyedQualifier (DefaultPredKey q).
End DefaultKeying.
(** Skolemizing with conditions. **)
Lemma all_tag_cond_dep I T (C : pred I) U :
(forall x, T x) -> (forall x, C x -> {y : T x & U x y}) ->
{f : forall x, T x & forall x, C x -> U x (f x)}. Proof.
move=> f0 fP; apply: all_tag (fun x y => C x -> U x y) _ => x. bycase Cx: (C x); [case/fP: Cx => y; exists y | exists (f0 x)]. Qed.
Lemma all_tag_cond I T (C : pred I) U :
T -> (forall x, C x -> {y : T & U x y}) ->
{f : I -> T & forall x, C x -> U x (f x)}. Proof. by move=> y0; apply: all_tag_cond_dep. Qed.
Lemma all_sig_cond_dep I T (C : pred I) P :
(forall x, T x) -> (forall x, C x -> {y : T x | P x y}) ->
{f : forall x, T x | forall x, C x -> P x (f x)}. Proof. by move=> f0 /(all_tag_cond_dep f0)[f]; exists f. Qed.
Lemma all_sig_cond I T (C : pred I) P :
T -> (forall x, C x -> {y : T | P x y}) ->
{f : I -> T | forall x, C x -> P x (f x)}. Proof. by move=> y0; apply: all_sig_cond_dep. Qed.
Lemma all_sig2_cond {I T} (C : pred I) P Q :
T -> (forall x, C x -> {y : T | P x y & Q x y}) ->
{f : I -> T | forall x, C x -> P x (f x) & forall x, C x -> Q x (f x)}. Proof. by move=> /all_sig_cond/[apply]-[f Pf]; exists f => i Di; have [] := Pf i Di. Qed.
Section RelationProperties.
(** Caveat:reflexiveshouldnotbeusedtostatelemmas,asautoandtrivial
will not expand the constant. **)
Variable T : Type.
Variable R : rel T.
Definition total := forall x y, R x y || R y x. Definition transitive := forall y x z, R x y -> R y z -> R x z.
Definition symmetric := forall x y, R x y = R y x. Definition antisymmetric := forall x y, R x y && R y x -> x = y. Definition pre_symmetric := forall x y, R x y -> R y x.
Lemma symmetric_from_pre : pre_symmetric -> symmetric. Proof. by move=> symR x y; apply/idP/idP; apply: symR. Qed.
Definition reflexive := forall x, R x x. Definition irreflexive := forall x, R x x = false.
Definition left_transitive := forall x y, R x y -> R x =1 R y. Definition right_transitive := forall x y, R x y -> R^~ x =1 R^~ y.
SectionPER.
Hypotheses (symR : symmetric) (trR : transitive).
Lemma sym_left_transitive : left_transitive. Proof. by move=> x y Rxy z; apply/idP/idP; apply: trR; rewrite // symR. Qed.
Lemma sym_right_transitive : right_transitive. Proof. by move=> x y /sym_left_transitive Rxy z; rewrite !(symR z) Rxy. Qed.
EndPER.
(** Wedefinetheequivalencepropertywithprenexquantificationsothatit
can be localized using the {in ..., ..} form defined below. **)
Definition equivalence_rel := forall x y z, R z z * (R x y -> R x z = R y z).
Lemma equivalence_relP : equivalence_rel <-> reflexive /\ left_transitive. Proof. split=> [eqiR | [Rxx trR] x y z]; last bysplit=> [|/trR->]. bysplit=> [x | x y Rxy z]; [rewrite (eqiR x x x) | rewrite (eqiR x y z)]. Qed.
End RelationProperties.
Lemma rev_trans T (R : rel T) : transitive R -> transitive (fun x y => R y x). Proof. by move=> trR x y z Ryx Rzy; apply: trR Rzy Ryx. Qed.
(** Property localization **)
LocalNotation"{ 'all1' P }" := (forall x, P x : Prop) (at level 0). LocalNotation"{ 'all2' P }" := (forall x y, P x y : Prop) (at level 0). LocalNotation"{ 'all3' P }" := (forall x y z, P x y z: Prop) (at level 0). LocalNotation ph := (phantom _).
Notation"{ 'on' cd & , P }" :=
(prop_on2 (mem cd) (inPhantom P) (inPhantom P)) : type_scope.
LocalArguments onPhantom : clear scopes. Notation"{ 'on' cd , P & g }" :=
(prop_on1 (mem cd) (Phantom (_ -> Prop) P) (onPhantom P g)) : type_scope. Notation"{ 'in' d , 'bijective' f }" := (bijective_in (mem d) f) : type_scope. Notation"{ 'on' cd , 'bijective' f }" :=
(bijective_on (mem cd) f) : type_scope.
(** Weakeningandmonotonicitylemmasforlocalizedpredicates. Notethatusingtheselemmasinbackwardreasoningwillforceexpansionof thepredicatedefinition,asRocqneedstoexposethequantifiertoapply theselemmas.Wedefineafewspecializedvariantstoavoidthisforsome
of the ssrfun predicates. **)
Lemma sub_in_bij (D1' : pred T1) :
{subset D1 <= D1'} -> {in D1', bijective f} -> {in D1, bijective f}. Proof. by move=> subD [g' fK g'K]; exists g' => x; move/subD; [apply: fK | apply: g'K]. Qed.
Lemma subon_bij (D2' : pred T2) :
{subset D2 <= D2'} -> {on D2', bijective f} -> {on D2, bijective f}. Proof. by move=> subD [g' fK g'K]; exists g' => x; move/subD; [apply: fK | apply: g'K]. Qed.
Lemma in_on1P : {in D1, {on D2, allQ1 f}} <->
{in [pred x in D1 | f x \in D2], allQ1 f}. Proof. split => allf x; have := allf x; rewrite inE => Q1f; first bycase/andP. by move=> ? ?; apply: Q1f; apply/andP. Qed.
Lemma in_on1lP : {in D1, {on D2, allQ1l f & h}} <->
{in [pred x in D1 | f x \in D2], allQ1l f h}. Proof. split => allf x; have := allf x; rewrite inE => Q1f; first bycase/andP. by move=> ? ?; apply: Q1f; apply/andP. Qed.
Lemma in_on2P : {in D1 &, {on D2 &, allQ2 f}} <->
{in [pred x in D1 | f x \in D2] &, allQ2 f}. Proof. split => allf x y; have := allf x y; rewrite !inE => Q2f. by move=> /andP[? ?] /andP[? ?]; apply: Q2f. by move=> ? ? ? ?; apply: Q2f; apply/andP. Qed.
Lemma can_in_pcan [rT aT : Type] (A : {pred aT}) [f : aT -> rT] [g : rT -> aT] :
{in A, cancel f g} -> {in A, pcancel f (fun y : rT => Some (g y))}. Proof. by move=> fK x Ax; rewrite fK. Qed.
Lemma pcan_in_inj [rT aT : Type] [A : {pred aT}]
[f : aT -> rT] [g : rT -> option aT] :
{in A, pcancel f g} -> {in A &, injective f}. Proof. by move=> fK x y Ax Ay /(congr1 g); rewrite !fK// => -[]. Qed.
Lemma in_inj_comp A B C (f : B -> A) (h : C -> B) (P : pred B) (Q : pred C) :
{in P &, injective f} -> {in Q &, injective h} -> {homo h : x / Q x >-> P x} ->
{in Q &, injective (f \o h)}. Proof. by move=> Pf Qh QP x y xQ yQ xy; apply Qh => //; apply Pf => //; apply QP. Qed.
Lemma can_in_comp [A B C : Type] (D : {pred B}) (D' : {pred C})
[f : B -> A] [h : C -> B] [f' : A -> B] [h' : B -> C] :
{homo h : x / x \in D' >-> x \in D} ->
{in D, cancel f f'} -> {in D', cancel h h'} ->
{in D', cancel (f \o h) (h' \o f')}. Proof. by move=> hD fK hK c cD /=; rewrite fK ?hK ?hD. Qed.
Lemma pcan_in_comp [A B C : Type] (D : {pred B}) (D' : {pred C})
[f : B -> A] [h : C -> B] [f' : A -> option B] [h' : B -> option C] :
{homo h : x / x \in D' >-> x \in D} ->
{in D, pcancel f f'} -> {in D', pcancel h h'} ->
{in D', pcancel (f \o h) (obind h' \o f')}. Proof. by move=> hD fK hK c cD /=; rewrite fK/= ?hK ?hD. Qed.
Definition pred_oapp T (D : {pred T}) : pred (option T) :=
[pred x | oapp (mem D) false x].
Lemma ocan_in_comp [A B C : Type] (D : {pred B}) (D' : {pred C})
[f : B -> option A] [h : C -> option B] [f' : A -> B] [h' : B -> C] :
{homo h : x / x \in D' >-> x \in pred_oapp D} ->
{in D, ocancel f f'} -> {in D', ocancel h h'} ->
{in D', ocancel (obind f \o h) (h' \o f')}. Proof.
move=> hD fK hK c cD /=; rewrite -[RHS]hK/=; case hcE : (h c) => [b|]//=.
have bD : b \in D by have := hD _ cD; rewrite hcE inE. byrewrite -[b in RHS]fK; case: (f b) => //=; have /hK := cD; rewrite hcE. Qed.
Lemma sub_in2 T d d' (P : T -> T -> Prop) :
sub_mem d d' -> forall Ph : ph {all2 P}, prop_in2 d' Ph -> prop_in2 d Ph. Proof. by move=> /= sub_dd'; apply: sub_in11. Qed.
Lemma sub_in3 T d d' (P : T -> T -> T -> Prop) :
sub_mem d d' -> forall Ph : ph {all3 P}, prop_in3 d' Ph -> prop_in3 d Ph. Proof. by move=> /= sub_dd'; apply: sub_in111. Qed.
Lemma sub_in12 T1 T d1 d1' d d' (P : T1 -> T -> T -> Prop) :
sub_mem d1 d1' -> sub_mem d d' -> forall Ph : ph {all3 P}, prop_in12 d1' d' Ph -> prop_in12 d1 d Ph. Proof. by move=> /= sub1 sub; apply: sub_in111. Qed.
Lemma sub_in21 T T3 d d' d3 d3' (P : T -> T -> T3 -> Prop) :
sub_mem d d' -> sub_mem d3 d3' -> forall Ph : ph {all3 P}, prop_in21 d' d3' Ph -> prop_in21 d d3 Ph. Proof. by move=> /= sub sub3; apply: sub_in111. Qed.
Lemma equivalence_relP_in T (R : rel T) (A : pred T) :
{in A & &, equivalence_rel R}
<-> {in A, reflexive R} /\ {in A &, forall x y, R x y -> {in A, R x =1 R y}}. Proof. split=> [eqiR | [Rxx trR] x y z *]; last bysplit=> [|/trR-> //]; apply: Rxx. bysplit=> [x Ax|x y Ax Ay Rxy z Az]; [rewrite (eqiR x x) | rewrite (eqiR x y)]. Qed.
Section MonoHomoMorphismTheory.
Variables (aT rT sT : Type) (f : aT -> rT) (g : rT -> aT). Variables (aP : pred aT) (rP : pred rT) (aR : rel aT) (rR : rel rT).
Lemma monoW : {mono f : x / aP x >-> rP x} -> {homo f : x / aP x >-> rP x}. Proof. by move=> hf x ax; rewrite hf. Qed.
Lemma mono2W :
{mono f : x y / aR x y >-> rR x y} -> {homo f : x y / aR x y >-> rR x y}. Proof. by move=> hf x y axy; rewrite hf. Qed.
Hypothesis fgK : cancel g f.
Lemma homoRL :
{homo f : x y / aR x y >-> rR x y} -> forall x y, aR (g x) y -> rR x (f y). Proof. by move=> Hf x y /Hf; rewrite fgK. Qed.
Lemma homoLR :
{homo f : x y / aR x y >-> rR x y} -> forall x y, aR x (g y) -> rR (f x) y. Proof. by move=> Hf x y /Hf; rewrite fgK. Qed.
Lemma homo_mono :
{homo f : x y / aR x y >-> rR x y} -> {homo g : x y / rR x y >-> aR x y} ->
{mono g : x y / rR x y >-> aR x y}. Proof.
move=> mf mg x y; case: (boolP (rR _ _))=> [/mg //|]. byapply: contraNF=> /mf; rewrite !fgK. Qed.
Lemma monoLR :
{mono f : x y / aR x y >-> rR x y} -> forall x y, rR (f x) y = aR x (g y). Proof. by move=> mf x y; rewrite -{1}[y]fgK mf. Qed.
Lemma monoRL :
{mono f : x y / aR x y >-> rR x y} -> forall x y, rR x (f y) = aR (g x) y. Proof. by move=> mf x y; rewrite -{1}[x]fgK mf. Qed.
Lemma can_mono :
{mono f : x y / aR x y >-> rR x y} -> {mono g : x y / rR x y >-> aR x y}. Proof. by move=> mf x y /=; rewrite -mf !fgK. Qed.
End MonoHomoMorphismTheory.
Section MonoHomoMorphismTheory_in.
Variables (aT rT : predArgType) (f : aT -> rT) (g : rT -> aT). Variables (aD : {pred aT}) (rD : {pred rT}). Variable (aP : pred aT) (rP : pred rT) (aR : rel aT) (rR : rel rT).
Lemma mono1W_in :
{in aD, {mono f : x / aP x >-> rP x}} ->
{in aD, {homo f : x / aP x >-> rP x}}. Proof. by move=> hf x hx ax; rewrite hf. Qed.
#[deprecated(since="Coq 8.16", note="Use mono1W_in instead.")] Notation mono2W_in := mono1W_in.
Lemma monoW_in :
{in aD &, {mono f : x y / aR x y >-> rR x y}} ->
{in aD &, {homo f : x y / aR x y >-> rR x y}}. Proof. by move=> hf x y hx hy axy; rewrite hf. Qed.
Hypothesis fgK : {in rD, {on aD, cancel g & f}}. Hypothesis mem_g : {homo g : x / x \in rD >-> x \in aD}.
Lemma homoRL_in :
{in aD &, {homo f : x y / aR x y >-> rR x y}} ->
{in rD & aD, forall x y, aR (g x) y -> rR x (f y)}. Proof. by move=> Hf x y hx hy /Hf; rewrite fgK ?mem_g// ?inE; apply. Qed.
Lemma homoLR_in :
{in aD &, {homo f : x y / aR x y >-> rR x y}} ->
{in aD & rD, forall x y, aR x (g y) -> rR (f x) y}. Proof. by move=> Hf x y hx hy /Hf; rewrite fgK ?mem_g// ?inE; apply. Qed.
Lemma homo_mono_in :
{in aD &, {homo f : x y / aR x y >-> rR x y}} ->
{in rD &, {homo g : x y / rR x y >-> aR x y}} ->
{in rD &, {mono g : x y / rR x y >-> aR x y}}. Proof.
move=> mf mg x y hx hy; case: (boolP (rR _ _))=> [/mg //|]; first exact. byapply: contraNF=> /mf; rewrite !fgK ?mem_g//; apply. Qed.
Lemma monoLR_in :
{in aD &, {mono f : x y / aR x y >-> rR x y}} ->
{in aD & rD, forall x y, rR (f x) y = aR x (g y)}. Proof. by move=> mf x y hx hy; rewrite -{1}[y]fgK ?mem_g// mf ?mem_g. Qed.
Lemma monoRL_in :
{in aD &, {mono f : x y / aR x y >-> rR x y}} ->
{in rD & aD, forall x y, rR x (f y) = aR (g x) y}. Proof. by move=> mf x y hx hy; rewrite -{1}[x]fgK ?mem_g// mf ?mem_g. Qed.
Lemma can_mono_in :
{in aD &, {mono f : x y / aR x y >-> rR x y}} ->
{in rD &, {mono g : x y / rR x y >-> aR x y}}. Proof. by move=> mf x y hx hy; rewrite -mf ?mem_g// !fgK ?mem_g. Qed.
End MonoHomoMorphismTheory_in. Arguments homoRL_in {aT rT f g aD rD aR rR}. Arguments homoLR_in {aT rT f g aD rD aR rR}. Arguments homo_mono_in {aT rT f g aD rD aR rR}. Arguments monoLR_in {aT rT f g aD rD aR rR}. Arguments monoRL_in {aT rT f g aD rD aR rR}. Arguments can_mono_in {aT rT f g aD rD aR rR}.
Section HomoMonoMorphismFlip. Variables (aT rT : Type) (aR : rel aT) (rR : rel rT) (f : aT -> rT). Variable (aD aD' : {pred aT}).
Lemma homo_sym : {homo f : x y / aR x y >-> rR x y} ->
{homo f : y x / aR x y >-> rR x y}. Proof. by move=> fR y x; apply: fR. Qed.
Lemma mono_sym : {mono f : x y / aR x y >-> rR x y} ->
{mono f : y x / aR x y >-> rR x y}. Proof. by move=> fR y x; apply: fR. Qed.
Lemma homo_sym_in : {in aD &, {homo f : x y / aR x y >-> rR x y}} ->
{in aD &, {homo f : y x / aR x y >-> rR x y}}. Proof. by move=> fR y x yD xD; apply: fR. Qed.
Lemma mono_sym_in : {in aD &, {mono f : x y / aR x y >-> rR x y}} ->
{in aD &, {mono f : y x / aR x y >-> rR x y}}. Proof. by move=> fR y x yD xD; apply: fR. Qed.
Lemma homo_sym_in11 : {in aD & aD', {homo f : x y / aR x y >-> rR x y}} ->
{in aD' & aD, {homo f : y x / aR x y >-> rR x y}}. Proof. by move=> fR y x yD xD; apply: fR. Qed.
Lemma mono_sym_in11 : {in aD & aD', {mono f : x y / aR x y >-> rR x y}} ->
{in aD' & aD, {mono f : y x / aR x y >-> rR x y}}. Proof. by move=> fR y x yD xD; apply: fR. Qed.
End HomoMonoMorphismFlip. Arguments homo_sym {aT rT} [aR rR f]. Arguments mono_sym {aT rT} [aR rR f]. Arguments homo_sym_in {aT rT} [aR rR f aD]. Arguments mono_sym_in {aT rT} [aR rR f aD]. Arguments homo_sym_in11 {aT rT} [aR rR f aD aD']. Arguments mono_sym_in11 {aT rT} [aR rR f aD aD'].
Lemma onW_can : cancel g f -> {on aD, cancel g & f}. Proof. by move=> fgK x xaD; apply: fgK. Qed.
Lemma onW_can_in : {in rD, cancel g f} -> {in rD, {on aD, cancel g & f}}. Proof. by move=> fgK x xrD xaD; apply: fgK. Qed.
Lemma in_onW_can : cancel g f -> {in rD, {on aD, cancel g & f}}. Proof. by move=> fgK x xrD xaD; apply: fgK. Qed.
Lemma onS_can : (forall x, g x \in aD) -> {on aD, cancel g & f} -> cancel g f. Proof. by move=> mem_g fgK x; apply: fgK. Qed.
Lemma onS_can_in : {homo g : x / x \in rD >-> x \in aD} ->
{in rD, {on aD, cancel g & f}} -> {in rD, cancel g f}. Proof. by move=> mem_g fgK x x_rD; apply/fgK/mem_g. Qed.
Lemma in_onS_can : (forall x, g x \in aD) ->
{in rT, {on aD, cancel g & f}} -> cancel g f. Proof. by move=> mem_g fgK x; apply/fgK. Qed.
End CancelOn. Arguments onW_can {aT rT} aD {f g}. Arguments onW_can_in {aT rT} aD {rD f g}. Arguments in_onW_can {aT rT} aD rD {f g}. Arguments onS_can {aT rT} aD {f g}. Arguments onS_can_in {aT rT} aD {rD f g}. Arguments in_onS_can {aT rT} aD {f g}.
Lemma inj_can_sym_in_on :
{homo f : x / x \in aD >-> x \in rD} -> {in aD, {on rD, cancel f & g}} ->
{in rD &, {on aD &, injective g}} -> {in rD, {on aD, cancel g & f}}. Proof. by move=> fD fK gI x x_rD gx_aD; apply: gI; rewrite ?inE ?fK ?fD. Qed.
Lemma inj_can_sym_on : {in aD, cancel f g} ->
{on aD &, injective g} -> {on aD, cancel g & f}. Proof. by move=> fK gI x gx_aD; apply: gI; rewrite ?inE ?fK. Qed.
Lemma inj_can_sym_in : {homo f \o g : x / x \in rD} -> {on rD, cancel f & g} ->
{in rD &, injective g} -> {in rD, cancel g f}. Proof. by move=> fgD fK gI x x_rD; apply: gI; rewrite ?fK ?fgD. Qed.
End inj_can_sym_in_on. Arguments inj_can_sym_in_on {aT rT aD rD f g}. Arguments inj_can_sym_on {aT rT aD f g}. Arguments inj_can_sym_in {aT rT rD f g}.
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.229Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.