Require Import mathcomp.ssreflect.ssreflect.

Require Import edone bcase base.

Finite Sets over choice types and countable types

This file defines a type {fset T} of finite sets over a type T with choice. The type {fset T} is implemented as constructive quotient on duplicate free lists. If T is a countable type, then {fset T}, {fset {fset T}}, etc. also are countable types.
For X,Y : {fset T} and x,y : T we define.
x \in X == x is an element of X (i.e., {fset X} is a predType)
fset0 == the empty set
[fset x] == singleton x
[fset x in X | P] == separation (i.e, the elements of A satisfying P)
[fset f x | x <- X] == replacement (i.e., map)
[fset f x | x <- X,P] == replacement (i.e., map)
[fset x;..;y] == explicit set
[fset x;..;y & X] == x |` (.. (y |` X))
X `|` Y == the union of X and Y
x |` X == [fset x] `|` X
X `&` Y == the intersection of X and Y
\bigcup_(x in X) F == the union of all F x where x ranges over X
powerset X == the poweset of X (of type {fset {fset T}})
X `<=` Y == X is a subset of Y
X `<` Y == X is a proper subset of Y
size X == the cardinality of X (via coercion to seq T)
fsum w X == the sum of the weights of the elements in X (w : T -> nat)
If F : {fset T} -> {fset T} is a monotone function bounded by some set
lfp F == the least fipoint of F
gfp F == the greatest fixpoint of F
We port a large protion of the lemmas from finset.v. Lemmas corresponding to lemmas in finset.v have a 'f' prefixed to their name (or the string 'set') Otherwise we follow a similar naming convention:
0 -- the empty set
1 -- singleton set
I -- intersection
U -- union
D -- difference
S -- subset

Set Implicit Arguments.
Import Prenex Implicits.


We build finite sets over choice types and countable types by chosing a unique, duplicate free list as canonical representative of every set.

Section FinSets.
  Variable T : choiceType.

  Definition fset_axiom (el : seq T) := uniq el && (el == choose (perm_eq el) el).
  Record fset_type := Fset { elements :> seq T ; _ : fset_axiom elements}.

  Definition fset_of of phant T := fset_type.
  Identity Coercion type_of_fset_of : fset_of >-> fset_type.

  Canonical Structure fset_subType := [subType for elements by fset_type_rect].
  Canonical Structure fset_eqType := EqType _ [eqMixin of fset_type by <:].
  Canonical Structure fset_predType := mkPredType (fun (X : fset_type) x => nosimpl x \in elements X).
  Canonical Structure fset_choiceType := Eval hnf in ChoiceType _ [choiceMixin of fset_type by <:].
End FinSets.

Additional Canonical Structures in case T is a countType. This allows sets of sets of countTypes

Canonical Structure fset_countType (T : countType) :=
  Eval hnf in CountType _ [countMixin of fset_type T by <:].
Canonical Structure fset_subCountType (T : countType) :=
  Eval hnf in [subCountType of fset_type T].

Notation for fsets using Phant to allow the type checker to infer the Caonical Structure for the element type

Notation "{ 'fset' T }" := (fset_of (Phant T))
  (at level 0, format "{ 'fset' T }") : type_scope.

Section Extensionality.
  Variables T : choiceType.

  Lemma fset_eq X Y : X =i Y -> X == Y :> {fset T}.

  Lemma fset_ext X Y : X =i Y -> X = Y :> {fset T}.
End Extensionality.

In conntrast to finite sets over finite types, where sets are constructed from predicates, we contruct sets from seqences by chosing a ducplicate free equivalent.

Section SetOfSeq.
  Variable (T : choiceType).

  Definition fseq (xs : seq T) : seq T :=
    let e := undup xs in choose (perm_eq e) e.

  Lemma fseq_perm_eq xs : perm_eq (undup xs) (fseq xs).

  Lemma fseq_uniq xs : uniq (fseq xs).

  Lemma fseq_axiom (xs : seq T) : fset_axiom (fseq xs).

  Definition set_of xs : {fset T} := Fset (fseq_axiom xs).

  Lemma set_ofE x xs : (x \in set_of xs) = (x \in xs).

  Lemma funiq (X : {fset T}) : uniq X.

  Lemma set_of_uniq (s : seq T) : uniq s -> perm_eq (set_of s) s.
End SetOfSeq.
Global Opaque set_of.

Primitive operations

The primitive operations for the construction of sets are separation, union, singleton, emptyset and replacement (imset).


Module Type FsetType.
  Implicit Types (T aT rT : choiceType).
  Parameter sep : forall T, {fset T} -> pred T -> {fset T}.
  Axiom sepE : sep = sep_def.
  Parameter fsetU : forall T, {fset T} -> {fset T} -> {fset T}.
  Axiom fsetUE : fsetU = fsetU_def.
  Parameter fset0_ : forall T, {fset T}.
  Axiom fset0E : fset0_ = fset0_def.
  Parameter fset1 : forall T, T-> {fset T}.
  Axiom fset1E : fset1 = fset1_def.
  Parameter fimset : forall aT rT, (aT -> rT) -> {fset aT} -> {fset rT}.
  Axiom fimsetE : fimset = fimset_def.
  Parameter fimset2 : forall aT aT' rT, (aT -> aT' -> rT) -> {fset aT} -> {fset aT'} -> {fset rT}.
  Axiom fimset2E : fimset2 = fimset2_def.
End FsetType.

Module Fset : FsetType.
  Implicit Types (T aT rT : choiceType).
  Definition sep := sep_def.
  Lemma sepE : sep = sep_def.
  Definition fsetU := fsetU_def.
  Lemma fsetUE : fsetU = fsetU_def.
  Definition fset0_ := fset0_def.
  Lemma fset0E : @fset0_ = fset0_def.
  Definition fset1 := fset1_def.
  Lemma fset1E : fset1 = fset1_def.
  Definition fimset := fimset_def.
  Lemma fimsetE : fimset = fimset_def.
  Definition fimset2 := fimset2_def.
  Lemma fimset2E : fimset2 = fimset2_def.
End Fset.
Export Fset.

Notations


Notation "[ 'fset' x 'in' X | P ]" := (sep X (fun x => P))
  (at level 0, x, X at level 99, format "[ 'fset' x 'in' X | P ]").

Definition fsetI (T : choiceType) (X Y : {fset T}) := [fset x in X | x \in Y].
Definition fsetD (T : choiceType) (X Y : {fset T}) := [fset x in X | x \notin Y].
Definition subset (T : choiceType) (X Y : {fset T}) := all (mem Y) X.
Definition proper (T : choiceType) (X Y : {fset T}) := subset X Y && ~~ subset Y X.
Definition fsetX (T T' : choiceType) (X : {fset T}) (Y : {fset T'}) := fimset2 pair X Y.


Notation "X `|` Y" := (fsetU X Y) (at level 52, left associativity).
Notation "X `&` Y" := (fsetI X Y) (at level 48, left associativity).
Notation "X `\` Y" := (fsetD X Y) (at level 48, left associativity).
Notation "X `<=` Y" := (subset X Y) (at level 70 ,no associativity).
Notation "X `<` Y" := (proper X Y) (at level 70, no associativity).
Notation "[ 'fset' x ]" := (fset1 x) (at level 0,x at level 99, format "[ 'fset' x ]" ).
Notation fset0 := (@fset0_ _).
Notation "f `@` X" := (fimset f X) (at level 45).
Notation "x |` X" := ([fset x] `|` X) (at level 52, left associativity).
Notation "X `x` Y" := (fsetX X Y) (at level 44, left associativity).

