l3lab/ntp-mathlib huggingface dataset:
theorem mem_range_embedding_iff {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ c.sizeUpTo i ≤ j ∧ (j : ℕ) < c.sizeUpTo (i : ℕ).succ := by
  constructor
  · intro h
    rcases Set.mem_range.2 h with ⟨k, hk⟩
    rw [Fin.ext_iff] at hk
    dsimp at hk
    rw [← hk]
    simp [sizeUpTo_succ', k.is_lt]
  · intro h
    apply Set.mem_range.2
    refine' ⟨⟨j - c.sizeUpTo i, _⟩, _⟩
    · rw [tsub_lt_iff_left, ← sizeUpTo_succ']
      · exact h.2
      · exact h.1
    · 

Proof state:
case mpr.refine'_2
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)
⊢ (embedding c i) { val := ↑j - sizeUpTo c ↑i, isLt := (_ : ↑j - sizeUpTo c ↑i < blocksFun c i) } = j

Next tactic:
rw [Fin.ext_iff]
theorem mem_range_embedding_iff {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ c.sizeUpTo i ≤ j ∧ (j : ℕ) < c.sizeUpTo (i : ℕ).succ := by
  constructor
  · intro h
    rcases Set.mem_range.2 h with ⟨k, hk⟩
    rw [Fin.ext_iff] at hk
    dsimp at hk
    rw [← hk]
    simp [sizeUpTo_succ', k.is_lt]
  · intro h
    apply Set.mem_range.2
    refine' ⟨⟨j - c.sizeUpTo i, _⟩, _⟩
    · rw [tsub_lt_iff_left, ← sizeUpTo_succ']
      · exact h.2
      · exact h.1
    · rw [Fin.ext_iff]
      

Proof state:
case mpr.refine'_2
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)
⊢ ↑((embedding c i) { val := ↑j - sizeUpTo c ↑i, isLt := (_ : ↑j - sizeUpTo c ↑i < blocksFun c i) }) = ↑j

Next tactic:
exact add_tsub_cancel_of_le h.1
/-- The embeddings of different blocks of a composition are disjoint. -/
theorem disjoint_range {i₁ i₂ : Fin c.length} (h : i₁ ≠ i₂) :
    Disjoint (Set.range (c.embedding i₁)) (Set.range (c.embedding i₂)) := by
  

Proof state:
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
⊢ _root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))

Next tactic:
classical
    wlog h' : i₁ < i₂
    exact (this c h.symm (h.lt_or_lt.resolve_left h')).symm
    by_contra d
    obtain ⟨x, hx₁, hx₂⟩ :
      ∃ x : Fin n, x ∈ Set.range (c.embedding i₁) ∧ x ∈ Set.range (c.embedding i₂) :=
      Set.not_disjoint_iff.1 d
    have A : (i₁ : ℕ).succ ≤ i₂ := Nat.succ_le_of_lt h'
    apply lt_irrefl (x : ℕ)
    calc
      (x : ℕ) < c.sizeUpTo (i₁ : ℕ).succ := (c.mem_range_embedding_iff.1 hx₁).2
      _ ≤ c.sizeUpTo (i₂ : ℕ) := monotone_sum_take _ A
      _ ≤ x := (c.mem_range_embedding_iff.1 hx₂).1
/-- The embeddings of different blocks of a composition are disjoint. -/
theorem disjoint_range {i₁ i₂ : Fin c.length} (h : i₁ ≠ i₂) :
    Disjoint (Set.range (c.embedding i₁)) (Set.range (c.embedding i₂)) := by
  classical
    

Proof state:
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
⊢ _root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))

Next tactic:
wlog h' : i₁ < i₂
/-- The embeddings of different blocks of a composition are disjoint. -/
theorem disjoint_range {i₁ i₂ : Fin c.length} (h : i₁ ≠ i₂) :
    Disjoint (Set.range (c.embedding i₁)) (Set.range (c.embedding i₂)) := by
  classical
    wlog h' : i₁ < i₂
    

Proof state:
case inr
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
this :
  ∀ {n : ℕ} (c : Composition n) {i₁ i₂ : Fin (length c)},
    i₁ ≠ i₂ → i₁ < i₂ → _root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))
