Library zoo.common.gmultiset

Require Export stdpp.gmultiset.

Require Import zoo.prelude.
Require Import zoo.common.list.
Require Import zoo.options.

Section basic.
  Context `{Countable A}.

  Implicit Type x y : A.
  Implicit Type X Y : gmultiset A.

  Lemma gmultisetemptyelem_of X :
    X =
       x,
      x X.

  Lemma gmultisetdisj_unionempty X1 X2 :
    X1 X2 =
      X1 =
      X2 = .
  Lemma gmultisetdisj_unionemptyinv X1 X2 :
    X1 X2 =
      X1 =
      X2 = .

  Lemma elem_ofgmultisetdisj_unionl x X1 X2 :
    x X1
    x X1 X2.
  Lemma elem_ofgmultisetdisj_unionr x X1 X2 :
    x X2
    x X1 X2.
End basic.

Section size.
  Context `{Countable A}.

  Implicit Type x y : A.
  Implicit Type X Y : gmultiset A.

  Lemma gmultisetsizesingletoninv X x y :
    size X = 1
    x X
    y X
    x = y.
  Lemma gmultisetsizeー1ーelem_of X :
    size X = 1
       x,
      X = {[+x+]}.

  Lemma gmultisetelem_ofsizenon_empty x X :
    x X
    size X 0.
End size.

Section map.
  Context `{Countable A}.
  Context `{Countable B}.
  Context (f : A B).

  Implicit Type x y : A.
  Implicit Type X Y : gmultiset A.
  Implicit Type 𝑋 𝑌 : gmultiset B.

  Lemma gmultisetsizemap X :
    size (gmultiset_map f X) = size X.

  Lemma gmultiset_mapemptyinv X :
    gmultiset_map f X =
    X = .

  Lemma gmultiset_mapsingletoninv X 𝑥 :
    gmultiset_map f X = {[+𝑥+]}
       x,
      X = {[+x+]}
      𝑥 = f x.

  Lemma gmultiset_mapdisj_unioninv X 𝑋1 𝑋2 :
    gmultiset_map f X = 𝑋1 𝑋2
       X1 X2,
      X = X1 X2
      𝑋1 = gmultiset_map f X1
      𝑋2 = gmultiset_map f X2.
  Lemma gmultiset_mapdisj_unionsingletonlinv X 𝑥 𝑋 :
    gmultiset_map f X = {[+𝑥+]} 𝑋
       x X',
      X = {[+x+]} X'
      𝑥 = f x
      𝑋 = gmultiset_map f X'.
  Lemma gmultiset_mapdisj_unionsingletonrinv X 𝑥 𝑋 :
    gmultiset_map f X = 𝑋 {[+𝑥+]}
       X' x,
      X = X' {[+x+]}
      𝑋 = gmultiset_map f X'
      𝑥 = f x.
End map.

Section list_to_set_disj.
  Context `{Countable A}.

  Implicit Type x y : A.
  Implicit Type l : list A.

  Lemma list_to_set_disjempty l :
    list_to_set_disj l =@{gmultiset _}
    l = [].

  Lemma list_to_set_disjsnoc l x :
    list_to_set_disj (l ++ [x]) =@{gmultiset _} {[+x+]} list_to_set_disj l.
End list_to_set_disj.

Section disj_union_list.
  Context `{Countable A}.

  Implicit Type x y : A.
  Implicit Type X Y : gmultiset A.
  Implicit Type Xs Ys : list $ gmultiset A.

  Lemma gmultisetdisj_union_listempty Xs :
    ⋃+ Xs =
       X,
      X Xs
      X = .
  Lemma gmultisetdisj_union_listreplicateempty n :
    ⋃+ replicate n =@{gmultiset A} .

  Lemma gmultisetdisj_union_listdelete Xs i X :
    Xs !! i = Some X
    ⋃+ (delete i Xs) = ⋃+ Xs X.
  Lemma gmultisetdisj_union_listdelete' Xs i X :
    Xs !! i = Some X
    ⋃+ Xs = X ⋃+ (delete i Xs).

  Lemma gmultisetdisj_union_listinsert Xs i X :
    is_Some (Xs !! i)
    ⋃+ <[i := X]> Xs = X ⋃+ (delete i Xs).
  Lemma gmultisetdisj_union_listinsertid Xs i X :
    Xs !! i = Some X
    ⋃+ <[i := X]> Xs = ⋃+ Xs.
  Lemma gmultisetdisj_union_listinsertdisj_unionl Xs i X1 X2 :
    Xs !! i = Some X2
    ⋃+ <[i := X1 X2]> Xs = X1 ⋃+ Xs.
  Lemma gmultisetdisj_union_listinsertdisj_unionr Xs i X1 X2 :
    Xs !! i = Some X1
    ⋃+ <[i := X1 X2]> Xs = X2 ⋃+ Xs.
End disj_union_list.