This is left recursive to avoid having an explicit fset0 at the end
Notation "[ 'fset' x1 ; x2 ; .. ; xn ]" := (fsetU .. (x1 |` [fset x2]) .. [fset xn])
  (at level 0, x1 at level 99, format "[ 'fset' x1 ; x2 ; .. ; xn ]").
Notation "[ 'fset' x1 , x2 , .. , xn & X ]" := (x1 |` (x2 |` .. (xn |` X) ..))
  (at level 0, x1 at level 99, format "[ 'fset' x1 , x2 , .. , xn & X ]").
Notation "[ 'all' x 'in' s , p ]" := (all (fun x => p) s)
  (at level 0, x at level 99, format "[ 'all' x 'in' s , p ]").
Notation "[ 'some' x 'in' s , p ]" := (has (fun x => p) s)
  (at level 0, x at level 99, format "[ 'some' x 'in' s , p ]").

Notation "[ 'fset' E | x <- X ]" := (fimset (fun x => E) X)
  (at level 0, E, x at level 99, format "[ '[hv' 'fset' E '/ ' | x <- X ] ']'").
Notation "[ 'fset' E | a <- A , b <- B ]" :=
  (fimset2 (fun a b => E) A B) (at level 0, E, a, b at level 99).

Definition fimset3 (aT1 aT2 aT3 rT : choiceType) (f : aT1 -> aT2 -> aT3 -> rT) X Y Z :=
  [fset f x y.1 y.2 | x <- X, y <- Y `x` Z].