h' : ¬i₁ < i₂
⊢ _root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
h' : i₁ < i₂
⊢ _root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))

Next tactic:
exact (this c h.symm (h.lt_or_lt.resolve_left h')).symm
/-- The embeddings of different blocks of a composition are disjoint. -/
theorem disjoint_range {i₁ i₂ : Fin c.length} (h : i₁ ≠ i₂) :
    Disjoint (Set.range (c.embedding i₁)) (Set.range (c.embedding i₂)) := by
  classical
    wlog h' : i₁ < i₂
    exact (this c h.symm (h.lt_or_lt.resolve_left h')).symm
    

Proof state:
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
h' : i₁ < i₂
⊢ _root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))

Next tactic:
by_contra d
/-- The embeddings of different blocks of a composition are disjoint. -/
theorem disjoint_range {i₁ i₂ : Fin c.length} (h : i₁ ≠ i₂) :
    Disjoint (Set.range (c.embedding i₁)) (Set.range (c.embedding i₂)) := by
  classical
    wlog h' : i₁ < i₂
    exact (this c h.symm (h.lt_or_lt.resolve_left h')).symm
    by_contra d
    

Proof state:
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
h' : i₁ < i₂
d : ¬_root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))
⊢ False

Next tactic:
obtain ⟨x, hx₁, hx₂⟩ :
      ∃ x : Fin n, x ∈ Set.range (c.embedding i₁) ∧ x ∈ Set.range (c.embedding i₂) :=
      Set.not_disjoint_iff.1 d
/-- The embeddings of different blocks of a composition are disjoint. -/
theorem disjoint_range {i₁ i₂ : Fin c.length} (h : i₁ ≠ i₂) :
    Disjoint (Set.range (c.embedding i₁)) (Set.range (c.embedding i₂)) := by
  classical
    wlog h' : i₁ < i₂
    exact (this c h.symm (h.lt_or_lt.resolve_left h')).symm
    by_contra d
    obtain ⟨x, hx₁, hx₂⟩ :
      ∃ x : Fin n, x ∈ Set.range (c.embedding i₁) ∧ x ∈ Set.range (c.embedding i₂) :=
      Set.not_disjoint_iff.1 d
    

Proof state:
case intro.intro
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
h' : i₁ < i₂
d : ¬_root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))
x : Fin n
hx₁ : x ∈ Set.range ⇑(embedding c i₁)
hx₂ : x ∈ Set.range ⇑(embedding c i₂)
⊢ False

Next tactic:
have A : (i₁ : ℕ).succ ≤ i₂ := Nat.succ_le_of_lt h'
/-- The embeddings of different blocks of a composition are disjoint. -/
theorem disjoint_range {i₁ i₂ : Fin c.length} (h : i₁ ≠ i₂) :
    Disjoint (Set.range (c.embedding i₁)) (Set.range (c.embedding i₂)) := by
  classical
    wlog h' : i₁ < i₂
    exact (this c h.symm (h.lt_or_lt.resolve_left h')).symm
    by_contra d
    obtain ⟨x, hx₁, hx₂⟩ :
      ∃ x : Fin n, x ∈ Set.range (c.embedding i₁) ∧ x ∈ Set.range (c.embedding i₂) :=
      Set.not_disjoint_iff.1 d
    have A : (i₁ : ℕ).succ ≤ i₂ := Nat.succ_le_of_lt h'
    

Proof state:
case intro.intro
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
h' : i₁ < i₂
d : ¬_root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))
x : Fin n
hx₁ : x ∈ Set.range ⇑(embedding c i₁)
hx₂ : x ∈ Set.range ⇑(embedding c i₂)
A : Nat.succ ↑i₁ ≤ ↑i₂
⊢ False

Next tactic:
apply lt_irrefl (x : ℕ)
/-- The embeddings of different blocks of a composition are disjoint. -/
theorem disjoint_range {i₁ i₂ : Fin c.length} (h : i₁ ≠ i₂) :
    Disjoint (Set.range (c.embedding i₁)) (Set.range (c.embedding i₂)) := by
  classical
    wlog h' : i₁ < i₂
    exact (this c h.symm (h.lt_or_lt.resolve_left h')).symm
    by_contra d
    obtain ⟨x, hx₁, hx₂⟩ :
      ∃ x : Fin n, x ∈ Set.range (c.embedding i₁) ∧ x ∈ Set.range (c.embedding i₂) :=
      Set.not_disjoint_iff.1 d
    have A : (i₁ : ℕ).succ ≤ i₂ := Nat.succ_le_of_lt h'
    apply lt_irrefl (x : ℕ)
    

Proof state:
case intro.intro
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
i₁ i₂ : Fin (length c)
h : i₁ ≠ i₂
h' : i₁ < i₂
d : ¬_root_.Disjoint (Set.range ⇑(embedding c i₁)) (Set.range ⇑(embedding c i₂))
x : Fin n
hx₁ : x ∈ Set.range ⇑(embedding c i₁)
hx₂ : x ∈ Set.range ⇑(embedding c i₂)
A : Nat.succ ↑i₁ ≤ ↑i₂
⊢ ↑x < ↑x

Next tactic:
calc
      (x : ℕ) < c.sizeUpTo (i₁ : ℕ).succ := (c.mem_range_embedding_iff.1 hx₁).2
      _ ≤ c.sizeUpTo (i₂ : ℕ) := monotone_sum_take _ A
      _ ≤ x := (c.mem_range_embedding_iff.1 hx₂).1
theorem mem_range_embedding (j : Fin n) : j ∈ Set.range (c.embedding (c.index j)) := by
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
⊢ j ∈ Set.range ⇑(embedding c (index c j))

Next tactic:
have : c.embedding (c.index j) (c.invEmbedding j) ∈ Set.range (c.embedding (c.index j)) :=
    Set.mem_range_self _
theorem mem_range_embedding (j : Fin n) : j ∈ Set.range (c.embedding (c.index j)) := by
  have : c.embedding (c.index j) (c.invEmbedding j) ∈ Set.range (c.embedding (c.index j)) :=
    Set.mem_range_self _
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
this : (embedding c (index c j)) (invEmbedding c j) ∈ Set.range ⇑(embedding c (index c j))
⊢ j ∈ Set.range ⇑(embedding c (index c j))

Next tactic:
rwa [c.embedding_comp_inv j] at this
theorem mem_range_embedding_iff' {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ i = c.index j := by
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
⊢ j ∈ Set.range ⇑(embedding c i) ↔ i = index c j

Next tactic:
constructor
theorem mem_range_embedding_iff' {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ i = c.index j := by
  constructor
  · 

Proof state:
case mp
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
⊢ j ∈ Set.range ⇑(embedding c i) → i = index c j

Next tactic:
rw [← not_imp_not]
theorem mem_range_embedding_iff' {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ i = c.index j := by
  constructor
  · rw [← not_imp_not]
    

Proof state:
case mp
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
⊢ ¬i = index c j → j ∉ Set.range ⇑(embedding c i)

Next tactic:
intro h
theorem mem_range_embedding_iff' {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ i = c.index j := by
  constructor
  · rw [← not_imp_not]
    intro h
    

Proof state:
case mp
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : ¬i = index c j
⊢ j ∉ Set.range ⇑(embedding c i)

Next tactic:
exact Set.disjoint_right.1 (c.disjoint_range h) (c.mem_range_embedding j)
theorem mem_range_embedding_iff' {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ i = c.index j := by
  constructor
  · rw [← not_imp_not]
    intro h
    exact Set.disjoint_right.1 (c.disjoint_range h) (c.mem_range_embedding j)
  · 

Proof state:
case mpr
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
⊢ i = index c j → j ∈ Set.range ⇑(embedding c i)

Next tactic:
intro h
theorem mem_range_embedding_iff' {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ i = c.index j := by
  constructor
  · rw [← not_imp_not]
    intro h
    exact Set.disjoint_right.1 (c.disjoint_range h) (c.mem_range_embedding j)
  · intro h
    

Proof state:
case mpr
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : i = index c j
⊢ j ∈ Set.range ⇑(embedding c i)

Next tactic:
rw [h]
theorem mem_range_embedding_iff' {j : Fin n} {i : Fin c.length} :
    j ∈ Set.range (c.embedding i) ↔ i = c.index j := by
  constructor
  · rw [← not_imp_not]
    intro h
    exact Set.disjoint_right.1 (c.disjoint_range h) (c.mem_range_embedding j)
  · intro h
    rw [h]
    

Proof state:
case mpr
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : i = index c j
⊢ j ∈ Set.range ⇑(embedding c (index c j))

Next tactic:
exact c.mem_range_embedding j
theorem index_embedding (i : Fin c.length) (j : Fin (c.blocksFun i)) :
    c.index (c.embedding i j) = i := by
  

Proof state:
n : ℕ
c : Composition n
i : Fin (length c)
j : Fin (blocksFun c i)
⊢ index c ((embedding c i) j) = i

Next tactic:
symm
theorem index_embedding (i : Fin c.length) (j : Fin (c.blocksFun i)) :
    c.index (c.embedding i j) = i := by
  symm
  

Proof state:
n : ℕ
c : Composition n
i : Fin (length c)
j : Fin (blocksFun c i)
⊢ i = index c ((embedding c i) j)

Next tactic:
rw [← mem_range_embedding_iff']
theorem index_embedding (i : Fin c.length) (j : Fin (c.blocksFun i)) :
    c.index (c.embedding i j) = i := by
  symm
  rw [← mem_range_embedding_iff']
  

Proof state:
n : ℕ
c : Composition n
i : Fin (length c)
j : Fin (blocksFun c i)
⊢ (embedding c i) j ∈ Set.range ⇑(embedding c i)

Next tactic:
apply Set.mem_range_self
theorem invEmbedding_comp (i : Fin c.length) (j : Fin (c.blocksFun i)) :
    (c.invEmbedding (c.embedding i j) : ℕ) = j := by
  

Proof state:
n : ℕ
c : Composition n
i : Fin (length c)
j : Fin (blocksFun c i)
⊢ ↑(invEmbedding c ((embedding c i) j)) = ↑j

Next tactic:
simp_rw [coe_invEmbedding, index_embedding, coe_embedding, add_tsub_cancel_left]
/-- Equivalence between the disjoint union of the blocks (each of them seen as
`Fin (c.blocks_fun i)`) with `Fin n`. -/
def blocksFinEquiv : (Σi : Fin c.length, Fin (c.blocksFun i)) ≃ Fin n
    where
  toFun x := c.embedding x.1 x.2
  invFun j := ⟨c.index j, c.invEmbedding j⟩
  left_inv x := by
    

Proof state:
n : ℕ
c : Composition n
x : (i : Fin (length c)) × Fin (blocksFun c i)
⊢ (fun j => { fst := index c j, snd := invEmbedding c j }) ((fun x => (embedding c x.fst) x.snd) x) = x

Next tactic:
rcases x with ⟨i, y⟩
/-- Equivalence between the disjoint union of the blocks (each of them seen as
`Fin (c.blocks_fun i)`) with `Fin n`. -/
def blocksFinEquiv : (Σi : Fin c.length, Fin (c.blocksFun i)) ≃ Fin n
    where
  toFun x := c.embedding x.1 x.2
  invFun j := ⟨c.index j, c.invEmbedding j⟩
  left_inv x := by
    rcases x with ⟨i, y⟩
    

Proof state:
case mk
n : ℕ
c : Composition n
i : Fin (length c)
y : Fin (blocksFun c i)
⊢ (fun j => { fst := index c j, snd := invEmbedding c j })
      ((fun x => (embedding c x.fst) x.snd) { fst := i, snd := y }) =
    { fst := i, snd := y }

Next tactic:
dsimp
/-- Equivalence between the disjoint union of the blocks (each of them seen as
`Fin (c.blocks_fun i)`) with `Fin n`. -/
def blocksFinEquiv : (Σi : Fin c.length, Fin (c.blocksFun i)) ≃ Fin n
    where
  toFun x := c.embedding x.1 x.2
  invFun j := ⟨c.index j, c.invEmbedding j⟩
  left_inv x := by
    rcases x with ⟨i, y⟩
    dsimp
    

Proof state:
case mk
n : ℕ
c : Composition n
i : Fin (length c)
y : Fin (blocksFun c i)
⊢ { fst := index c ((embedding c i) y), snd := invEmbedding c ((embedding c i) y) } = { fst := i, snd := y }

Next tactic:
congr
/-- Equivalence between the disjoint union of the blocks (each of them seen as
`Fin (c.blocks_fun i)`) with `Fin n`. -/
def blocksFinEquiv : (Σi : Fin c.length, Fin (c.blocksFun i)) ≃ Fin n
    where
  toFun x := c.embedding x.1 x.2
  invFun j := ⟨c.index j, c.invEmbedding j⟩
  left_inv x := by
    rcases x with ⟨i, y⟩
    dsimp
    congr; · 

Proof state:
case mk.h.e_3.h
n : ℕ
c : Composition n
i : Fin (length c)
y : Fin (blocksFun c i)
⊢ index c ((embedding c i) y) = i

Next tactic:
exact c.index_embedding _ _
/-- Equivalence between the disjoint union of the blocks (each of them seen as
`Fin (c.blocks_fun i)`) with `Fin n`. -/
def blocksFinEquiv : (Σi : Fin c.length, Fin (c.blocksFun i)) ≃ Fin n
    where
  toFun x := c.embedding x.1 x.2
  invFun j := ⟨c.index j, c.invEmbedding j⟩
  left_inv x := by
    rcases x with ⟨i, y⟩
    dsimp
    congr; · exact c.index_embedding _ _
    

Proof state:
case mk.h.e_4
n : ℕ
c : Composition n
i : Fin (length c)
y : Fin (blocksFun c i)
⊢ HEq (invEmbedding c ((embedding c i) y)) y

Next tactic:
rw [Fin.heq_ext_iff]
/-- Equivalence between the disjoint union of the blocks (each of them seen as
`Fin (c.blocks_fun i)`) with `Fin n`. -/
def blocksFinEquiv : (Σi : Fin c.length, Fin (c.blocksFun i)) ≃ Fin n
    where
  toFun x := c.embedding x.1 x.2
  invFun j := ⟨c.index j, c.invEmbedding j⟩
  left_inv x := by
    rcases x with ⟨i, y⟩
    dsimp
    congr; · exact c.index_embedding _ _
    rw [Fin.heq_ext_iff]
    · 

Proof state:
case mk.h.e_4
n : ℕ
c : Composition n
i : Fin (length c)
y : Fin (blocksFun c i)
⊢ ↑(invEmbedding c ((embedding c i) y)) = ↑y

Next tactic:
exact c.invEmbedding_comp _ _
/-- Equivalence between the disjoint union of the blocks (each of them seen as
`Fin (c.blocks_fun i)`) with `Fin n`. -/
def blocksFinEquiv : (Σi : Fin c.length, Fin (c.blocksFun i)) ≃ Fin n
    where
  toFun x := c.embedding x.1 x.2
  invFun j := ⟨c.index j, c.invEmbedding j⟩
  left_inv x := by
    rcases x with ⟨i, y⟩
    dsimp
    congr; · exact c.index_embedding _ _
    rw [Fin.heq_ext_iff]
    · exact c.invEmbedding_comp _ _
    · 

Proof state:
case mk.h.e_4.h
n : ℕ
c : Composition n
i : Fin (length c)
y : Fin (blocksFun c i)
⊢ blocksFun c (index c ((embedding c i) y)) = blocksFun c i

Next tactic:
rw [c.index_embedding]
theorem blocksFun_congr {n₁ n₂ : ℕ} (c₁ : Composition n₁) (c₂ : Composition n₂) (i₁ : Fin c₁.length)
    (i₂ : Fin c₂.length) (hn : n₁ = n₂) (hc : c₁.blocks = c₂.blocks) (hi : (i₁ : ℕ) = i₂) :
    c₁.blocksFun i₁ = c₂.blocksFun i₂ := by
  

Proof state:
n : ℕ
c : Composition n
n₁ n₂ : ℕ
c₁ : Composition n₁
c₂ : Composition n₂
i₁ : Fin (length c₁)
i₂ : Fin (length c₂)
hn : n₁ = n₂
hc : c₁.blocks = c₂.blocks
hi : ↑i₁ = ↑i₂
⊢ blocksFun c₁ i₁ = blocksFun c₂ i₂

Next tactic:
cases hn
theorem blocksFun_congr {n₁ n₂ : ℕ} (c₁ : Composition n₁) (c₂ : Composition n₂) (i₁ : Fin c₁.length)
    (i₂ : Fin c₂.length) (hn : n₁ = n₂) (hc : c₁.blocks = c₂.blocks) (hi : (i₁ : ℕ) = i₂) :
    c₁.blocksFun i₁ = c₂.blocksFun i₂ := by
  cases hn
  

Proof state:
case refl
n : ℕ
c : Composition n
n₁ : ℕ
c₁ : Composition n₁
i₁ : Fin (length c₁)
c₂ : Composition n₁
i₂ : Fin (length c₂)
hc : c₁.blocks = c₂.blocks
hi : ↑i₁ = ↑i₂
⊢ blocksFun c₁ i₁ = blocksFun c₂ i₂

Next tactic:
rw [← Composition.ext_iff] at hc
theorem blocksFun_congr {n₁ n₂ : ℕ} (c₁ : Composition n₁) (c₂ : Composition n₂) (i₁ : Fin c₁.length)
    (i₂ : Fin c₂.length) (hn : n₁ = n₂) (hc : c₁.blocks = c₂.blocks) (hi : (i₁ : ℕ) = i₂) :
    c₁.blocksFun i₁ = c₂.blocksFun i₂ := by
  cases hn
  rw [← Composition.ext_iff] at hc
  

Proof state:
case refl
n : ℕ
c : Composition n
n₁ : ℕ
c₁ : Composition n₁
i₁ : Fin (length c₁)
c₂ : Composition n₁
i₂ : Fin (length c₂)
hc : c₁ = c₂
hi : ↑i₁ = ↑i₂
⊢ blocksFun c₁ i₁ = blocksFun c₂ i₂

Next tactic:
cases hc
theorem blocksFun_congr {n₁ n₂ : ℕ} (c₁ : Composition n₁) (c₂ : Composition n₂) (i₁ : Fin c₁.length)
    (i₂ : Fin c₂.length) (hn : n₁ = n₂) (hc : c₁.blocks = c₂.blocks) (hi : (i₁ : ℕ) = i₂) :
    c₁.blocksFun i₁ = c₂.blocksFun i₂ := by
  cases hn
  rw [← Composition.ext_iff] at hc
  cases hc
  

Proof state:
case refl.refl
n : ℕ
c : Composition n
n₁ : ℕ
c₁ : Composition n₁
i₁ i₂ : Fin (length c₁)
hi : ↑i₁ = ↑i₂
⊢ blocksFun c₁ i₁ = blocksFun c₁ i₂

Next tactic:
congr
theorem blocksFun_congr {n₁ n₂ : ℕ} (c₁ : Composition n₁) (c₂ : Composition n₂) (i₁ : Fin c₁.length)
    (i₂ : Fin c₂.length) (hn : n₁ = n₂) (hc : c₁.blocks = c₂.blocks) (hi : (i₁ : ℕ) = i₂) :
    c₁.blocksFun i₁ = c₂.blocksFun i₂ := by
  cases hn
  rw [← Composition.ext_iff] at hc
  cases hc
  congr
  

Proof state:
case refl.refl.e_a
n : ℕ
c : Composition n
n₁ : ℕ
c₁ : Composition n₁
i₁ i₂ : Fin (length c₁)
hi : ↑i₁ = ↑i₂
⊢ i₁ = i₂

Next tactic:
rwa [Fin.ext_iff]
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  

Proof state:
n : ℕ
c✝ : Composition n
c c' : (n : ℕ) × Composition n
⊢ c = c' ↔ c.snd.blocks = c'.snd.blocks

Next tactic:
refine' ⟨fun H => by rw [H], fun H => _⟩
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by 

Proof state:
n : ℕ
c✝ : Composition n
c c' : (n : ℕ) × Composition n
H : c = c'
⊢ c.snd.blocks = c'.snd.blocks

Next tactic:
rw [H]
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by rw [H], fun H => _⟩
  

Proof state:
n : ℕ
c✝ : Composition n
c c' : (n : ℕ) × Composition n
H : c.snd.blocks = c'.snd.blocks
⊢ c = c'

Next tactic:
rcases c with ⟨n, c⟩
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by rw [H], fun H => _⟩
  rcases c with ⟨n, c⟩
  

Proof state:
case mk
n✝ : ℕ
c✝ : Composition n✝
c' : (n : ℕ) × Composition n
n : ℕ
c : Composition n
H : { fst := n, snd := c }.snd.blocks = c'.snd.blocks
⊢ { fst := n, snd := c } = c'

Next tactic:
rcases c' with ⟨n', c'⟩
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by rw [H], fun H => _⟩
  rcases c with ⟨n, c⟩
  rcases c' with ⟨n', c'⟩
  

Proof state:
case mk.mk
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
n' : ℕ
c' : Composition n'
H : { fst := n, snd := c }.snd.blocks = { fst := n', snd := c' }.snd.blocks
⊢ { fst := n, snd := c } = { fst := n', snd := c' }

Next tactic:
have : n = n' := by rw [← c.blocks_sum, ← c'.blocks_sum, H]
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by rw [H], fun H => _⟩
  rcases c with ⟨n, c⟩
  rcases c' with ⟨n', c'⟩
  have : n = n' := by 

Proof state:
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
n' : ℕ
c' : Composition n'
H : { fst := n, snd := c }.snd.blocks = { fst := n', snd := c' }.snd.blocks
⊢ n = n'

Next tactic:
rw [← c.blocks_sum, ← c'.blocks_sum, H]
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by rw [H], fun H => _⟩
  rcases c with ⟨n, c⟩
  rcases c' with ⟨n', c'⟩
  have : n = n' := by rw [← c.blocks_sum, ← c'.blocks_sum, H]
  

Proof state:
case mk.mk
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
n' : ℕ
c' : Composition n'
H : { fst := n, snd := c }.snd.blocks = { fst := n', snd := c' }.snd.blocks
this : n = n'
⊢ { fst := n, snd := c } = { fst := n', snd := c' }

Next tactic:
induction this
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by rw [H], fun H => _⟩
  rcases c with ⟨n, c⟩
  rcases c' with ⟨n', c'⟩
  have : n = n' := by rw [← c.blocks_sum, ← c'.blocks_sum, H]
  induction this
  

Proof state:
case mk.mk.refl
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
n' : ℕ
c' : Composition n
H : { fst := n, snd := c }.snd.blocks = { fst := n, snd := c' }.snd.blocks
⊢ { fst := n, snd := c } = { fst := n, snd := c' }

Next tactic:
congr
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by rw [H], fun H => _⟩
  rcases c with ⟨n, c⟩
  rcases c' with ⟨n', c'⟩
  have : n = n' := by rw [← c.blocks_sum, ← c'.blocks_sum, H]
  induction this
  congr
  

Proof state:
case mk.mk.refl.e_snd
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
n' : ℕ
c' : Composition n
H : { fst := n, snd := c }.snd.blocks = { fst := n, snd := c' }.snd.blocks
⊢ c = c'

Next tactic:
ext1
/-- Two compositions (possibly of different integers) coincide if and only if they have the
same sequence of blocks. -/
theorem sigma_eq_iff_blocks_eq {c : Σn, Composition n} {c' : Σn, Composition n} :
    c = c' ↔ c.2.blocks = c'.2.blocks := by
  refine' ⟨fun H => by rw [H], fun H => _⟩
  rcases c with ⟨n, c⟩
  rcases c' with ⟨n', c'⟩
  have : n = n' := by rw [← c.blocks_sum, ← c'.blocks_sum, H]
  induction this
  congr
  ext1
  

Proof state:
case mk.mk.refl.e_snd.blocks
n✝ : ℕ
c✝ : Composition n✝
n : ℕ
c : Composition n
n' : ℕ
c' : Composition n
H : { fst := n, snd := c }.snd.blocks = { fst := n, snd := c' }.snd.blocks
⊢ c.blocks = c'.blocks

Next tactic:
exact H