Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \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) *) (************************************************************************) Require Import Orders OrdersTac OrdersFacts Setoid Morphisms Basics.
Module Type HasMax (Import E:EqLe'). Parameter Inline max : t -> t -> t. Parameter max_l : forall x y, y<=x -> max x y == x. Parameter max_r : forall x y, x<=y -> max x y == y. End HasMax. Module Type HasMin (Import E:EqLe'). Parameter Inline min : t -> t -> t. Parameter min_l : forall x y, x<=y -> min x y == x. Parameter min_r : forall x y, y<=x -> min x y == y. End HasMin. Module Type HasMinMax (E:EqLe) := HasMax E <+ HasMin E.
Definition gmax {A} (cmp : A->A->comparison) x y := match cmp x y with Lt => y | _ => x end. Definition gmin {A} (cmp : A->A->comparison) x y := match cmp x y with Gt => y | _ => x end. Module GenericMinMax (Import O:OrderedTypeFull') <: HasMinMax O. Definition max := gmax O.compare. Definition min := gmin O.compare.x, y:ty <= x -> x < y -> Falsex, y:ty <= x -> x < y -> Falsex, y:tH:y <= xH':x < yFalsex, y:tH:y <= xH':x < yx < xx, y:tH:y < xH':x < yx < xx, y:tH:y == xH':x < yx < xtransitivity y; auto.x, y:tH:y < xH':x < yx < xrewrite H in H'; auto. Qed.x, y:tH:y == xH':x < yx < xx, y:ty <= x -> max x y == xx, y:ty <= x -> max x y == xx, y:tH:y <= xmax x y == xx, y:tH:y <= xmatch x ?= y with | Lt => y | _ => x end == xintros; elim (ge_not_lt x y); auto. Qed.x, y:tH:y <= xx < y -> y == xx, y:tx <= y -> max x y == yx, y:tx <= y -> max x y == yx, y:tH:x <= ymax x y == yx, y:tH:x <= ymatch x ?= y with | Lt => y | _ => x end == yintros; elim (ge_not_lt y x); auto. Qed.x, y:tH:x <= yy < x -> x == yx, y:tx <= y -> min x y == xx, y:tx <= y -> min x y == xx, y:tH:x <= ymin x y == xx, y:tH:x <= ymatch x ?= y with | Gt => y | _ => x end == xintros; elim (ge_not_lt y x); auto. Qed.x, y:tH:x <= yy < x -> y == xx, y:ty <= x -> min x y == yx, y:ty <= x -> min x y == yx, y:tH:y <= xmin x y == yx, y:tH:y <= xmatch x ?= y with | Gt => y | _ => x end == yintros; elim (ge_not_lt x y); auto. Qed. End GenericMinMax.x, y:tH:y <= xx < y -> x == y
Module MinMaxLogicalProperties (Import O:TotalOrder')(Import M:HasMinMax O). Module Import Private_Tac := !MakeOrderTac O O.
An alternative characterisation of max, equivalent to
max_l ∧ max_r
n, m:tn < m /\ max n m == m \/ m <= n /\ max n m == nn, m:tn < m /\ max n m == m \/ m <= n /\ max n m == nn, m:tH:n < mn < m /\ max n m == mn, m:tH:n == m \/ m < nm <= n /\ max n m == nn, m:tH:n < mn < m /\ max n m == mn, m:tH:n < mmax n m == mrewrite le_lteq; auto.n, m:tH:n < mn <= mn, m:tH:n == m \/ m < nm <= n /\ max n m == nn, m:tH:n == m \/ m < nH0:m <= nm <= n /\ max n m == nnow apply max_l. Qed.n, m:tH:n == m \/ m < nH0:m <= nmax n m == n
A more symmetric version of max_spec, based only on le.
Beware that left and right alternatives overlap.
n, m:tn <= m /\ max n m == m \/ m <= n /\ max n m == ndestruct (max_spec n m); [left|right]; intuition; order. Qed.n, m:tn <= m /\ max n m == m \/ m <= n /\ max n m == nProper (eq ==> eq ==> iff) leProper (eq ==> eq ==> iff) leintuition order. Qed.forall x y : t, x == y -> forall x0 y0 : t, x0 == y0 -> (x <= x0 -> y <= y0) /\ (y <= y0 -> x <= x0)Proper (eq ==> eq ==> eq) maxProper (eq ==> eq ==> eq) maxx, x':tHx:x == x'y, y':tHy:y == y'max x y == max x' y'x, x':tHx:x == x'y, y':tHy:y == y'H1:x < y /\ max x y == y \/ y <= x /\ max x y == xmax x y == max x' y'x, x':tHx:x == x'y, y':tHy:y == y'H1:x < y /\ max x y == y \/ y <= x /\ max x y == xH2:x' < y' /\ max x' y' == y' \/ y' <= x' /\ max x' y' == x'max x y == max x' y'x, x':tHx:x == x'y, y':tHy:y == y'm:tH1:x < y /\ m == y \/ y <= x /\ m == xm':tH2:x' < y' /\ m' == y' \/ y' <= x' /\ m' == x'm == m'destruct (lt_total x y); intuition order. Qed.x, x':tHx:x == x'y, y':tHy:y == y'm:tH1:x < y /\ m == y \/ y <= x /\ m == xm':tH2:x < y /\ m' == y \/ y <= x /\ m' == xm == m'
A function satisfying the same specification is equal to max.
n, m, p:tn < m /\ p == m \/ m <= n /\ p == n -> p == max n mn, m, p:tn < m /\ p == m \/ m <= n /\ p == n -> p == max n mdestruct (lt_total n m); intuition; order. Qed.n, m, p:tHm:n < m /\ max n m == m \/ m <= n /\ max n m == nn < m /\ p == m \/ m <= n /\ p == n -> p == max n mf:t -> t -> t(forall n m : t, n < m /\ f n m == m \/ m <= n /\ f n m == n) -> forall n m : t, f n m == max n mf:t -> t -> t(forall n m : t, n < m /\ f n m == m \/ m <= n /\ f n m == n) -> forall n m : t, f n m == max n mapply max_unicity; auto. Qed.f:t -> t -> tH:forall n0 m0 : t, n0 < m0 /\ f n0 m0 == m0 \/ m0 <= n0 /\ f n0 m0 == n0n, m:tf n m == max n m
max commutes with monotone functions.
f:t -> tProper (eq ==> eq) f -> Proper (le ==> le) f -> forall x y : t, max (f x) (f y) == f (max x y)f:t -> tProper (eq ==> eq) f -> Proper (le ==> le) f -> forall x y : t, max (f x) (f y) == f (max x y)f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tmax (f x) (f y) == f (max x y)f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:x < yE:max x y == yH':f y <= f xE':max (f x) (f y) == f xmax (f x) (f y) == f yf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:y <= xE:max x y == xH':f x < f yE':max (f x) (f y) == f ymax (f x) (f y) == f xf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:x < yE:max x y == yH':f y <= f xE':max (f x) (f y) == f xmax (f x) (f y) == f yorder.f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:x < yE:max x y == yH':f y <= f xE':max (f x) (f y) == f xH0:f x <= f ymax (f x) (f y) == f yf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:y <= xE:max x y == xH':f x < f yE':max (f x) (f y) == f ymax (f x) (f y) == f xorder. Qed.f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:y <= xE:max x y == xH':f x < f yE':max (f x) (f y) == f yH0:f y <= f xmax (f x) (f y) == f x
n:tmax n n == napply max_l; order. Qed. Notation max_idempotent := max_id (only parsing).n:tmax n n == nm, n, p:tmax m (max n p) == max (max m n) pm, n, p:tmax m (max n p) == max (max m n) pm, n, p:tH:n < pE:max n p == pH':m < nE':max m n == nmax m p == pm, n, p:tH:p <= nE:max n p == nH':n <= mE':max m n == mm == max m papply max_r; order.m, n, p:tH:n < pE:max n p == pH':m < nE':max m n == nmax m p == pm, n, p:tH:p <= nE:max n p == nH':n <= mE':max m n == mm == max m papply max_l; order. Qed.m, n, p:tH:p <= nE:max n p == nH':n <= mE':max m n == mmax m p == mn, m:tmax n m == max m ndestruct (max_spec m n) as [(H,E)|(H,E)]; rewrite E; (apply max_r || apply max_l); order. Qed. Ltac solve_max := match goal with |- context [max ?n ?m] => destruct (max_spec n m); intuition; order end.n, m:tmax n m == max m n
n, m:tn <= max n msolve_max. Qed.n, m:tn <= max n mn, m:tm <= max n msolve_max. Qed.n, m:tm <= max n mn, m:tmax n m == n <-> m <= nsolve_max. Qed.n, m:tmax n m == n <-> m <= nn, m:tmax n m == m <-> n <= msolve_max. Qed.n, m:tmax n m == m <-> n <= mn, m, p:tp <= max n m -> p <= n \/ p <= mdestruct (max_spec n m); [right|left]; intuition; order. Qed.n, m, p:tp <= max n m -> p <= n \/ p <= mn, m, p:tp <= max n m <-> p <= n \/ p <= mn, m, p:tp <= max n m <-> p <= n \/ p <= mn, m, p:tp <= max n m -> p <= n \/ p <= mn, m, p:tp <= n \/ p <= m -> p <= max n mapply max_le.n, m, p:tp <= max n m -> p <= n \/ p <= msolve_max. Qed.n, m, p:tp <= n \/ p <= m -> p <= max n mn, m, p:tp < max n m <-> p < n \/ p < mdestruct (max_spec n m); intuition; order || (right; order) || (left; order). Qed.n, m, p:tp < max n m <-> p < n \/ p < mn, m, p:tmax n m <= p -> n <= psolve_max. Qed.n, m, p:tmax n m <= p -> n <= pn, m, p:tmax n m <= p -> m <= psolve_max. Qed.n, m, p:tmax n m <= p -> m <= pn, m, p:tn <= p -> m <= p -> max n m <= psolve_max. Qed.n, m, p:tn <= p -> m <= p -> max n m <= pn, m, p:tmax n m <= p <-> n <= p /\ m <= psolve_max. Qed.n, m, p:tmax n m <= p <-> n <= p /\ m <= pn, m, p:tn < p -> m < p -> max n m < psolve_max. Qed.n, m, p:tn < p -> m < p -> max n m < pn, m, p:tmax n m < p <-> n < p /\ m < psolve_max. Qed.n, m, p:tmax n m < p <-> n < p /\ m < pn, m, p:tn <= m -> max p n <= max p mn, m, p:tn <= m -> max p n <= max p mn, m, p:tH:n <= mmax p n <= max p msolve_max. Qed.n, m, p:tH:n <= mp <= max p m /\ n <= max p mn, m, p:tn <= m -> max n p <= max m pn, m, p:tn <= m -> max n p <= max m pn, m, p:tH:n <= mmax n p <= max m psolve_max. Qed.n, m, p:tH:n <= mn <= max m p /\ p <= max m pn, m, p, q:tn <= m -> p <= q -> max n p <= max m qn, m, p, q:tn <= m -> p <= q -> max n p <= max m qn, m, p, q:tHnm:n <= mHpq:p <= qmax n p <= max m qn, m, p, q:tHnm:n <= mHpq:p <= qLE:max m p <= max m qmax n p <= max m qorder. Qed.n, m, p, q:tHnm:n <= mHpq:p <= qLE:max m p <= max m qLE':max n p <= max m pmax n p <= max m q
Properties of min
n, m:tn < m /\ min n m == n \/ m <= n /\ min n m == mn, m:tn < m /\ min n m == n \/ m <= n /\ min n m == mn, m:tH:n < mn < m /\ min n m == nn, m:tH:n == m \/ m < nm <= n /\ min n m == mn, m:tH:n < mn < m /\ min n m == nn, m:tH:n < mmin n m == nrewrite le_lteq; auto.n, m:tH:n < mn <= mn, m:tH:n == m \/ m < nm <= n /\ min n m == mn, m:tH:n == m \/ m < nH0:m <= nm <= n /\ min n m == mnow apply min_r. Qed.n, m:tH:n == m \/ m < nH0:m <= nmin n m == mn, m:tn <= m /\ min n m == n \/ m <= n /\ min n m == mdestruct (min_spec n m); [left|right]; intuition; order. Qed.n, m:tn <= m /\ min n m == n \/ m <= n /\ min n m == mProper (eq ==> eq ==> eq) minProper (eq ==> eq ==> eq) minx, x':tHx:x == x'y, y':tHy:y == y'min x y == min x' y'x, x':tHx:x == x'y, y':tHy:y == y'H1:x < y /\ min x y == x \/ y <= x /\ min x y == ymin x y == min x' y'x, x':tHx:x == x'y, y':tHy:y == y'H1:x < y /\ min x y == x \/ y <= x /\ min x y == yH2:x' < y' /\ min x' y' == x' \/ y' <= x' /\ min x' y' == y'min x y == min x' y'x, x':tHx:x == x'y, y':tHy:y == y'm:tH1:x < y /\ m == x \/ y <= x /\ m == ym':tH2:x' < y' /\ m' == x' \/ y' <= x' /\ m' == y'm == m'destruct (lt_total x y); intuition order. Qed.x, x':tHx:x == x'y, y':tHy:y == y'm:tH1:x < y /\ m == x \/ y <= x /\ m == ym':tH2:x < y /\ m' == x \/ y <= x /\ m' == ym == m'n, m, p:tn < m /\ p == n \/ m <= n /\ p == m -> p == min n mn, m, p:tn < m /\ p == n \/ m <= n /\ p == m -> p == min n mdestruct (lt_total n m); intuition; order. Qed.n, m, p:tHm:n < m /\ min n m == n \/ m <= n /\ min n m == mn < m /\ p == n \/ m <= n /\ p == m -> p == min n mf:t -> t -> t(forall n m : t, n < m /\ f n m == n \/ m <= n /\ f n m == m) -> forall n m : t, f n m == min n mf:t -> t -> t(forall n m : t, n < m /\ f n m == n \/ m <= n /\ f n m == m) -> forall n m : t, f n m == min n mapply min_unicity; auto. Qed.f:t -> t -> tH:forall n0 m0 : t, n0 < m0 /\ f n0 m0 == n0 \/ m0 <= n0 /\ f n0 m0 == m0n, m:tf n m == min n mf:t -> tProper (eq ==> eq) f -> Proper (le ==> le) f -> forall x y : t, min (f x) (f y) == f (min x y)f:t -> tProper (eq ==> eq) f -> Proper (le ==> le) f -> forall x y : t, min (f x) (f y) == f (min x y)f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tmin (f x) (f y) == f (min x y)f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:x < yE:min x y == xH':f y <= f xE':min (f x) (f y) == f ymin (f x) (f y) == f xf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:y <= xE:min x y == yH':f x < f yE':min (f x) (f y) == f xmin (f x) (f y) == f yf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:x < yE:min x y == xH':f y <= f xE':min (f x) (f y) == f ymin (f x) (f y) == f xorder.f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:x < yE:min x y == xH':f y <= f xE':min (f x) (f y) == f yH0:f x <= f ymin (f x) (f y) == f xf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:y <= xE:min x y == yH':f x < f yE':min (f x) (f y) == f xmin (f x) (f y) == f yorder. Qed.f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> le) fx, y:tH:y <= xE:min x y == yH':f x < f yE':min (f x) (f y) == f xH0:f y <= f xmin (f x) (f y) == f yn:tmin n n == napply min_l; order. Qed. Notation min_idempotent := min_id (only parsing).n:tmin n n == nm, n, p:tmin m (min n p) == min (min m n) pm, n, p:tmin m (min n p) == min (min m n) pm, n, p:tH:n < pE:min n p == nH':m < nE':min m n == mm == min m pm, n, p:tH:p <= nE:min n p == pH':n <= mE':min m n == nmin m p == pm, n, p:tH:n < pE:min n p == nH':m < nE':min m n == mm == min m papply min_l; order.m, n, p:tH:n < pE:min n p == nH':m < nE':min m n == mmin m p == mapply min_r; order. Qed.m, n, p:tH:p <= nE:min n p == pH':n <= mE':min m n == nmin m p == pn, m:tmin n m == min m ndestruct (min_spec m n) as [(H,E)|(H,E)]; rewrite E; (apply min_r || apply min_l); order. Qed. Ltac solve_min := match goal with |- context [min ?n ?m] => destruct (min_spec n m); intuition; order end.n, m:tmin n m == min m nn, m:tmin n m <= msolve_min. Qed.n, m:tmin n m <= mn, m:tmin n m <= nsolve_min. Qed.n, m:tmin n m <= nn, m:tmin n m == n <-> n <= msolve_min. Qed.n, m:tmin n m == n <-> n <= mn, m:tmin n m == m <-> m <= nsolve_min. Qed.n, m:tmin n m == m <-> m <= nn, m, p:tmin n m <= p -> n <= p \/ m <= pdestruct (min_spec n m); [left|right]; intuition; order. Qed.n, m, p:tmin n m <= p -> n <= p \/ m <= pn, m, p:tmin n m <= p <-> n <= p \/ m <= pn, m, p:tmin n m <= p <-> n <= p \/ m <= pn, m, p:tmin n m <= p -> n <= p \/ m <= pn, m, p:tn <= p \/ m <= p -> min n m <= papply min_le.n, m, p:tmin n m <= p -> n <= p \/ m <= psolve_min. Qed.n, m, p:tn <= p \/ m <= p -> min n m <= pn, m, p:tmin n m < p <-> n < p \/ m < pdestruct (min_spec n m); intuition; order || (right; order) || (left; order). Qed.n, m, p:tmin n m < p <-> n < p \/ m < pn, m, p:tp <= min n m -> p <= nsolve_min. Qed.n, m, p:tp <= min n m -> p <= nn, m, p:tp <= min n m -> p <= msolve_min. Qed.n, m, p:tp <= min n m -> p <= mn, m, p:tp <= n -> p <= m -> p <= min n msolve_min. Qed.n, m, p:tp <= n -> p <= m -> p <= min n mn, m, p:tp <= min n m <-> p <= n /\ p <= msolve_min. Qed.n, m, p:tp <= min n m <-> p <= n /\ p <= mn, m, p:tp < n -> p < m -> p < min n msolve_min. Qed.n, m, p:tp < n -> p < m -> p < min n mn, m, p:tp < min n m <-> p < n /\ p < msolve_min. Qed.n, m, p:tp < min n m <-> p < n /\ p < mn, m, p:tn <= m -> min p n <= min p mn, m, p:tn <= m -> min p n <= min p mn, m, p:tH:n <= mmin p n <= min p msolve_min. Qed.n, m, p:tH:n <= mmin p n <= p /\ min p n <= mn, m, p:tn <= m -> min n p <= min m pn, m, p:tn <= m -> min n p <= min m pn, m, p:tH:n <= mmin n p <= min m psolve_min. Qed.n, m, p:tH:n <= mmin n p <= m /\ min n p <= pn, m, p, q:tn <= m -> p <= q -> min n p <= min m qn, m, p, q:tn <= m -> p <= q -> min n p <= min m qn, m, p, q:tHnm:n <= mHpq:p <= qmin n p <= min m qn, m, p, q:tHnm:n <= mHpq:p <= qLE:min m p <= min m qmin n p <= min m qorder. Qed.n, m, p, q:tHnm:n <= mHpq:p <= qLE:min m p <= min m qLE':min n p <= min m pmin n p <= min m q
n, m:tmax n (min n m) == nn, m:tmax n (min n m) == nn, m:tmax n (min n m) == nn, m:tC:n < mE:min n m == nmax n n == nn, m:tC:m <= nE:min n m == mmax n m == nn, m:tC:n < mE:min n m == nmax n n == norder.n, m:tC:n < mE:min n m == nn <= ndestruct (max_spec n m); intuition; order. Qed.n, m:tC:m <= nE:min n m == mmax n m == nn, m:tmin n (max n m) == nn, m:tmin n (max n m) == nn, m:tmin n (max n m) == nn, m:tC:n < mE:max n m == mmin n m == nn, m:tC:m <= nE:max n m == nmin n n == nn, m:tC:n < mE:max n m == mmin n m == norder.n, m:tC:n < mE:max n m == mC':m <= nE':min n m == mmin n m == nn, m:tC:m <= nE:max n m == nmin n n == norder. Qed.n, m:tC:m <= nE:max n m == nn <= n
Distributivity
n, m, p:tmax n (min m p) == min (max n m) (max n p)n, m, p:tmax n (min m p) == min (max n m) (max n p)n, m, p:tmin (max n m) (max n p) == max n (min m p)n, m, p:tProper (eq ==> eq) (max n)n, m, p:tProper (le ==> le) (max n)eauto with *.n, m, p:tProper (eq ==> eq) (max n)n, m, p:tProper (le ==> le) (max n)apply max_le_compat_l; auto. Qed.n, m, p, x, y:tH:x <= ymax n x <= max n yn, m, p:tmin n (max m p) == max (min n m) (min n p)n, m, p:tmin n (max m p) == max (min n m) (min n p)n, m, p:tmax (min n m) (min n p) == min n (max m p)n, m, p:tProper (eq ==> eq) (min n)n, m, p:tProper (le ==> le) (min n)eauto with *.n, m, p:tProper (eq ==> eq) (min n)n, m, p:tProper (le ==> le) (min n)apply min_le_compat_l; auto. Qed.n, m, p, x, y:tH:x <= ymin n x <= min n y
Modularity
n, m, p:tmax n (min m (max n p)) == min (max n m) (max n p)n, m, p:tmax n (min m (max n p)) == min (max n m) (max n p)n, m, p:tmax n (min m (max n p)) == max n (min m p)n, m, p:tC:p <= nE:max n p == nmax n (min m n) == max n (min m p)n, m, p:tC:p <= nE:max n p == nC':m < nE':min m n == mmax n m == max n (min m p)n, m, p:tC:p <= nE:max n p == nC':n <= mE':min m n == nmax n n == max n (min m p)n, m, p:tC:p <= nE:max n p == nC':m < nE':min m n == mmax n m == max n (min m p)rewrite min_le_iff; auto.n, m, p:tC:p <= nE:max n p == nC':m < nE':min m n == mmin m p <= nn, m, p:tC:p <= nE:max n p == nC':n <= mE':min m n == nmax n n == max n (min m p)rewrite min_le_iff; auto. Qed.n, m, p:tC:p <= nE:max n p == nC':n <= mE':min m n == nmin m p <= nn, m, p:tmin n (max m (min n p)) == max (min n m) (min n p)n, m, p:tmin n (max m (min n p)) == max (min n m) (min n p)n, m, p:tmin n (max m (min n p)) == max (min n m) (min n p)n, m, p:tmin n (max m (min n p)) == min n (max m p)n, m, p:tC:n < pE:min n p == nmin n (max m n) == min n (max m p)n, m, p:tC:n < pE:min n p == nC':m < nE':max m n == nmin n n == min n (max m p)n, m, p:tC:n < pE:min n p == nC':n <= mE':max m n == mmin n m == min n (max m p)n, m, p:tC:n < pE:min n p == nC':m < nE':max m n == nmin n n == min n (max m p)rewrite max_le_iff; right; order.n, m, p:tC:n < pE:min n p == nC':m < nE':max m n == nn <= max m pn, m, p:tC:n < pE:min n p == nC':n <= mE':max m n == mmin n m == min n (max m p)rewrite max_le_iff; auto. Qed.n, m, p:tC:n < pE:min n p == nC':n <= mE':max m n == mn <= max m p
Disassociativity
n, m, p:tmin n (max m p) <= max (min n m) pn, m, p:tmin n (max m p) <= max (min n m) pn, m, p:tmin n (max m p) <= max (min n m) pauto using max_le_compat_l, le_min_r. Qed.n, m, p:tmax (min n m) (min n p) <= max (min n m) p
Anti-monotonicity swaps the role of min and max
f:t -> tProper (eq ==> eq) f -> Proper (le ==> flip le) f -> forall x y : t, max (f x) (f y) == f (min x y)f:t -> tProper (eq ==> eq) f -> Proper (le ==> flip le) f -> forall x y : t, max (f x) (f y) == f (min x y)f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tmax (f x) (f y) == f (min x y)f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:x < yE:min x y == xH':f x < f yE':max (f x) (f y) == f ymax (f x) (f y) == f xf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:y <= xE:min x y == yH':f y <= f xE':max (f x) (f y) == f xmax (f x) (f y) == f yf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:x < yE:min x y == xH':f x < f yE':max (f x) (f y) == f ymax (f x) (f y) == f xorder.f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:x < yE:min x y == xH':f x < f yE':max (f x) (f y) == f yH0:f y <= f xmax (f x) (f y) == f xf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:y <= xE:min x y == yH':f y <= f xE':max (f x) (f y) == f xmax (f x) (f y) == f yorder. Qed.f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:y <= xE:min x y == yH':f y <= f xE':max (f x) (f y) == f xH0:f x <= f ymax (f x) (f y) == f yf:t -> tProper (eq ==> eq) f -> Proper (le ==> flip le) f -> forall x y : t, min (f x) (f y) == f (max x y)f:t -> tProper (eq ==> eq) f -> Proper (le ==> flip le) f -> forall x y : t, min (f x) (f y) == f (max x y)f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tmin (f x) (f y) == f (max x y)f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:x < yE:max x y == yH':f x < f yE':min (f x) (f y) == f xmin (f x) (f y) == f yf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:y <= xE:max x y == xH':f y <= f xE':min (f x) (f y) == f ymin (f x) (f y) == f xf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:x < yE:max x y == yH':f x < f yE':min (f x) (f y) == f xmin (f x) (f y) == f yorder.f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:x < yE:max x y == yH':f x < f yE':min (f x) (f y) == f xH0:f y <= f xmin (f x) (f y) == f yf:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:y <= xE:max x y == xH':f y <= f xE':min (f x) (f y) == f ymin (f x) (f y) == f xorder. Qed. End MinMaxLogicalProperties.f:t -> tEqf:Proper (eq ==> eq) fLef:Proper (le ==> flip le) fx, y:tH:y <= xE:max x y == xH':f y <= f xE':min (f x) (f y) == f yH0:f x <= f ymin (f x) (f y) == f x
Module MinMaxDecProperties (Import O:OrderedTypeFull')(Import M:HasMinMax O).
Induction principles for max.
n, m:tP:t -> Type(forall x y : t, x == y -> P x -> P y) -> (m <= n -> P n) -> (n <= m -> P m) -> P (max n m)n, m:tP:t -> Type(forall x y : t, x == y -> P x -> P y) -> (m <= n -> P n) -> (n <= m -> P m) -> P (max n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mP (max n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mEQ:n == mP (max n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mLT:n < mP (max n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mGT:m < nP (max n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mEQ:n == mP (max n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mEQ:n == mH:n <= mP (max n m)symmetry; apply max_r; auto.n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mEQ:n == mH:n <= mm == max n mn, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mLT:n < mP (max n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mLT:n < mH:n <= mP (max n m)symmetry; apply max_r; auto.n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mLT:n < mH:n <= mm == max n mn, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mGT:m < nP (max n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mGT:m < nH:m <= nP (max n m)symmetry; apply max_l; auto. Defined.n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:m <= n -> P nHr:n <= m -> P mGT:m < nH:m <= nn == max n mn, m:tP:t -> Type(forall x y : t, x == y -> P x -> P y) -> P n -> P m -> P (max n m)n, m:tP:t -> Type(forall x y : t, x == y -> P x -> P y) -> P n -> P m -> P (max n m)apply max_case_strong; auto. Defined.n, m:tP:t -> TypeX:forall x y : t, x == y -> P x -> P yX0:P nX1:P mP (max n m)
max returns one of its arguments.
n, m:t{max n m == n} + {max n m == m}n, m:t{max n m == n} + {max n m == m}intros x y H [E|E]; [left|right]; rewrite <-H; auto. Defined.n, m:tforall x y : t, x == y -> {x == n} + {x == m} -> {y == n} + {y == m}
Idem for min
n, m:tP:t -> Type(forall x y : t, x == y -> P x -> P y) -> (n <= m -> P n) -> (m <= n -> P m) -> P (min n m)n, m:tP:t -> Type(forall x y : t, x == y -> P x -> P y) -> (n <= m -> P n) -> (m <= n -> P m) -> P (min n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mP (min n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mEQ:n == mP (min n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mLT:n < mP (min n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mGT:m < nP (min n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mEQ:n == mP (min n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mEQ:n == mH:n <= mP (min n m)symmetry; apply min_l; auto.n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mEQ:n == mH:n <= mn == min n mn, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mLT:n < mP (min n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mLT:n < mH:n <= mP (min n m)symmetry; apply min_l; auto.n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mLT:n < mH:n <= mn == min n mn, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mGT:m < nP (min n m)n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mGT:m < nH:m <= nP (min n m)symmetry; apply min_r; auto. Defined.n, m:tP:t -> TypeCompat:forall x y : t, x == y -> P x -> P yHl:n <= m -> P nHr:m <= n -> P mGT:m < nH:m <= nm == min n mn, m:tP:t -> Type(forall x y : t, x == y -> P x -> P y) -> P n -> P m -> P (min n m)n, m:tP:t -> Type(forall x y : t, x == y -> P x -> P y) -> P n -> P m -> P (min n m)apply min_case_strong; auto. Defined.n, m:tP:t -> TypeX:forall x y : t, x == y -> P x -> P yX0:P nX1:P mP (min n m)n, m:t{min n m == n} + {min n m == m}n, m:t{min n m == n} + {min n m == m}n, m:t{min n m == n} + {min n m == m}intros x y H [E|E]; [left|right]; rewrite <- E; auto with relations. Defined. End MinMaxDecProperties. Module MinMaxProperties (Import O:OrderedTypeFull')(Import M:HasMinMax O). Module OT := OTF_to_TotalOrder O. Include MinMaxLogicalProperties OT M. Include MinMaxDecProperties O M. Definition max_l := max_l. Definition max_r := max_r. Definition min_l := min_l. Definition min_r := min_r. Notation max_monotone := max_mono. Notation min_monotone := min_mono. Notation max_min_antimonotone := max_min_antimono. Notation min_max_antimonotone := min_max_antimono. End MinMaxProperties.n, m:tforall x y : t, x == y -> {x == n} + {x == m} -> {y == n} + {y == m}
Module UsualMinMaxLogicalProperties (Import O:UsualTotalOrder')(Import M:HasMinMax O). Include MinMaxLogicalProperties O M.f:t -> tProper (le ==> le) f -> forall x y : t, max (f x) (f y) = f (max x y)f:t -> tProper (le ==> le) f -> forall x y : t, max (f x) (f y) = f (max x y)congruence. Qed.f:t -> tH:Proper (le ==> le) fx, y:tProper (Logic.eq ==> Logic.eq) ff:t -> tProper (le ==> le) f -> forall x y : t, min (f x) (f y) = f (min x y)f:t -> tProper (le ==> le) f -> forall x y : t, min (f x) (f y) = f (min x y)congruence. Qed.f:t -> tH:Proper (le ==> le) fx, y:tProper (Logic.eq ==> Logic.eq) ff:t -> tProper (le ==> flip le) f -> forall x y : t, min (f x) (f y) = f (max x y)f:t -> tProper (le ==> flip le) f -> forall x y : t, min (f x) (f y) = f (max x y)congruence. Qed.f:t -> tH:Proper (le ==> flip le) fx, y:tProper (Logic.eq ==> Logic.eq) ff:t -> tProper (le ==> flip le) f -> forall x y : t, max (f x) (f y) = f (min x y)f:t -> tProper (le ==> flip le) f -> forall x y : t, max (f x) (f y) = f (min x y)congruence. Qed. End UsualMinMaxLogicalProperties. Module UsualMinMaxDecProperties (Import O:UsualOrderedTypeFull')(Import M:HasMinMax O). Module Import Private_Dec := MinMaxDecProperties O M.f:t -> tH:Proper (le ==> flip le) fx, y:tProper (Logic.eq ==> Logic.eq) fforall (n m : t) (P : t -> Type), (m <= n -> P n) -> (n <= m -> P m) -> P (max n m)forall (n m : t) (P : t -> Type), (m <= n -> P n) -> (n <= m -> P m) -> P (max n m)congruence. Defined.n, m:tP:t -> TypeX:m <= n -> P nX0:n <= m -> P mforall x y : t, x = y -> P x -> P yforall (n m : t) (P : t -> Type), P n -> P m -> P (max n m)intros; apply max_case_strong; auto. Defined.forall (n m : t) (P : t -> Type), P n -> P m -> P (max n m)forall n m : t, {max n m = n} + {max n m = m}exact max_dec. Defined.forall n m : t, {max n m = n} + {max n m = m}forall (n m : t) (P : t -> Type), (n <= m -> P n) -> (m <= n -> P m) -> P (min n m)forall (n m : t) (P : t -> Type), (n <= m -> P n) -> (m <= n -> P m) -> P (min n m)congruence. Defined.n, m:tP:t -> TypeX:n <= m -> P nX0:m <= n -> P mforall x y : t, x = y -> P x -> P yforall (n m : t) (P : t -> Type), P n -> P m -> P (min n m)forall (n m : t) (P : t -> Type), P n -> P m -> P (min n m)apply min_case_strong; auto. Defined.n, m:tP:t -> TypeX:P nX0:P mP (min n m)forall n m : t, {min n m = n} + {min n m = m}exact min_dec. Defined. End UsualMinMaxDecProperties. Module UsualMinMaxProperties (Import O:UsualOrderedTypeFull')(Import M:HasMinMax O). Module OT := OTF_to_TotalOrder O. Include UsualMinMaxLogicalProperties OT M. Include UsualMinMaxDecProperties O M. Definition max_l := max_l. Definition max_r := max_r. Definition min_l := min_l. Definition min_r := min_r. End UsualMinMaxProperties.forall n m : t, {min n m = n} + {min n m = m}
From TotalOrder and HasMax and HasEqDec, we can prove
that the order is decidable and build an OrderedTypeFull.
Module TOMaxEqDec_to_Compare (Import O:TotalOrder')(Import M:HasMax O)(Import E:HasEqDec O) <: HasCompare O. Definition compare x y := if eq_dec x y then Eq else if eq_dec (M.max x y) y then Lt else Gt.forall x y : t, CompSpec eq lt x y (compare x y)forall x y : t, CompSpec eq lt x y (compare x y)x, y:tn:x ~= ye:max x y == yx < yx, y:tn:x ~= yn0:max x y ~= yy < xx, y:tn:x ~= ye:max x y == yx < yx, y:tn:x ~= ye:max x y == yH:x == y \/ y < xx < yx, y:tn:x ~= ye:max x y == yH:x == y \/ y < xx == yx, y:tn:x ~= ye:max x y == yH:x == y \/ y < xx == max x yx, y:tn:x ~= ye:max x y == yH:x == y \/ y < xmax x y == xrewrite le_lteq; intuition.x, y:tn:x ~= ye:max x y == yH:x == y \/ y < xy <= xx, y:tn:x ~= yn0:max x y ~= yy < xx, y:tn:x ~= yn0:max x y ~= yH:y == x \/ x < yy < xapply max_r; rewrite le_lteq; intuition. Qed. End TOMaxEqDec_to_Compare. Module TOMaxEqDec_to_OTF (O:TotalOrder)(M:HasMax O)(E:HasEqDec O) <: OrderedTypeFull := O <+ E <+ TOMaxEqDec_to_Compare O M E.x, y:tn:x ~= yn0:max x y ~= yH:y == x \/ x < ymax x y == y
TODO: Some Remaining questions...
--> Compare with a type-classes version ?
--> Is max_unicity and max_unicity_ext really convenient to express
that any possible definition of max will in fact be equivalent ?
--> Is it possible to avoid copy-paste about min even more ?