Notation "[ 'fset' E | a <- A , b <- B , c <- C ]" :=
  (fimset3 (fun a b c => E) A B C) (at level 0, E, a, b, c at level 99).

Basic Theory


Section OperationsTheory.
  Variable aT1 aT2 aT3 T T': choiceType.
  Implicit Types X Y Z : {fset T}.
  Implicit Types x y z : T.

  Lemma fset0F : set_of [::] = fset0 :> {fset T}.

  Lemma fset1F x : set_of [:: x] = [fset x] :> {fset T}.

For fset0 and fset1 we know the repesentative
  Lemma fset1Es x : [fset x] = [:: x] :> seq T.

  Lemma fset0Es : fset0 = [::] :> seq T.

  Lemma in_sep X p x : x \in [fset y in X | p y] = (x \in X) && (p x).

  Lemma in_fsetU x X Y : (x \in X `|` Y) = (x \in X) || (x \in Y).

  Lemma in_fsetD x X Y : (x \in X `\` Y) = (x \in X) && (x \notin Y).

  Lemma in_fsetI x X Y : (x \in X `&` Y) = (x \in X) && (x \in Y).

  Lemma in_fset0 x : (x \in fset0) = false.

  Lemma in_fset1 x y : (x \in [fset y]) = (x == y).

  Lemma fset11 x : (x \in [fset x]).

  Definition in_fset := (in_sep,in_fsetU,in_fset0,fset11,in_fset1).
  Definition inE := (in_fset,inE).

  Section Laws.
    Variables X Y Z : {fset T}.

    Lemma fsetUA : X `|` (Y `|` Z) = X `|` Y `|` Z.

    Lemma fsetUC : X `|` Y = Y `|` X.

    Lemma fsetIA : X `&` (Y `&` Z) = X `&` Y `&` Z.

    Lemma fsetIC : X `&` Y = Y `&` X.

    Lemma fsetIUr : X `&` (Y `|` Z) = (X `&` Y) `|` (X `&` Z).

    Lemma fsetIUl : (Y `|` Z) `&` X = (Y `&` X) `|` (Z `&` X).

    Lemma fsetUIr : X `|` (Y `&` Z) = (X `|` Y) `&` (X `|` Z).

    Lemma fsetUIl : (Y `&` Z) `|` X = (Y `|` X) `&` (Z `|` X).

    Lemma fset1U x : x \in X -> X = x |` X.

    Lemma fset1U1 x : x \in x |` X.

    Lemma fsetUP x : reflect (x \in X \/ x \in Y) (x \in X `|` Y).

    Lemma fsetU1P y x : reflect (y = x \/ y \in X) (y \in x |` X).
  End Laws.

  Lemma fsetUCA (A B C : {fset T}) : A `|` (B `|` C) = B `|` (A `|` C).

Separation
  Lemma sepU X Y p :
    [fset x in X `|` Y | p x] = [fset x in X | p x] `|` [fset x in Y | p x].

  Lemma sep0 p : [fset x in fset0 | p x] = fset0 :> {fset T}.

  Lemma sep1 (a : T) (p : pred T) :
    [fset x in [fset a] | p x] = if p a then [fset a] else fset0.

  Lemma sepP (p : pred T) X x : reflect (x \in X /\ p x) (x \in [fset x in X | p x]).

