File: Mathlib/Analysis/Analytic/Composition.lean

full_name: FormalMultilinearSeries.applyComposition
code: /-- Given a formal multilinear series `p`, a composition `c` of `n` and the index `i` of a
block of `c`, we may define a function on `fin n → E` by picking the variables in the `i`-th block
of `n`, and applying the corresponding coefficient of `p` to these variables. This function is
called `p.apply_composition c v i` for `v : fin n → E` and `i : fin c.length`. -/
def applyComposition (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (c : Composition n) :
    (Fin n → E) → Fin c.length → F 
goal: (Fin n → E) → Fin c.length → F

full_name: FormalMultilinearSeries.applyComposition_ones
code: theorem applyComposition_ones (p : FormalMultilinearSeries 𝕜 E F) (n : ℕ) :
    p.applyComposition (Composition.ones n) = fun v i =>
      p 1 fun _ => v (Fin.castLE (Composition.length_le _) i) 
goal: p.applyComposition (Composition.ones n) = fun v i => (p 1) fun x => v (Fin.castLE ⋯ i)

full_name: FormalMultilinearSeries.applyComposition_single
code: theorem applyComposition_single (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (hn : 0 < n)
    (v : Fin n → E) : p.applyComposition (Composition.single n hn) v = fun _j => p n v 
goal: p.applyComposition (Composition.single n hn) v = fun _j => (p n) v

full_name: FormalMultilinearSeries.removeZero_applyComposition
code: @[simp]
theorem removeZero_applyComposition (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ}
    (c : Composition n) : p.removeZero.applyComposition c = p.applyComposition c 
goal: p.removeZero.applyComposition c = p.applyComposition c

full_name: FormalMultilinearSeries.applyComposition_update
code: /-- Technical lemma stating how `p.apply_composition` commutes with updating variables. This
will be the key point to show that functions constructed from `apply_composition` retain
multilinearity. -/
theorem applyComposition_update (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (c : Composition n)
    (j : Fin n) (v : Fin n → E) (z : E) :
    p.applyComposition c (Function.update v j z) =
      Function.update (p.applyComposition c v) (c.index j)
        (p (c.blocksFun (c.index j))
          (Function.update (v ∘ c.embedding (c.index j)) (c.invEmbedding j) z)) 
goal: p.applyComposition c (Function.update v j z) =
  Function.update (p.applyComposition c v) (c.index j)
    ((p (c.blocksFun (c.index j))) (Function.update (v ∘ ⇑(c.embedding (c.index j))) (c.invEmbedding j) z))

full_name: FormalMultilinearSeries.compContinuousLinearMap_applyComposition
code: @[simp]
theorem compContinuousLinearMap_applyComposition {n : ℕ} (p : FormalMultilinearSeries 𝕜 F G)
    (f : E →L[𝕜] F) (c : Composition n) (v : Fin n → E) :
    (p.compContinuousLinearMap f).applyComposition c v = p.applyComposition c (f ∘ v) 
goal: (p.compContinuousLinearMap f).applyComposition c v = p.applyComposition c (⇑f ∘ v)

full_name: ContinuousMultilinearMap.compAlongComposition
code: /-- Given a formal multilinear series `p`, a composition `c` of `n` and a continuous multilinear
map `f` in `c.length` variables, one may form a continuous multilinear map in `n` variables by
applying the right coefficient of `p` to each block of the composition, and then applying `f` to
the resulting vector. It is called `f.comp_along_composition p c`. -/
def compAlongComposition {n : ℕ} (p : FormalMultilinearSeries 𝕜 E F) (c : Composition n)
    (f : ContinuousMultilinearMap 𝕜 (fun _i : Fin c.length => F) G) :
    ContinuousMultilinearMap 𝕜 (fun _i : Fin n => E) G 
goal: ContinuousMultilinearMap 𝕜 (fun _i => E) G

full_name: ContinuousMultilinearMap.compAlongComposition_apply
code: @[simp]
theorem compAlongComposition_apply {n : ℕ} (p : FormalMultilinearSeries 𝕜 E F) (c : Composition n)
    (f : ContinuousMultilinearMap 𝕜 (fun _i : Fin c.length => F) G) (v : Fin n → E) :
    (f.compAlongComposition p c) v = f (p.applyComposition c v) 
goal: (ContinuousMultilinearMap.compAlongComposition p c f) v = f (p.applyComposition c v)

full_name: FormalMultilinearSeries.compAlongComposition
code: /-- Given two formal multilinear series `q` and `p` and a composition `c` of `n`, one may
form a continuous multilinear map in `n` variables by applying the right coefficient of `p` to each
block of the composition, and then applying `q c.length` to the resulting vector. It is
called `q.comp_along_composition p c`. -/
def compAlongComposition {n : ℕ} (q : FormalMultilinearSeries 𝕜 F G)
    (p : FormalMultilinearSeries 𝕜 E F) (c : Composition n) :
    ContinuousMultilinearMap 𝕜 (fun _i : Fin n => E) G 
goal: ContinuousMultilinearMap 𝕜 (fun _i => E) G

full_name: FormalMultilinearSeries.compAlongComposition_apply
code: @[simp]
theorem compAlongComposition_apply {n : ℕ} (q : FormalMultilinearSeries 𝕜 F G)
    (p : FormalMultilinearSeries 𝕜 E F) (c : Composition n) (v : Fin n → E) :
    (q.compAlongComposition p c) v = q c.length (p.applyComposition c v) 
goal: (q.compAlongComposition p c) v = (q c.length) (p.applyComposition c v)

full_name: FormalMultilinearSeries.comp
code: /-- Formal composition of two formal multilinear series. The `n`-th coefficient in the composition
is defined to be the sum of `q.comp_along_composition p c` over all compositions of
`n`. In other words, this term (as a multilinear function applied to `v_0, ..., v_{n-1}`) is
`∑'_{k} ∑'_{i₁ + ... + iₖ = n} qₖ (p_{i_1} (...), ..., p_{i_k} (...))`, where one puts all variables
`v_0, ..., v_{n-1}` in increasing order in the dots.

In general, the composition `q ∘ p` only makes sense when the constant coefficient of `p` vanishes.
We give a general formula but which ignores the value of `p 0` instead.
-/
protected def comp (q : FormalMultilinearSeries 𝕜 F G) (p : FormalMultilinearSeries 𝕜 E F) :
    FormalMultilinearSeries 𝕜 E G 
goal: FormalMultilinearSeries 𝕜 E G

full_name: FormalMultilinearSeries.comp_coeff_zero
code: /-- The `0`-th coefficient of `q.comp p` is `q 0`. Since these maps are multilinear maps in zero
variables, but on different spaces, we can not state this directly, so we state it when applied to
arbitrary vectors (which have to be the zero vector). -/
theorem comp_coeff_zero (q : FormalMultilinearSeries 𝕜 F G) (p : FormalMultilinearSeries 𝕜 E F)
    (v : Fin 0 → E) (v' : Fin 0 → F) : (q.comp p) 0 v = q 0 v' 
goal: (q.comp p 0) v = (q 0) v'

full_name: FormalMultilinearSeries.comp_coeff_zero'
code: @[simp]
theorem comp_coeff_zero' (q : FormalMultilinearSeries 𝕜 F G) (p : FormalMultilinearSeries 𝕜 E F)
    (v : Fin 0 → E) : (q.comp p) 0 v = q 0 fun _i => 0 
goal: (q.comp p 0) v = (q 0) fun _i => 0

full_name: FormalMultilinearSeries.comp_coeff_zero''
code: /-- The `0`-th coefficient of `q.comp p` is `q 0`. When `p` goes from `E` to `E`, this can be
expressed as a direct equality -/
theorem comp_coeff_zero'' (q : FormalMultilinearSeries 𝕜 E F) (p : FormalMultilinearSeries 𝕜 E E) :
    (q.comp p) 0 = q 0 
goal: q.comp p 0 = q 0

full_name: FormalMultilinearSeries.comp_coeff_one
code: /-- The first coefficient of a composition of formal multilinear series is the composition of the
first coefficients seen as continuous linear maps. -/
theorem comp_coeff_one (q : FormalMultilinearSeries 𝕜 F G) (p : FormalMultilinearSeries 𝕜 E F)
    (v : Fin 1 → E) : (q.comp p) 1 v = q 1 fun _i => p 1 v 
goal: (q.comp p 1) v = (q 1) fun _i => (p 1) v

full_name: FormalMultilinearSeries.removeZero_comp_of_pos
code: /-- Only `0`-th coefficient of `q.comp p` depends on `q 0`. -/
theorem removeZero_comp_of_pos (q : FormalMultilinearSeries 𝕜 F G)
    (p : FormalMultilinearSeries 𝕜 E F) {n : ℕ} (hn : 0 < n) :
    q.removeZero.comp p n = q.comp p n 
goal: q.removeZero.comp p n = q.comp p n

full_name: FormalMultilinearSeries.comp_removeZero
code: @[simp]
theorem comp_removeZero (q : FormalMultilinearSeries 𝕜 F G) (p : FormalMultilinearSeries 𝕜 E F) :
    q.comp p.removeZero = q.comp p 
goal: q.comp p.removeZero = q.comp p

full_name: FormalMultilinearSeries.compAlongComposition_bound
code: /-- The norm of `f.comp_along_composition p c` is controlled by the product of
the norms of the relevant bits of `f` and `p`. -/
theorem compAlongComposition_bound {n : ℕ} (p : FormalMultilinearSeries 𝕜 E F) (c : Composition n)
    (f : ContinuousMultilinearMap 𝕜 (fun _i : Fin c.length => F) G) (v : Fin n → E) :
    ‖f.compAlongComposition p c v‖ ≤ (‖f‖ * ∏ i, ‖p (c.blocksFun i)‖) * ∏ i : Fin n, ‖v i‖ 
goal: ‖(ContinuousMultilinearMap.compAlongComposition p c f) v‖ ≤
  (‖f‖ * ∏ i : Fin c.length, ‖p (c.blocksFun i)‖) * ∏ i : Fin n, ‖v i‖

full_name: FormalMultilinearSeries.compAlongComposition_norm
code: /-- The norm of `q.comp_along_composition p c` is controlled by the product of
the norms of the relevant bits of `q` and `p`. -/
theorem compAlongComposition_norm {n : ℕ} (q : FormalMultilinearSeries 𝕜 F G)
    (p : FormalMultilinearSeries 𝕜 E F) (c : Composition n) :
    ‖q.compAlongComposition p c‖ ≤ ‖q c.length‖ * ∏ i, ‖p (c.blocksFun i)‖ 
goal: ‖q.compAlongComposition p c‖ ≤ ‖q c.length‖ * ∏ i : Fin c.length, ‖p (c.blocksFun i)‖

full_name: FormalMultilinearSeries.compAlongComposition_nnnorm
code: theorem compAlongComposition_nnnorm {n : ℕ} (q : FormalMultilinearSeries 𝕜 F G)
    (p : FormalMultilinearSeries 𝕜 E F) (c : Composition n) :
    ‖q.compAlongComposition p c‖₊ ≤ ‖q c.length‖₊ * ∏ i, ‖p (c.blocksFun i)‖₊ 
goal: ‖q.compAlongComposition p c‖₊ ≤ ‖q c.length‖₊ * ∏ i : Fin c.length, ‖p (c.blocksFun i)‖₊

full_name: FormalMultilinearSeries.id
code: /-- The identity formal multilinear series, with all coefficients equal to `0` except for `n = 1`
where it is (the continuous multilinear version of) the identity. -/
def id : FormalMultilinearSeries 𝕜 E E
  
goal: FormalMultilinearSeries 𝕜 E E

full_name: FormalMultilinearSeries.id_apply_one
code: /-- The first coefficient of `id 𝕜 E` is the identity. -/
@[simp]
theorem id_apply_one (v : Fin 1 → E) : (FormalMultilinearSeries.id 𝕜 E) 1 v = v 0 
goal: (FormalMultilinearSeries.id 𝕜 E 1) v = v 0

full_name: FormalMultilinearSeries.id_apply_one'
code: /-- The `n`th coefficient of `id 𝕜 E` is the identity when `n = 1`. We state this in a dependent
way, as it will often appear in this form. -/
theorem id_apply_one' {n : ℕ} (h : n = 1) (v : Fin n → E) :
    (id 𝕜 E) n v = v ⟨0, h.symm ▸ zero_lt_one⟩ 
goal: (FormalMultilinearSeries.id 𝕜 E n) v = v ⟨0, ⋯⟩

full_name: FormalMultilinearSeries.id_apply_ne_one
code: /-- For `n ≠ 1`, the `n`-th coefficient of `id 𝕜 E` is zero, by definition. -/
@[simp]
theorem id_apply_ne_one {n : ℕ} (h : n ≠ 1) : (FormalMultilinearSeries.id 𝕜 E) n = 0 
goal: FormalMultilinearSeries.id 𝕜 E n = 0

full_name: FormalMultilinearSeries.comp_id
code: @[simp]
theorem comp_id (p : FormalMultilinearSeries 𝕜 E F) : p.comp (id 𝕜 E) = p 
goal: p.comp (FormalMultilinearSeries.id 𝕜 E) = p

full_name: FormalMultilinearSeries.id_comp
code: @[simp]
theorem id_comp (p : FormalMultilinearSeries 𝕜 E F) (h : p 0 = 0) : (id 𝕜 F).comp p = p 
goal: (FormalMultilinearSeries.id 𝕜 F).comp p = p

full_name: FormalMultilinearSeries.comp_summable_nnreal
code: /-- If two formal multilinear series have positive radius of convergence, then the terms appearing
in the definition of their composition are also summable (when multiplied by a suitable positive
geometric term). -/
theorem comp_summable_nnreal (q : FormalMultilinearSeries 𝕜 F G) (p : FormalMultilinearSeries 𝕜 E F)
    (hq : 0 < q.radius) (hp : 0 < p.radius) :
    ∃ r > (0 : ℝ≥0),
      Summable fun i : Σ n, Composition n => ‖q.compAlongComposition p i.2‖₊ * r ^ i.1 
goal: ∃ r > 0, Summable fun i => ‖q.compAlongComposition p i.snd‖₊ * r ^ i.fst

full_name: FormalMultilinearSeries.le_comp_radius_of_summable
code: /-- Bounding below the radius of the composition of two formal multilinear series assuming
summability over all compositions. -/
theorem le_comp_radius_of_summable (q : FormalMultilinearSeries 𝕜 F G)
    (p : FormalMultilinearSeries 𝕜 E F) (r : ℝ≥0)
    (hr : Summable fun i : Σ n, Composition n => ‖q.compAlongComposition p i.2‖₊ * r ^ i.1) :
    (r : ℝ≥0∞) ≤ (q.comp p).radius 
goal: ↑r ≤ (q.comp p).radius

full_name: FormalMultilinearSeries.compPartialSumSource
code: /-- Source set in the change of variables to compute the composition of partial sums of formal
power series.
See also `comp_partial_sum`. -/
def compPartialSumSource (m M N : ℕ) : Finset (Σ n, Fin n → ℕ) 
goal: Finset ((n : ℕ) × (Fin n → ℕ))

full_name: FormalMultilinearSeries.mem_compPartialSumSource_iff
code: @[simp]
theorem mem_compPartialSumSource_iff (m M N : ℕ) (i : Σ n, Fin n → ℕ) :
    i ∈ compPartialSumSource m M N ↔
      (m ≤ i.1 ∧ i.1 < M) ∧ ∀ a : Fin i.1, 1 ≤ i.2 a ∧ i.2 a < N 
goal: i ∈ FormalMultilinearSeries.compPartialSumSource m M N ↔
  (m ≤ i.fst ∧ i.fst < M) ∧ ∀ (a : Fin i.fst), 1 ≤ i.snd a ∧ i.snd a < N

full_name: FormalMultilinearSeries.compChangeOfVariables
code: /-- Change of variables appearing to compute the composition of partial sums of formal
power series -/
def compChangeOfVariables (m M N : ℕ) (i : Σ n, Fin n → ℕ) (hi : i ∈ compPartialSumSource m M N) :
    Σ n, Composition n 
goal: (n : ℕ) × Composition n

full_name: FormalMultilinearSeries.compChangeOfVariables_length
code: @[simp]
theorem compChangeOfVariables_length (m M N : ℕ) {i : Σ n, Fin n → ℕ}
    (hi : i ∈ compPartialSumSource m M N) :
    Composition.length (compChangeOfVariables m M N i hi).2 = i.1 
goal: (FormalMultilinearSeries.compChangeOfVariables m M N i hi).snd.length = i.fst

full_name: FormalMultilinearSeries.compChangeOfVariables_blocksFun
code: theorem compChangeOfVariables_blocksFun (m M N : ℕ) {i : Σ n, Fin n → ℕ}
    (hi : i ∈ compPartialSumSource m M N) (j : Fin i.1) :
    (compChangeOfVariables m M N i hi).2.blocksFun
        ⟨j, (compChangeOfVariables_length m M N hi).symm ▸ j.2⟩ =
      i.2 j 
goal: (FormalMultilinearSeries.compChangeOfVariables m M N i hi).snd.blocksFun ⟨↑j, ⋯⟩ = i.snd j

full_name: FormalMultilinearSeries.compPartialSumTargetSet
code: /-- Target set in the change of variables to compute the composition of partial sums of formal
power series, here given a a set. -/
def compPartialSumTargetSet (m M N : ℕ) : Set (Σ n, Composition n) 
goal: Set ((n : ℕ) × Composition n)

full_name: FormalMultilinearSeries.compPartialSumTargetSet_image_compPartialSumSource
code: theorem compPartialSumTargetSet_image_compPartialSumSource (m M N : ℕ)
    (i : Σ n, Composition n) (hi : i ∈ compPartialSumTargetSet m M N) :
    ∃ (j : _) (hj : j ∈ compPartialSumSource m M N), compChangeOfVariables m M N j hj = i 
goal: ∃ j,
  ∃ (hj : j ∈ FormalMultilinearSeries.compPartialSumSource m M N),
    FormalMultilinearSeries.compChangeOfVariables m M N j hj = i

full_name: FormalMultilinearSeries.compPartialSumTarget
code: /-- Target set in the change of variables to compute the composition of partial sums of formal
power series, here given a a finset.
See also `comp_partial_sum`. -/
def compPartialSumTarget (m M N : ℕ) : Finset (Σ n, Composition n) 
goal: Finset ((n : ℕ) × Composition n)

full_name: FormalMultilinearSeries.mem_compPartialSumTarget_iff
code: @[simp]
theorem mem_compPartialSumTarget_iff {m M N : ℕ} {a : Σ n, Composition n} :
    a ∈ compPartialSumTarget m M N ↔
      m ≤ a.2.length ∧ a.2.length < M ∧ ∀ j : Fin a.2.length, a.2.blocksFun j < N 
goal: a ∈ FormalMultilinearSeries.compPartialSumTarget m M N ↔
  m ≤ a.snd.length ∧ a.snd.length < M ∧ ∀ (j : Fin a.snd.length), a.snd.blocksFun j < N

full_name: FormalMultilinearSeries.compChangeOfVariables_sum
code: /-- `comp_change_of_variables m M N` is a bijection between `comp_partial_sum_source m M N`
and `comp_partial_sum_target m M N`, yielding equal sums for functions that correspond to each
other under the bijection. As `comp_change_of_variables m M N` is a dependent function, stating
that it is a bijection is not directly possible, but the consequence on sums can be stated
more easily. -/
theorem compChangeOfVariables_sum {α : Type*} [AddCommMonoid α] (m M N : ℕ)
    (f : (Σ n : ℕ, Fin n → ℕ) → α) (g : (Σ n, Composition n) → α)
    (h : ∀ (e) (he : e ∈ compPartialSumSource m M N), f e = g (compChangeOfVariables m M N e he)) :
    ∑ e ∈ compPartialSumSource m M N, f e = ∑ e ∈ compPartialSumTarget m M N, g e 
goal: ∑ e ∈ FormalMultilinearSeries.compPartialSumSource m M N, f e =
  ∑ e ∈ FormalMultilinearSeries.compPartialSumTarget m M N, g e

full_name: FormalMultilinearSeries.compPartialSumTarget_tendsto_atTop
code: /-- The auxiliary set corresponding to the composition of partial sums asymptotically contains
all possible compositions. -/
theorem compPartialSumTarget_tendsto_atTop :
    Tendsto (fun N => compPartialSumTarget 0 N N) atTop atTop 
goal: Filter.Tendsto (fun N => FormalMultilinearSeries.compPartialSumTarget 0 N N) Filter.atTop Filter.atTop

full_name: FormalMultilinearSeries.comp_partialSum
code: /-- Composing the partial sums of two multilinear series coincides with the sum over all
compositions in `comp_partial_sum_target 0 N N`. This is precisely the motivation for the
definition of `comp_partial_sum_target`. -/
theorem comp_partialSum (q : FormalMultilinearSeries 𝕜 F G) (p : FormalMultilinearSeries 𝕜 E F)
    (N : ℕ) (z : E) :
    q.partialSum N (∑ i ∈ Finset.Ico 1 N, p i fun _j => z) =
      ∑ i ∈ compPartialSumTarget 0 N N, q.compAlongComposition p i.2 fun _j => z 
goal: q.partialSum N (∑ i ∈ Finset.Ico 1 N, (p i) fun _j => z) =
  ∑ i ∈ FormalMultilinearSeries.compPartialSumTarget 0 N N, (q.compAlongComposition p i.snd) fun _j => z

full_name: HasFPowerSeriesAt.comp
code: /-- If two functions `g` and `f` have power series `q` and `p` respectively at `f x` and `x`, then
`g ∘ f` admits the power series `q.comp p` at `x`. -/
theorem HasFPowerSeriesAt.comp {g : F → G} {f : E → F} {q : FormalMultilinearSeries 𝕜 F G}
    {p : FormalMultilinearSeries 𝕜 E F} {x : E} (hg : HasFPowerSeriesAt g q (f x))
    (hf : HasFPowerSeriesAt f p x) : HasFPowerSeriesAt (g ∘ f) (q.comp p) x 
goal: HasFPowerSeriesAt (g ∘ f) (q.comp p) x

full_name: AnalyticAt.comp
code: /-- If two functions `g` and `f` are analytic respectively at `f x` and `x`, then `g ∘ f` is
analytic at `x`. -/
theorem AnalyticAt.comp {g : F → G} {f : E → F} {x : E} (hg : AnalyticAt 𝕜 g (f x))
    (hf : AnalyticAt 𝕜 f x) : AnalyticAt 𝕜 (g ∘ f) x 
goal: AnalyticAt 𝕜 (g ∘ f) x

full_name: AnalyticAt.comp_of_eq
code: /-- Version of `AnalyticAt.comp` where point equality is a separate hypothesis. -/
theorem AnalyticAt.comp_of_eq {g : F → G} {f : E → F} {y : F} {x : E} (hg : AnalyticAt 𝕜 g y)
    (hf : AnalyticAt 𝕜 f x) (hy : f x = y) : AnalyticAt 𝕜 (g ∘ f) x 
goal: AnalyticAt 𝕜 (g ∘ f) x

full_name: AnalyticOn.comp'
code: /-- If two functions `g` and `f` are analytic respectively on `s.image f` and `s`, then `g ∘ f` is
analytic on `s`. -/
theorem AnalyticOn.comp' {s : Set E} {g : F → G} {f : E → F} (hg : AnalyticOn 𝕜 g (s.image f))
    (hf : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (g ∘ f) s 
goal: AnalyticOn 𝕜 (g ∘ f) s

full_name: AnalyticOn.comp
code: theorem AnalyticOn.comp {s : Set E} {t : Set F} {g : F → G} {f : E → F} (hg : AnalyticOn 𝕜 g t)
    (hf : AnalyticOn 𝕜 f s) (st : Set.MapsTo f s t) : AnalyticOn 𝕜 (g ∘ f) s 
goal: AnalyticOn 𝕜 (g ∘ f) s

full_name: Composition.sigma_composition_eq_iff
code: /-- Rewriting equality in the dependent type `Σ (a : composition n), composition a.length)` in
non-dependent terms with lists, requiring that the blocks coincide. -/
theorem sigma_composition_eq_iff (i j : Σ a : Composition n, Composition a.length) :
    i = j ↔ i.1.blocks = j.1.blocks ∧ i.2.blocks = j.2.blocks 
goal: i = j ↔ i.fst.blocks = j.fst.blocks ∧ i.snd.blocks = j.snd.blocks

full_name: Composition.sigma_pi_composition_eq_iff
code: /-- Rewriting equality in the dependent type
`Σ (c : composition n), Π (i : fin c.length), composition (c.blocks_fun i)` in
non-dependent terms with lists, requiring that the lists of blocks coincide. -/
theorem sigma_pi_composition_eq_iff
    (u v : Σ c : Composition n, ∀ i : Fin c.length, Composition (c.blocksFun i)) :
    u = v ↔ (ofFn fun i => (u.2 i).blocks) = ofFn fun i => (v.2 i).blocks 
goal: u = v ↔ (List.ofFn fun i => (u.snd i).blocks) = List.ofFn fun i => (v.snd i).blocks

full_name: Composition.gather
code: /-- When `a` is a composition of `n` and `b` is a composition of `a.length`, `a.gather b` is the
composition of `n` obtained by gathering all the blocks of `a` corresponding to a block of `b`.
For instance, if `a = [6, 5, 3, 5, 2]` and `b = [2, 3]`, one should gather together
the first two blocks of `a` and its last three blocks, giving `a.gather b = [11, 10]`. -/
def gather (a : Composition n) (b : Composition a.length) : Composition n 
goal: Composition n

full_name: Composition.length_gather
code: theorem length_gather (a : Composition n) (b : Composition a.length) :
    length (a.gather b) = b.length 
goal: (a.gather b).length = b.length

full_name: Composition.sigmaCompositionAux
code: /-- An auxiliary function used in the definition of `sigmaEquivSigmaPi` below, associating to
two compositions `a` of `n` and `b` of `a.length`, and an index `i` bounded by the length of
`a.gather b`, the subcomposition of `a` made of those blocks belonging to the `i`-th block of
`a.gather b`. -/
def sigmaCompositionAux (a : Composition n) (b : Composition a.length)
    (i : Fin (a.gather b).length) : Composition ((a.gather b).blocksFun i) 
goal: Composition ((a.gather b).blocksFun i)

full_name: Composition.length_sigmaCompositionAux
code: theorem length_sigmaCompositionAux (a : Composition n) (b : Composition a.length)
    (i : Fin b.length) :
    Composition.length (Composition.sigmaCompositionAux a b ⟨i, (length_gather a b).symm ▸ i.2⟩) =
      Composition.blocksFun b i 
goal: (a.sigmaCompositionAux b ⟨↑i, ⋯⟩).length = b.blocksFun i

full_name: Composition.blocksFun_sigmaCompositionAux
code: theorem blocksFun_sigmaCompositionAux (a : Composition n) (b : Composition a.length)
    (i : Fin b.length) (j : Fin (blocksFun b i)) :
    blocksFun (sigmaCompositionAux a b ⟨i, (length_gather a b).symm ▸ i.2⟩)
        ⟨j, (length_sigmaCompositionAux a b i).symm ▸ j.2⟩ =
      blocksFun a (embedding b i j) 
goal: (a.sigmaCompositionAux b ⟨↑i, ⋯⟩).blocksFun ⟨↑j, ⋯⟩ = a.blocksFun ((b.embedding i) j)

full_name: Composition.sizeUpTo_sizeUpTo_add
code: /-- Auxiliary lemma to prove that the composition of formal multilinear series is associative.

Consider a composition `a` of `n` and a composition `b` of `a.length`. Grouping together some
blocks of `a` according to `b` as in `a.gather b`, one can compute the total size of the blocks
of `a` up to an index `size_up_to b i + j` (where the `j` corresponds to a set of blocks of `a`
that do not fill a whole block of `a.gather b`). The first part corresponds to a sum of blocks
in `a.gather b`, and the second one to a sum of blocks in the next block of
`sigma_composition_aux a b`. This is the content of this lemma. -/
theorem sizeUpTo_sizeUpTo_add (a : Composition n) (b : Composition a.length) {i j : ℕ}
    (hi : i < b.length) (hj : j < blocksFun b ⟨i, hi⟩) :
    sizeUpTo a (sizeUpTo b i + j) =
      sizeUpTo (a.gather b) i +
        sizeUpTo (sigmaCompositionAux a b ⟨i, (length_gather a b).symm ▸ hi⟩) j 
goal: a.sizeUpTo (b.sizeUpTo i + j) = (a.gather b).sizeUpTo i + (a.sigmaCompositionAux b ⟨i, ⋯⟩).sizeUpTo j

full_name: Composition.sigmaEquivSigmaPi
code: /-- Natural equivalence between `(Σ (a : composition n), composition a.length)` and
`(Σ (c : composition n), Π (i : fin c.length), composition (c.blocks_fun i))`, that shows up as a
change of variables in the proof that composition of formal multilinear series is associative.

Consider a composition `a` of `n` and a composition `b` of `a.length`. Then `b` indicates how to
group together some blocks of `a`, giving altogether `b.length` blocks of blocks. These blocks of
blocks can be called `d₀, ..., d_{a.length - 1}`, and one obtains a composition `c` of `n` by
saying that each `dᵢ` is one single block. The map `⟨a, b⟩ → ⟨c, (d₀, ..., d_{a.length - 1})⟩` is
the direct map in the equiv.

Conversely, if one starts from `c` and the `dᵢ`s, one can join the `dᵢ`s to obtain a composition
`a` of `n`, and register the lengths of the `dᵢ`s in a composition `b` of `a.length`. This is the
inverse map of the equiv.
-/
def sigmaEquivSigmaPi (n : ℕ) :
    (Σ a : Composition n, Composition a.length) ≃
      Σ c : Composition n, ∀ i : Fin c.length, Composition (c.blocksFun i) 
goal: (a : Composition n) × Composition a.length ≃ (c : Composition n) × ((i : Fin c.length) → Composition (c.blocksFun i))

full_name: FormalMultilinearSeries.comp_assoc
code: theorem comp_assoc (r : FormalMultilinearSeries 𝕜 G H) (q : FormalMultilinearSeries 𝕜 F G)
    (p : FormalMultilinearSeries 𝕜 E F) : (r.comp q).comp p = r.comp (q.comp p) 
goal: (r.comp q).comp p = r.comp (q.comp p)