QRC1.Preamble

From mathcomp Require Import all_ssreflect finmap.

Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.

Section bigop.

Variables (T : eqType) (F : T -> nat) (w : seq T).

Lemma leq_bigmax_list (j : T) : j \in w -> F j <= \max_(i <- w) F i.
Proof. by move=> /seq_tnthP [n ->]; rewrite big_tnth leq_bigmax. Qed.

Lemma bigmax_leqP_list (m : nat) :
  reflect {in w, forall i, F i <= m} (\max_(i <- w) F i <= m).
Proof.
  rewrite big_tnth; apply: (iffP idP).
    by move=> /bigmax_leqP => /= H x /seq_tnthP [i ->]; apply: H.
  move=> H; apply/bigmax_leqP => /= i _.
  by have /H := mem_tnth i (in_tuple w).
Qed.

End bigop.

Section finmap.

Open Scope fset.

Variables (T K V : choiceType) (f : K -> V).

Lemma fset_seq1 (A : T) :
  [fset A] = [:: A] :> seq T.
Proof.
  apply: perm_small_eq => //.
  apply: uniq_perm => //.
  by move=> B; rewrite 2!inE.
Qed.

Lemma fsetmap1 (k : K) : [fset f k' | k' in [fset k]] = [fset f k].
Proof.
  apply/fsetP => k'; apply/imfsetP/fset1P => /=.
    by move=> [k'' /fset1P ->].
  by move=> ->; exists k; rewrite ?in_fsetE.
Qed.

Lemma fsetmapU (K1 K2 : {fset K}) :
  [fset f k | k in K1 `|` K2] = [fset f k | k in K1] `|` [fset f k | k in K2].
Proof.
  apply/fsetP => v; apply/imfsetP/fsetUP => /=.
    move=> [k /fsetUP [kinK1 -> | kinK2 ->]].
      by left; apply/imfsetP; exists k.
    by right; apply/imfsetP; exists k.
  move=> [|] /imfsetP /= [k].
    by move=> kinK1 ->; exists k => //; rewrite inE kinK1.
  by move=> kinK2 ->; exists k => //; rewrite inE kinK2 orbT.
Qed.

Lemma fsetmap2 (k1 k2 : K) :
  [fset f k' | k' in [fset k1; k2]] = [fset f k1; f k2].
Proof. by rewrite fsetmapU 2!fsetmap1. Qed.

Lemma fsetmap_bigfcup (F : T -> {fset K}) (ts : {fset T}) :
  [fset f k | k in \bigcup_(t <- ts) F t] =
    \bigcup_(t <- ts) [fset f k | k in F t].
Proof.
  apply/fsetP => v.
  apply/imfsetP/bigfcupP => /=.
    move=> [k /bigfcupP [t tintsT kinFt] ->].
    exists t => //.
    by apply/imfsetP => /=; exists k.
  move=> [t tintsT /imfsetP /= [k kinFt ->]].
  exists k => //=.
  by apply/bigfcupP; exists t.
Qed.

End finmap.

Open Scope fset.

Lemma all_fsetU {T : choiceType} a (A B : {fset T}) :
  all a (A `|` B) = (all a A) && (all a B).
Proof.
  apply/allP/andP.
    move=> allAUB; split; apply/allP.
      by move=> x xinA; apply: allAUB; rewrite inE xinA.
    by move=> x xinB; apply: allAUB; rewrite inE xinB orbT.
  move=> [/allP allA /allP allB] x /fsetUP [xinA | xinB].
    by apply: allA.
  by apply: allB.
Qed.

Close Scope fset.

Section BigComFSet.

Variable (R : Type) (idx : R) (op : Monoid.com_law idx).
Variable (I J : choiceType).

Local Open Scope fset.

Lemma big_fsetU (A B : {fset I}) (F : I -> R) : idempotent op ->
   \big[op/idx]_(i <- (A `|` B)) F i
     = op (\big[op/idx]_(i <- A) F i) (\big[op/idx]_(i <- B) F i).
Proof.
  move=> idop.
  rewrite eq_big_imfset //= big_map.
  rewrite big_undup //.
  by rewrite big_cat.
Qed.

End BigComFSet.