Empty Set

  Lemma fset0Vmem X : ( X = fset0 ) + { x | x \in X }.

  Lemma emptyPn X : reflect (exists x , x \in X) (X != fset0).

  Lemma fsetU0 X : X `|` fset0 = X.

  Lemma fset0U X : fset0 `|` X = X.

  Lemma fsetI0 X : fset0 `&` X = fset0.

  Lemma fset0I X : X `&` fset0 = fset0.

  Lemma fsetD0 X : X `\` fset0 = X.

Imset

  Lemma fimsetP X (f : T -> T') a :
    reflect (exists2 x, x \in X & a = f x) (a \in f `@` X).

  Lemma in_fimset x X (f : T -> T') : (x \in X) -> (f x \in f `@` X).

  Variables (A : {fset aT1}) (B : {fset aT2}) (C : {fset aT3}).

  CoInductive fimset2_spec (rT : choiceType) f (y : rT) : Prop :=
    fImset_spec a b : y = f a b -> a \in A -> b \in B -> fimset2_spec f y.

  Lemma fimset2P (rT : choiceType) f (y : rT) :
    reflect (fimset2_spec f y) (y \in fimset2 f A B).

  Lemma mem_fimset2 (rT : choiceType) (f : aT1 -> aT2 -> rT) a b :
    a \in A -> b \in B -> f a b \in fimset2 f A B.

  Definition injective2 (f : aT1 -> aT2 -> T) :=
    forall a1 a2 b1 b2, f a1 b1 = f a2 b2 -> a1 = a2 /\ b1 = b2.

  Lemma in_fimset2 (f : aT1 -> aT2 -> T) a b :
    injective2 f -> (f a b \in fimset2 f A B) = (a \in A) && (b \in B).

  Lemma in_fimset2F (f g : aT1 -> aT2 -> T) a b :
    (forall a b a' b', f a b <> g a' b') -> (f a b \in fimset2 g A B = false).

Cross Product

  Lemma in_fsetX a b : ((a,b) \in A `x` B) = (a \in A) && (b \in B).

  Lemma fsetXP a b : reflect (a \in A /\ b \in B) ((a,b) \in A `x` B).

Subset


  Lemma subP (T1 : choiceType) (X Y : {fset T1}) : reflect {subset X <= Y} (X `<=` Y).

  Lemma subPn X Y : reflect (exists2 x, x \in X & x \notin Y) (~~ (X `<=` Y)).

  Lemma subxx X : X `<=` X.
  Hint Resolve subxx.

  Lemma sub_trans Y X Z : X `<=` Y -> Y `<=` Z -> X `<=` Z.

  Lemma eqEsub X Y : (X == Y) = (X `<=` Y) && (Y `<=` X).

  Lemma sub0x X : fset0 `<=` X.

  Lemma subx0 X : X `<=` fset0 = (X == fset0).

  Lemma fsubUr X Y : X `<=` Y `|` X.

  Lemma fsubUl X Y : X `<=` X `|` Y.

  Lemma fsubIl X Y : (X `&` Y) `<=` X.

  Lemma fsubIr X Y : (X `&` Y) `<=` Y.

  Lemma fsubDl X Y : X `\` Y `<=` X.

  Hint Resolve sub0x fset11 fsubUr fsubUl fsubDl.

  Lemma subsep X (P : pred T) : [fset x in X | P x] `<=` X.

  Lemma sep_sub X X' p q : X `<=` X' -> {in X, subpred p q} ->
    [fset x in X | p x] `<=` [fset x in X' | q x].

  Lemma sep_sep X p q : [fset x in sep X p | q x] = [fset x in X | p x && q x].

  Lemma sepS X Y p : X `<=` Y -> [fset x in X | p x] `<=` [fset x in Y | p x].

  Lemma fsubUset X Y Z : (X `|` Y `<=` Z) = (X `<=` Z) && (Y `<=` Z).

  Lemma fsubUsetP X Y Z: reflect ((X `<=` Z) /\ (Y `<=` Z)) (X `|` Y `<=` Z).

  Lemma fsetUSU X X' Y Y' : X `<=` X' -> Y `<=` Y' -> X `|` Y `<=` X' `|` Y'.

  Lemma fsetSU X Y Z : X `<=` Y -> X `|` Z `<=` Y `|` Z.

  Lemma fsetUS X Y Z : X `<=` Y -> Z `|` X `<=` Z `|` Y.

  Lemma fsub1 x X : ([fset x] `<=` X) = (x \in X).

  Lemma fsetDSS X X' Y Y' : X `<=` X' -> Y' `<=` Y -> X `\` Y `<=` X' `\` Y'.

  Lemma fsetDS X Y Z : X `<=` Y -> Z `\` Y `<=` Z `\` X.

  Definition fsetCK Y X : X `<=` Y -> Y `\` (Y `\` X) = X.

  Lemma fsetUD X Y : Y `<=` X -> Y `|` (X `\` Y) = X.

  Lemma fsetUD1 x X : x \in X -> x |` (X `\` [fset x]) = X.

  Lemma properE X Y : X `<` Y -> exists2 x, (x \in Y) & (x \notin X).

  Lemma properEneq X Y : (X `<` Y) = (X != Y) && (X `<=` Y).

  Lemma properD1 X x : x \in X -> X `\` [fset x] `<` X.

  Lemma fproperU X Y : (X `<` Y `|` X) = ~~ (Y `<=` X).

  Lemma fproper1 x X : (X `<` x |` X) = (x \notin X).

  Lemma fimsetS X Y (f : T -> T') : X `<=` Y -> f `@` X `<=` f `@` Y.

Powerset - Definition suggested by Georges Gonthier

  Definition powerset X : {fset {fset T}} :=
    let e := elements X in
    let mT := ((size e).-tuple bool) in
      set_of (map (fun m : mT => set_of (mask m e)) (enum {: mT})).

  Lemma powersetE X Y : (X \in powerset Y) = (X `<=` Y).

  Lemma powersetP X Y : reflect {subset X <= Y} (X \in powerset Y).

  Lemma powersetU X1 X2 (X3 : {fset T}) :
    (X1 `|` X2 \in powerset X3) = (X1 \in powerset X3) && (X2 \in powerset X3).

  Lemma sub_power X Y Z : X `<=` Y -> Y \in powerset Z -> X \in powerset Z.

  Lemma power_sub X Z Z' : X \in powerset Z -> Z `<=` Z' -> X \in powerset Z'.

  Lemma power_mon X Y : X `<=` Y -> powerset X `<=` powerset Y.

  Lemma fsubsetU X Z Z' : (X `<=` Z) || (X `<=` Z') -> (X `<=` Z `|` Z').

Quantification

  Lemma allU X Y p : all p (X `|` Y) = all p X && all p Y.

  Lemma all_fset1 x p : all p [fset x] = p x.

  Lemma all_fset0 (p : pred T) : all p fset0.

  Lemma has_fset1 x p : has p [fset x] = p x.

  Lemma has_fset0 (p : pred T) : has p fset0 = false.

  Lemma all_subP (U : {fset T}) (P : pred _) :
    reflect (forall X, X `<=` U -> P X) (all P (powerset U)).

End OperationsTheory.
Hint Resolve sub0x fset11 fsubUr fsubUl fsubDl subsep.

Section Fimset3.
  Variables (aT1 aT2 aT3 rT : choiceType) (f : aT1 -> aT2 -> aT3 -> rT).
  Variables (A : {fset aT1}) (B : {fset aT2}) (C : {fset aT3}).

  CoInductive fimset3_spec x : Prop :=
    fImset3_spec a b c : x = f a b c -> a \in A -> b \in B -> c \in C -> fimset3_spec x.

  Lemma fimset3P x :
    reflect (fimset3_spec x) (x \in [fset f a b c | a <- A , b <- B , c <- C]).

  Lemma mem_fimset3 a b c:
    a \in A -> b \in B -> c \in C -> f a b c \in fimset3 f A B C.
End Fimset3.

TODO: if T is a finite type, then {fset T} should also be a finite type. This means there is a universal set and one can form unrestricted comprehensions. Hence, for finite T, {fset T} behaves like {set T}.

Definition fsetT {T : finType} := set_of (enum T).

Lemma in_fsetT (T : finType) (x : T) : x \in fsetT.

Definition fset (T: finType) (q : pred T) := [fset x in fsetT | q x].

Lemma fsetE (T: finType) (q : pred T) x : x \in fset q = q x.

Big Unions

fsetU/fset0 forms a commutative monoid. For any such monoid indexing with a separation is equivalent to indexing on the base set and filtering.

Lemma big_sep (T R : choiceType) (idx : R) (op : Monoid.com_law idx) (F : T -> R) (X : {fset T}) p:
  \big[op/idx]_(i <- [fset x in X | p x]) F i = \big[op/idx]_(i <- X | p i) F i.

Canonical Structure fsetU_law (T : choiceType) :=
  Monoid.Law (@fsetUA T) (@fset0U T) (@fsetU0 T).
Canonical Structure fsetU_comlaw (T : choiceType) :=
  Monoid.ComLaw (@fsetUC T).

Notation "\bigcup_( x 'in' X | P ) F" :=
  (\big[fsetU/fset0]_(x <- elements X | P) F) (at level 41).
Notation "\bigcup_( x 'in' X ) F" :=
  (\bigcup_( x in X | true ) F) (at level 41).

Lemma cupP (T T' : choiceType) (X : {fset T}) (P : pred T) (F : T -> {fset T'}) y :
  reflect (exists x, [&& x \in X , P x & y \in F x]) (y \in \bigcup_(x in X | P x) F x).

