(* (c) Copyright 2006-2016 Microsoft Corporation and Inria.                  *)
(* Distributed under the terms of CeCILL-B.                                  *)
From mathcomp
From mathcomp
(******************************************************************************)
(* This file defines a type for sets over a finite Type, similar to the type  *)
(* of functions over a finite Type defined in finfun.v (indeed, based in it): *)
(*  {set T} where T must have a finType structure                             *)
(* We equip {set T} itself with a finType structure, hence Leibnitz and       *)
(* extensional equalities coincide on {set T}, and we can form {set {set T}}  *)
(*   If A, B : {set T} and P : {set {set T}}, we define:                      *)
(*           x \in A == x belongs to A (i.e., {set T} implements predType,    *)
(*                      by coercion to pred_sort).                            *)
(*             mem A == the predicate corresponding to A.                     *)
(*          finset p == the set corresponding to a predicate p.               *)
(*       [set x | P] == the set containing the x such that P is true (x may   *)
(*                      appear in P).                                         *)
(*   [set x | P & Q] := [set x | P && Q].                                     *)
(*      [set x in A] == the set containing the x in a collective predicate A. *)
(*  [set x in A | P] == the set containing the x in A such that P is true.    *)
(* [set x in A | P & Q] := [set x in A | P && Q].                             *)
(*  All these have typed variants [set x : T | P], [set x : T in A], etc.     *)
(*              set0 == the empty set.                                        *)
(*  [set: T] or setT == the full set (the A containing all x : T).            *)
(*           A :|: B == the union of A and B.                                 *)
(*            x |: A == A with the element x added (:= [set x] :| A).         *)
(*           A :&: B == the intersection of A and B.                          *)
(*              ~: A == the complement of A.                                  *)
(*           A :\: B == the difference A minus B.                             *)
(*            A :\ x == A with the element x removed (:= A :\: [set x]).      *)
(* \bigcup_<range> A == the union of all A, for i in <range> (i is bound in   *)
(*                      A, see bigop.v).                                      *)
(* \bigcap_<range> A == the intersection of all A, for i in <range>.          *)
(*           cover P == the union of the set of sets P.                       *)
(*        trivIset P <=> the elements of P are pairwise disjoint.             *)
(*     partition P A <=> P is a partition of A.                               *)
(*        pblock P x == a block of P containing x, or else set0.              *)
(* equivalence_partition R D == the partition induced on D by the relation R  *)
(*                       (provided R is an equivalence relation in D).        *)
(*       preim_partition f D == the partition induced on D by the equivalence *)
(*                              [rel x y | f x == f y].                       *)
(*    is_transversal X P D <=> X is a transversal of the partition P of D.    *)
(*   transversal P D == a transversal of P, provided P is a partition of D.   *)
(*  transversal_repr x0 X B == a representative of B \in P selected by the    *)
(*                      tranversal X of P, or else x0.                        *)
(*        powerset A == the set of all subset of the set A.                   *)
(*          P ::&: A == those sets in P that are subsets of the set A.        *)
(*         f @^-1: A == the preimage of the collective predicate A under f.   *)
(*            f @: A == the image set of the collective predicate A by f.     *)
(*       f @2:(A, B) == the image set of A x B by the binary function f.      *)
(*  [set E | x in A] == the set of all the values of the expression E, for x  *)
(*                      drawn from the collective predicate A.                *)
(*  [set E | x in A & P] == the set of values of E for x drawn from A, such   *)
(*                      that P is true.                                       *)
(*  [set E | x in A, y in B] == the set of values of E for x drawn from A and *)
(*                      and y drawn from B; B may depend on x.                *)
(*  [set E | x <- A, y <- B & P] == the set of values of E for x drawn from A *)
(*                      y drawn from B, such that P is trye.                  *)
(*  [set E | x : T] == the set of all values of E, with x in type T.          *)
(*  [set E | x : T & P] == the set of values of E for x : T s.t. P is true.   *)
(*  [set E | x : T, y : U in B], [set E | x : T, y : U in B & P],             *)
(*  [set E | x : T in A, y : U], [set E | x : T in A, y : U & P],             *)
(*  [set E | x : T, y : U], [set E | x : T, y : U & P]                        *)
(*             == type-ranging versions of the binary comprehensions.         *)
(*   [set E | x : T in A], [set E | x in A, y], [set E | x, y & P], etc.      *)
(*             == typed and untyped variants of the comprehensions above.     *)
(*                The types may be required as type inference processes E     *)
(*                before considering A or B. Note that type casts in the      *)
(*                binary comprehension must either be both present or absent  *)
(*                and that there are no untyped variants for single-type      *)
(*                comprehension as Coq parsing confuses [x | P] and [E | x].  *)
(*        minset p A == A is a minimal set satisfying p.                      *)
(*        maxset p A == A is a maximal set satisfying p.                      *)
(* We also provide notations A :=: B, A :<>: B, A :==: B, A :!=: B, A :=P: B  *)
(* that specialize A = B, A <> B, A == B, etc., to {set _}. This is useful    *)
(* for subtypes of {set T}, such as {group T}, that coerce to {set T}.        *)
(*   We give many lemmas on these operations, on card, and on set inclusion.  *)
(* In addition to the standard suffixes described in ssrbool.v, we associate  *)
(* the following suffixes to set operations:                                  *)
(*  0 -- the empty set, as in in_set0 : (x \in set0) = false.                 *)
(*  T -- the full set, as in in_setT : x \in [set: T].                        *)
(*  1 -- a singleton set, as in in_set1 : (x \in [set a]) = (x == a).         *)
(*  2 -- an unordered pair, as in                                             *)
(*          in_set2 : (x \in [set a; b]) = (x == a) || (x == b).              *)
(*  C -- complement, as in setCK : ~: ~: A = A.                               *)
(*  I -- intersection, as in setIid : A :&: A = A.                            *)
(*  U -- union, as in setUid : A :|: A = A.                                   *)
(*  D -- difference, as in setDv : A :\: A = set0.                            *)
(*  S -- a subset argument, as in                                             *)
(*         setIS: B \subset C -> A :&: B \subset A :&: C                      *)
(* These suffixes are sometimes preceded with an `s' to distinguish them from *)
(* their basic ssrbool interpretation, e.g.,                                  *)
(*  card1 : #|pred1 x| = 1 and cards1 : #|[set x]| = 1                        *)
(* We also use a trailling `r' to distinguish a right-hand complement from    *)
(* commutativity, e.g.,                                                       *)
(*  setIC : A :&: B = B :&: A and setICr : A :&: ~: A = set0.                 *)
(******************************************************************************)
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Section SetType.
Variable T : finType.
Inductive set_type : predArgType := FinSet of {ffun pred T}.
Definition finfun_of_set A := let: FinSet f := A in f.
Definition set_of of phant T := set_type.
Identity Coercion type_of_set_of : set_of >-> set_type.
Canonical set_subType := Eval hnf in [newType for finfun_of_set].
Definition set_eqMixin := Eval hnf in [eqMixin of set_type by <:].
Canonical set_eqType := Eval hnf in EqType set_type set_eqMixin.
Definition set_choiceMixin := [choiceMixin of set_type by <:].
Canonical set_choiceType := Eval hnf in ChoiceType set_type set_choiceMixin.
Definition set_countMixin := [countMixin of set_type by <:].
Canonical set_countType := Eval hnf in CountType set_type set_countMixin.
Canonical set_subCountType := Eval hnf in [subCountType of set_type].
Definition set_finMixin := [finMixin of set_type by <:].
Canonical set_finType := Eval hnf in FinType set_type set_finMixin.
Canonical set_subFinType := Eval hnf in [subFinType of set_type].
End SetType.
Delimit Scope set_scope with SET.
Bind Scope set_scope with set_type.
Bind Scope set_scope with set_of.
Open Scope set_scope.
Arguments finfun_of_set {T} A%SET.
Notation "{ 'set' T }" := (set_of (Phant T))
(at level 0, format "{ 'set'  T }") : type_scope.
(* We later define several subtypes that coerce to set; for these it is       *)
(* preferable to state equalities at the {set _} level, even when comparing   *)
(* subtype values, because the primitive "injection" tactic tends to diverge  *)
(* on complex types (e.g., quotient groups). We provide some parse-only       *)
(* notation to make this technicality less obstrusive.                        *)
Notation "A :=: B" := (A = B :> {set _})
(at level 70, no associativity, only parsing) : set_scope.
Notation "A :<>: B" := (A <> B :> {set _})
(at level 70, no associativity, only parsing) : set_scope.
Notation "A :==: B" := (A == B :> {set _})
(at level 70, no associativity, only parsing) : set_scope.
Notation "A :!=: B" := (A != B :> {set _})
(at level 70, no associativity, only parsing) : set_scope.
Notation "A :=P: B" := (A =P B :> {set _})
(at level 70, no associativity, only parsing) : set_scope.
Local Notation finset_def := (fun T P => @FinSet T (finfun P)).
Local Notation pred_of_set_def := (fun T (A : set_type T) => val A : _ -> _).
Module Type SetDefSig.
Parameter finset : forall T : finType, pred T -> {set T}.
Parameter pred_of_set : forall T, set_type T -> fin_pred_sort (predPredType T).

(* Specifications: *)
(* The weird type of pred_of_set is imposed by the syntactic restrictions on  *)
(* coercion declarations; it is unfortunately not possible to use a functor   *)
(* to retype the declaration, because this triggers an ugly bug in the Coq    *)
(* coercion chaining code.                                                    *)
Axiom finsetE : finset = finset_def.
Axiom pred_of_setE : pred_of_set = pred_of_set_def.
End SetDefSig.