Module docstring
{"# The antidiagonal on a multiset.
The antidiagonal of a multiset s consists of all pairs (t₁, t₂)
such that t₁ + t₂ = s. These pairs are counted with multiplicities.
"}
{"# The antidiagonal on a multiset.
The antidiagonal of a multiset s consists of all pairs (t₁, t₂)
such that t₁ + t₂ = s. These pairs are counted with multiplicities.
"}
Multiset.antidiagonal
      definition
     (s : Multiset α) : Multiset (Multiset α × Multiset α)
        /-- The antidiagonal of a multiset `s` consists of all pairs `(t₁, t₂)`
    such that `t₁ + t₂ = s`. These pairs are counted with multiplicities. -/
def antidiagonal (s : Multiset α) : Multiset (MultisetMultiset α × Multiset α) :=
  Quot.liftOn s (fun l ↦ (revzip (powersetAux l) : Multiset (MultisetMultiset α × Multiset α)))
    fun _ _ h ↦ Quot.sound (revzip_powersetAux_perm h)
        Multiset.antidiagonal_coe
      theorem
     (l : List α) : @antidiagonal α l = revzip (powersetAux l)
        theorem antidiagonal_coe (l : List α) : @antidiagonal α l = revzip (powersetAux l) :=
  rfl
        Multiset.antidiagonal_coe'
      theorem
     (l : List α) : @antidiagonal α l = revzip (powersetAux' l)
        @[simp]
theorem antidiagonal_coe' (l : List α) : @antidiagonal α l = revzip (powersetAux' l) :=
  Quot.sound revzip_powersetAux_perm_aux'
        Multiset.mem_antidiagonal
      theorem
     {s : Multiset α} {x : Multiset α × Multiset α} : x ∈ antidiagonal s ↔ x.1 + x.2 = s
        /-- A pair `(t₁, t₂)` of multisets is contained in `antidiagonal s`
    if and only if `t₁ + t₂ = s`. -/
@[simp]
theorem mem_antidiagonal {s : Multiset α} {x : MultisetMultiset α × Multiset α} :
    x ∈ antidiagonal sx ∈ antidiagonal s ↔ x.1 + x.2 = s :=
  Quotient.inductionOn s fun l ↦ by
    dsimp only [quot_mk_to_coe, antidiagonal_coe]
    refine ⟨fun h => revzip_powersetAux h, fun h ↦ ?_⟩
    have _ := Classical.decEq α
    simp only [revzip_powersetAux_lemma l revzip_powersetAux, h.symm, mem_coe,
      List.mem_map, mem_powersetAux]
    obtain ⟨x₁, x₂⟩ := x
    exact ⟨x₁, le_add_right _ _, by rw [add_tsub_cancel_left x₁ x₂]⟩
        Multiset.antidiagonal_map_fst
      theorem
     (s : Multiset α) : (antidiagonal s).map Prod.fst = powerset s
        @[simp]
theorem antidiagonal_map_fst (s : Multiset α) : (antidiagonal s).map Prod.fst = powerset s :=
  Quotient.inductionOn s fun l ↦ by simp [powersetAux']
        Multiset.antidiagonal_map_snd
      theorem
     (s : Multiset α) : (antidiagonal s).map Prod.snd = powerset s
        @[simp]
theorem antidiagonal_map_snd (s : Multiset α) : (antidiagonal s).map Prod.snd = powerset s :=
  Quotient.inductionOn s fun l ↦ by simp [powersetAux']
        Multiset.antidiagonal_zero
      theorem
     : @antidiagonal α 0 = {(0, 0)}
        @[simp]
theorem antidiagonal_zero : @antidiagonal α 0 = {(0, 0)} :=
  rfl
        Multiset.antidiagonal_cons
      theorem
     (a : α) (s) :
  antidiagonal (a ::ₘ s) = map (Prod.map id (cons a)) (antidiagonal s) + map (Prod.map (cons a) id) (antidiagonal s)
        @[simp]
theorem antidiagonal_cons (a : α) (s) :
    antidiagonal (a ::ₘ s) =
      map (Prod.map id (cons a)) (antidiagonal s) + map (Prod.map (cons a) id) (antidiagonal s) :=
  Quotient.inductionOn s fun l ↦ by
    simp only [revzip, reverse_append, quot_mk_to_coe, coe_eq_coe, powersetAux'_cons, cons_coe,
      map_coe, antidiagonal_coe', coe_add]
    rw [← zip_map, ← zip_map, zip_append, (_ : _ ++ _ = _)]
    · congr
      · simp only [List.map_id]
      · rw [map_reverse]
      · simp
    · simp
        Multiset.antidiagonal_eq_map_powerset
      theorem
     [DecidableEq α] (s : Multiset α) : s.antidiagonal = s.powerset.map fun t ↦ (s - t, t)
        theorem antidiagonal_eq_map_powerset [DecidableEq α] (s : Multiset α) :
    s.antidiagonal = s.powerset.map fun t ↦ (s - t, t) := by
  induction' s using Multiset.induction_on with a s hs
  · simp only [antidiagonal_zero, powerset_zero, Multiset.zero_sub, map_singleton]
  · simp_rw [antidiagonal_cons, powerset_cons, map_add, hs, map_map, Function.comp, Prod.map_apply,
      id, sub_cons, erase_cons_head]
    rw [add_comm]
    congr 1
    refine Multiset.map_congr rfl fun x hx ↦ ?_
    rw [cons_sub_of_le _ (mem_powerset.mp hx)]
        Multiset.card_antidiagonal
      theorem
     (s : Multiset α) : card (antidiagonal s) = 2 ^ card s
        @[simp]
theorem card_antidiagonal (s : Multiset α) : card (antidiagonal s) = 2 ^ card s := by
  have := card_powerset s
  rwa [← antidiagonal_map_fst, card_map] at this