Lemma bigU1 (T T' : choiceType) (X : {fset T}) (F : T -> {fset T'}) x :
  x \in X -> F x `<=` \bigcup_(x in X) F x.

Cardinality / Size


Section Size.
  Variable T : choiceType.
  Implicit Types X Y : {fset T}.

  Lemma sizes0 : @size T fset0 = 0.

  Lemma subset_size X Y : X `<=` Y -> size X <= size Y.

  Lemma subsize_eq X Y : X `<=` Y -> size Y <= size X -> X = Y.

  Lemma sizes_eq0 X : (size X == 0) = (X == fset0).

  Lemma size_gt0P X : reflect (exists x, x \in X) (0 < size X).

  Lemma size_sep X (p : pred T) : size [fset x in X | p x] <= size X.

  Lemma properW X Y : X `<` Y -> X `<=` Y.

  Lemma proper_size X Y : X `<` Y -> size X < size Y.

  Lemma size_of_uniq (T0 : choiceType) (s : seq T0) : uniq s -> size (set_of s) = size s.

  Lemma powerset_size X : size (powerset X) = 2 ^ (size X).
End Size.

Weight function for sets


Definition const aT rT (c:rT) (f : aT -> rT) := forall x, f x = c.

Section FSum.
  Variables (T : choiceType) (w : T -> nat).
  Implicit Types X Y : {fset T}.

  Definition fdisj X Y := X `&` Y == fset0.

  Definition fsum X := \sum_(x <- X) w x.

  Lemma fsumID p X : fsum X = fsum [fset x in X | p x ] + fsum [fset x in X | ~~ p x].

  Lemma fsum1 x : fsum [fset x] = w x.

  Lemma fsum0 : fsum fset0 = 0.

  Lemma fsumS X p : fsum [fset x in X | p x] = fsum X - fsum [fset x in X | ~~ p x].

  Lemma fsumI X Y : fsum (X `&` Y) = fsum X - fsum (X `\` Y).

  Lemma fsumD X Y : fsum (X `\` Y) = fsum X - fsum (X `&` Y).

  Lemma fsumU X Y : fsum (X `|` Y) = fsum X + fsum Y - fsum (X `&` Y).

  Lemma fsumDsub X Y : Y `<=` X -> fsum (X `\` Y) = fsum X - fsum Y.

  Lemma fsum_const X n : {in X, const n w} -> fsum X = n * size X.

  Lemma fsum_eq0 X : fsum X = 0 -> {in X, const 0 w}.

  Lemma fsum_sub X Y : X `<=` Y -> fsum X <= fsum Y.

  Lemma fsum_replace X Y Z : fsum Z < fsum Y -> Y `<=` X -> fsum (Z `|` X `\` Y) < fsum X.
End FSum.

cardinality versions of some fsum lemmas

Lemma fsum_const1 (T : choiceType) (X : {fset T}) : fsum (fun _ => 1) X = size X.

Lemma fsizeU (T : choiceType) (X Y : {fset T}) : size (X `|` Y) <= size X + size Y.

Lemma fsizeU1 (T : choiceType) x (X : {fset T}) : size (x |` X) <= (size X).+1.

Lemma fimsetU (aT rT : choiceType) (f : aT -> rT) (A B : {fset aT}) :
 [fset f x | x <- A `|` B] = [fset f x | x <- A] `|` [fset f x | x <- B].

Lemma fimset1 (aT rT : choiceType) (f : aT -> rT) a : [fset f x | x <- [fset a]] = [fset f a].

Lemma fimset0 (aT rT : choiceType) (f : aT -> rT) : [fset f x | x <- fset0 ] = fset0.

Lemma fimsetU1 (aT rT : choiceType) (f : aT -> rT) (B : {fset aT}) a :
 [fset f x | x <- a |` B] = f a |` [fset f x | x <- B].

Section Pick.
  Variables (T:choiceType) (p : pred T) (X : {fset T}).

  Definition fpick :=
    if fset0Vmem [fset x in X | p x] is inr (exist x _) then Some x else None.

  CoInductive fpick_spec : option T -> Type :=
    | fPick x : p x -> x \in X -> fpick_spec (Some x)
    | fNopick : (forall x, x \in X -> ~~ p x) -> fpick_spec None.

  Lemma fpickP : fpick_spec (fpick).
End Pick.


Lemma wf_leq X (f : X -> nat) : well_founded (fun x y => f x < f y).

Lemma nat_size_ind (X:Type) (P : X -> Type) (f : X -> nat) :
   (forall x, (forall y, (f y < f x) -> P y) -> P x) -> forall x, P x.

Lemma slack_ind (T : choiceType) (P : {fset T} -> Type) (U : {fset T}):
  (forall X, (forall Y, Y `<=` U -> X `<` Y -> P Y) -> X `<=` U -> P X)-> forall X, X `<=` U -> P X.

Fixpoints


Lemma iter_fix T (F : T -> T) x k n :
  iter k F x = iter k.+1 F x -> k <= n -> iter n F x = iter n.+1 F x.

Least Fixpoints

Section Fixpoints.
  Variables (T : choiceType) (U : {fset T}) (F : {fset T} -> {fset T}).
  Definition monotone := forall X Y, X `<=` Y -> F X `<=` F Y.
  Definition bounded := forall X, X `<=` U -> F X `<=` U.
  Hypothesis (F_mono : monotone) (F_bound : bounded).

  Definition lfp := iter (size U) F fset0.

  Lemma lfp_ind_aux (P : {fset T} -> Type) : P fset0 -> (forall s , P s -> P (F s)) -> P lfp.

  Lemma lfp_ind (P : T -> Type) :
    (forall x X, (forall y, y \in X -> P y) -> x \in F X -> P x) -> forall x, x \in lfp -> P x.

  Lemma iterFsub1 n : iter n F fset0 `<=` iter n.+1 F fset0.

  Lemma iterFsub n m : n <= m -> iter n F fset0 `<=` iter m F fset0.

  Lemma iterFbound n : iter n F fset0 `<=` U.

  Lemma lfpE : lfp = F lfp.

  Lemma lfp_level_aux x : x \in lfp -> exists n, x \in iter n.+1 F fset0.

Should be level but this is not picked up by coqdoc
  Definition levl (x : T) (lx : x \in lfp) := ex_minn (lfp_level_aux lx).

  Lemma level_max (x : T) (lx : x \in lfp) : levl lx < size U.

  Lemma level1 (x : T) (lx : x \in lfp) : x \in iter (levl lx).+1 F fset0.

  Lemma level2 (x y : T) (lx : x \in lfp) :
    y \in iter (levl lx) F fset0 -> exists ly, @levl y ly < levl lx.

End Fixpoints.

Greatest Fixpoints

Section GreatestFixpoint.
  Variables (T : choiceType) (U : {fset T}) (F : {fset T} -> {fset T}).
  Hypothesis (F_mono : monotone F) (F_bound : bounded U F).


  Let F' A := ~` (F ~` A).

  Let mono_F' : monotone F'.

  Let bounded_F' : bounded U F'.

  Definition gfp := ~` (lfp U F').

  Lemma gfpE : gfp = F gfp.

  Lemma gfp_ind_aux (P : {fset T} -> Type) : P U -> (forall s , P s -> P (F s)) -> P gfp.

  Lemma gfp_ind (P : T -> Type) :
    (forall x X, (forall y, y \in U -> P y -> y \in X) -> P x -> x \in F X) ->
    forall x, x \in U -> P x -> x \in gfp.
End GreatestFixpoint.

Reachability withing a set


Section FsetConnect.
  Variables (T : choiceType) (S : {fset T}) (e : rel T).

  Definition restrict := [rel a b : seq_sub S | e (val a) (val b)].

  Definition connect_in (x y : T) :=
    [exists a, exists b, [&& val a == x, val b == y & connect restrict a b]].

  Lemma connect_in0 (x : T) : x \in S -> connect_in x x.

  Lemma connect_in1 (x y : T) : x \in S -> y \in S -> e x y -> connect_in x y.

  Lemma connect_in_trans (z x y : T) : connect_in x z -> connect_in z y -> connect_in x y.

  Lemma connect_inP x y :
    reflect (exists p : seq T, [/\ all (mem S) (x::p), path e x p & y = last x p])
            (connect_in x y).
End FsetConnect.

Maximal extensions


Section Maximal.
  Variable (T : choiceType) (U : {fset T}) (P : pred {fset T}).

  Definition maximalb (M : {fset T}) := P M && [all Y in powerset U, (M `<` Y) ==> ~~ P Y].
  Definition maximal (M : {fset T}) := P M /\ forall Y, Y `<=` U -> M `<` Y -> ~~ P Y.

  Lemma maximalP M : reflect (maximal M) (maximalb M).

  Lemma ex_max X : X `<=` U -> P X -> exists M, [/\ X `<=` M , M `<=` U & maximal M].
End Maximal.

Pruning


Section Pruning.
  Variables (T:choiceType) (p : T -> {fset T} -> bool).
  Implicit Types (S : {fset T}).

  Require Import Recdef.

  Function prune S {measure size} :=
    if fpick (p^~ S) S is Some x then prune (S `\` [fset x]) else S.

  Lemma prune_ind (P : {fset T} -> Type) S :
    P S ->
    (forall x S0, p x S0 -> x \in S0 -> P S0 -> S0 `<=` S -> P (S0 `\` [fset x])) ->
    P (prune S).

  Lemma prune_sub S : prune S `<=` S.

  Lemma pruneE x S : x \in prune S -> ~~ p x (prune S).
End Pruning.

Legacy/compatibility

Definition feqEsub := eqEsub.

Lemma set_of_nilp (T : choiceType) (s : seq T) : (set_of s == fset0) = (nilp s).


Rudimentary Automation


Section AutoLemmas.
  Variables (T T':choiceType).
  Implicit Types (X Y Z : {fset T}).

  Lemma fsubU_auto X Y Z : (X `<=` Z) -> (Y `<=` Z) -> (X `|` Y `<=` Z).

  Lemma fsub1_auto x X : x \in X -> ([fset x] `<=` X).

  Lemma fsetU_auto1 x X Y : x \in X -> x \in X `|` Y.

  Lemma fsetU_auto2 x X Y : x \in Y -> x \in X `|` Y.

  Lemma fsetU_auto3 X Y Z : X `<=` Y -> X `<=` Y `|` Z.

  Lemma fsetU_auto4 X Y Z : X `<=` Y -> X `<=` Z `|` Y.
End AutoLemmas.

Hint Resolve subxx fsetUSU fsubUl fsubUr fsubU_auto fsub1_auto
     fsetU_auto1 fsetU_auto2 fsetU_auto3 fsetU_auto4 fset11 fset1U1 : fset.

Hint Extern 4 (is_true _) => (match goal with [ H : is_true (_ `|` _ `<=` _) |- _ ] => case/fsubUsetP : H end) : fset .
Hint Extern 4 (is_true _) => (match goal with [ H : is_true ((_ \in _) && (_ \in _))|- _ ] => case/andP : H end) : fset .
Hint Extern 4 (is_true _) =>
  match goal with
    | [ H : is_true ((_ \in _) && (_ \in _)) |- _] => case/andP : H
  end : fset.