l3lab/ntp-mathlib huggingface dataset:
theorem sizeUpTo_le (i : ℕ) : c.sizeUpTo i ≤ n := by
  conv_rhs => 

Proof state:
n : ℕ
c : Composition n
i : ℕ
| n

Next tactic:
rw [← c.blocks_sum, ← sum_take_add_sum_drop _ i]
theorem sizeUpTo_le (i : ℕ) : c.sizeUpTo i ≤ n := by
  conv_rhs => rw [← c.blocks_sum, ← sum_take_add_sum_drop _ i]
  

Proof state:
n : ℕ
c : Composition n
i : ℕ
⊢ sizeUpTo c i ≤ sum (take i c.blocks) + sum (drop i c.blocks)

Next tactic:
exact Nat.le_add_right _ _
theorem sizeUpTo_succ {i : ℕ} (h : i < c.length) :
    c.sizeUpTo (i + 1) = c.sizeUpTo i + c.blocks.get ⟨i, h⟩ := by
  

Proof state:
n : ℕ
c : Composition n
i : ℕ
h : i < length c
⊢ sizeUpTo c (i + 1) = sizeUpTo c i + List.get c.blocks { val := i, isLt := h }

Next tactic:
simp only [sizeUpTo]
theorem sizeUpTo_succ {i : ℕ} (h : i < c.length) :
    c.sizeUpTo (i + 1) = c.sizeUpTo i + c.blocks.get ⟨i, h⟩ := by
  simp only [sizeUpTo]
  

Proof state:
n : ℕ
c : Composition n
i : ℕ
h : i < length c
⊢ sum (take (i + 1) c.blocks) = sum (take i c.blocks) + List.get c.blocks { val := i, isLt := h }

Next tactic:
rw [sum_take_succ _ _ h]
theorem sizeUpTo_strict_mono {i : ℕ} (h : i < c.length) : c.sizeUpTo i < c.sizeUpTo (i + 1) := by
  

Proof state:
n : ℕ
c : Composition n
i : ℕ
h : i < length c
⊢ sizeUpTo c i < sizeUpTo c (i + 1)

Next tactic:
rw [c.sizeUpTo_succ h]
theorem sizeUpTo_strict_mono {i : ℕ} (h : i < c.length) : c.sizeUpTo i < c.sizeUpTo (i + 1) := by
  rw [c.sizeUpTo_succ h]
  

Proof state:
n : ℕ
c : Composition n
i : ℕ
h : i < length c
⊢ sizeUpTo c i < sizeUpTo c i + List.get c.blocks { val := i, isLt := h }

Next tactic:
simp
@[simp]
theorem boundary_zero : c.boundary 0 = 0 := by 

Proof state:
n : ℕ
c : Composition n
⊢ (boundary c) 0 = 0

Next tactic:
simp [boundary, Fin.ext_iff]
@[simp]
theorem boundary_last : c.boundary (Fin.last c.length) = Fin.last n := by
  

Proof state:
n : ℕ
c : Composition n
⊢ (boundary c) (Fin.last (length c)) = Fin.last n

Next tactic:
simp [boundary, Fin.ext_iff]
theorem card_boundaries_eq_succ_length : c.boundaries.card = c.length + 1 := by 

Proof state:
n : ℕ
c : Composition n
⊢ Finset.card (boundaries c) = length c + 1

Next tactic:
simp [boundaries]
/-- To `c : Composition n`, one can associate a `CompositionAsSet n` by registering the leftmost
point of each block, and adding a virtual point at the right of the last block. -/
def toCompositionAsSet : CompositionAsSet n
    where
  boundaries := c.boundaries
  zero_mem := by
    

Proof state:
n : ℕ
c : Composition n
⊢ 0 ∈ boundaries c

Next tactic:
simp only [boundaries, Finset.mem_univ, exists_prop_of_true, Finset.mem_map]
/-- To `c : Composition n`, one can associate a `CompositionAsSet n` by registering the leftmost
point of each block, and adding a virtual point at the right of the last block. -/
def toCompositionAsSet : CompositionAsSet n
    where
  boundaries := c.boundaries
  zero_mem := by
    simp only [boundaries, Finset.mem_univ, exists_prop_of_true, Finset.mem_map]
    

Proof state:
n : ℕ
c : Composition n
⊢ ∃ a, True ∧ (boundary c).toEmbedding a = 0

Next tactic:
exact ⟨0, And.intro True.intro rfl⟩
/-- To `c : Composition n`, one can associate a `CompositionAsSet n` by registering the leftmost
point of each block, and adding a virtual point at the right of the last block. -/
def toCompositionAsSet : CompositionAsSet n
    where
  boundaries := c.boundaries
  zero_mem := by
    simp only [boundaries, Finset.mem_univ, exists_prop_of_true, Finset.mem_map]
    exact ⟨0, And.intro True.intro rfl⟩
  getLast_mem := by
    

Proof state:
n : ℕ
c : Composition n
⊢ Fin.last n ∈ boundaries c

Next tactic:
simp only [boundaries, Finset.mem_univ, exists_prop_of_true, Finset.mem_map]
/-- To `c : Composition n`, one can associate a `CompositionAsSet n` by registering the leftmost
point of each block, and adding a virtual point at the right of the last block. -/
def toCompositionAsSet : CompositionAsSet n
    where
  boundaries := c.boundaries
  zero_mem := by
    simp only [boundaries, Finset.mem_univ, exists_prop_of_true, Finset.mem_map]
    exact ⟨0, And.intro True.intro rfl⟩
  getLast_mem := by
    simp only [boundaries, Finset.mem_univ, exists_prop_of_true, Finset.mem_map]
    

Proof state:
n : ℕ
c : Composition n
⊢ ∃ a, True ∧ (boundary c).toEmbedding a = Fin.last n

Next tactic:
exact ⟨Fin.last c.length, And.intro True.intro c.boundary_last⟩
/-- The canonical increasing bijection between `Fin (c.length + 1)` and `c.boundaries` is
exactly `c.boundary`. -/
theorem orderEmbOfFin_boundaries :
    c.boundaries.orderEmbOfFin c.card_boundaries_eq_succ_length = c.boundary := by
  

Proof state:
n : ℕ
c : Composition n
⊢ Finset.orderEmbOfFin (boundaries c) (_ : Finset.card (boundaries c) = length c + 1) = boundary c

Next tactic:
refine' (Finset.orderEmbOfFin_unique' _ _).symm
/-- The canonical increasing bijection between `Fin (c.length + 1)` and `c.boundaries` is
exactly `c.boundary`. -/
theorem orderEmbOfFin_boundaries :
    c.boundaries.orderEmbOfFin c.card_boundaries_eq_succ_length = c.boundary := by
  refine' (Finset.orderEmbOfFin_unique' _ _).symm
  

Proof state:
n : ℕ
c : Composition n
⊢ ∀ (x : Fin (length c + 1)), (boundary c) x ∈ boundaries c

Next tactic:
exact fun i => (Finset.mem_map' _).2 (Finset.mem_univ _)
/-- `index_exists` asserts there is some `i` with `j < c.size_up_to (i+1)`.
In the next definition `index` we use `nat.find` to produce the minimal such index.
-/
theorem index_exists {j : ℕ} (h : j < n) : ∃ i : ℕ, j < c.sizeUpTo i.succ ∧ i < c.length := by
  

Proof state:
n : ℕ
c : Composition n
j : ℕ
h : j < n
⊢ ∃ i, j < sizeUpTo c (Nat.succ i) ∧ i < length c

Next tactic:
have n_pos : 0 < n := lt_of_le_of_lt (zero_le j) h
/-- `index_exists` asserts there is some `i` with `j < c.size_up_to (i+1)`.
In the next definition `index` we use `nat.find` to produce the minimal such index.
-/
theorem index_exists {j : ℕ} (h : j < n) : ∃ i : ℕ, j < c.sizeUpTo i.succ ∧ i < c.length := by
  have n_pos : 0 < n := lt_of_le_of_lt (zero_le j) h
  

Proof state:
n : ℕ
c : Composition n
j : ℕ
h : j < n
n_pos : 0 < n
⊢ ∃ i, j < sizeUpTo c (Nat.succ i) ∧ i < length c

Next tactic:
have : 0 < c.blocks.sum := by rwa [← c.blocks_sum] at n_pos
/-- `index_exists` asserts there is some `i` with `j < c.size_up_to (i+1)`.
In the next definition `index` we use `nat.find` to produce the minimal such index.
-/
theorem index_exists {j : ℕ} (h : j < n) : ∃ i : ℕ, j < c.sizeUpTo i.succ ∧ i < c.length := by
  have n_pos : 0 < n := lt_of_le_of_lt (zero_le j) h
  have : 0 < c.blocks.sum := by 

Proof state:
n : ℕ
c : Composition n
j : ℕ
h : j < n
n_pos : 0 < n
⊢ 0 < sum c.blocks

Next tactic:
rwa [← c.blocks_sum] at n_pos
/-- `index_exists` asserts there is some `i` with `j < c.size_up_to (i+1)`.
In the next definition `index` we use `nat.find` to produce the minimal such index.
-/
theorem index_exists {j : ℕ} (h : j < n) : ∃ i : ℕ, j < c.sizeUpTo i.succ ∧ i < c.length := by
  have n_pos : 0 < n := lt_of_le_of_lt (zero_le j) h
  have : 0 < c.blocks.sum := by rwa [← c.blocks_sum] at n_pos
  

Proof state:
n : ℕ
c : Composition n
j : ℕ
h : j < n
n_pos : 0 < n
this : 0 < sum c.blocks
⊢ ∃ i, j < sizeUpTo c (Nat.succ i) ∧ i < length c

Next tactic:
have length_pos : 0 < c.blocks.length := length_pos_of_sum_pos (blocks c) this
/-- `index_exists` asserts there is some `i` with `j < c.size_up_to (i+1)`.
In the next definition `index` we use `nat.find` to produce the minimal such index.
-/
theorem index_exists {j : ℕ} (h : j < n) : ∃ i : ℕ, j < c.sizeUpTo i.succ ∧ i < c.length := by
  have n_pos : 0 < n := lt_of_le_of_lt (zero_le j) h
  have : 0 < c.blocks.sum := by rwa [← c.blocks_sum] at n_pos
  have length_pos : 0 < c.blocks.length := length_pos_of_sum_pos (blocks c) this
  

Proof state:
n : ℕ
c : Composition n
j : ℕ
h : j < n
n_pos : 0 < n
this : 0 < sum c.blocks
length_pos : 0 < List.length c.blocks
⊢ ∃ i, j < sizeUpTo c (Nat.succ i) ∧ i < length c

Next tactic:
refine' ⟨c.length.pred, _, Nat.pred_lt (ne_of_gt length_pos)⟩
/-- `index_exists` asserts there is some `i` with `j < c.size_up_to (i+1)`.
In the next definition `index` we use `nat.find` to produce the minimal such index.
-/
theorem index_exists {j : ℕ} (h : j < n) : ∃ i : ℕ, j < c.sizeUpTo i.succ ∧ i < c.length := by
  have n_pos : 0 < n := lt_of_le_of_lt (zero_le j) h
  have : 0 < c.blocks.sum := by rwa [← c.blocks_sum] at n_pos
  have length_pos : 0 < c.blocks.length := length_pos_of_sum_pos (blocks c) this
  refine' ⟨c.length.pred, _, Nat.pred_lt (ne_of_gt length_pos)⟩
  

Proof state:
n : ℕ
c : Composition n
j : ℕ
h : j < n
n_pos : 0 < n
this : 0 < sum c.blocks
length_pos : 0 < List.length c.blocks
⊢ j < sizeUpTo c (Nat.succ (Nat.pred (length c)))

Next tactic:
have : c.length.pred.succ = c.length := Nat.succ_pred_eq_of_pos length_pos
/-- `index_exists` asserts there is some `i` with `j < c.size_up_to (i+1)`.
In the next definition `index` we use `nat.find` to produce the minimal such index.
-/
theorem index_exists {j : ℕ} (h : j < n) : ∃ i : ℕ, j < c.sizeUpTo i.succ ∧ i < c.length := by
  have n_pos : 0 < n := lt_of_le_of_lt (zero_le j) h
  have : 0 < c.blocks.sum := by rwa [← c.blocks_sum] at n_pos
  have length_pos : 0 < c.blocks.length := length_pos_of_sum_pos (blocks c) this
  refine' ⟨c.length.pred, _, Nat.pred_lt (ne_of_gt length_pos)⟩
  have : c.length.pred.succ = c.length := Nat.succ_pred_eq_of_pos length_pos
  

Proof state:
n : ℕ
c : Composition n
j : ℕ
h : j < n
n_pos : 0 < n
this✝ : 0 < sum c.blocks
length_pos : 0 < List.length c.blocks
this : Nat.succ (Nat.pred (length c)) = length c
⊢ j < sizeUpTo c (Nat.succ (Nat.pred (length c)))

Next tactic:
simp [this, h]
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
⊢ sizeUpTo c ↑(index c j) ≤ ↑j

Next tactic:
by_contra H
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
H : ¬sizeUpTo c ↑(index c j) ≤ ↑j
⊢ False

Next tactic:
set i := c.index j
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ¬sizeUpTo c ↑i ≤ ↑j
⊢ False

Next tactic:
push_neg at H
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
⊢ False

Next tactic:
have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    revert H
    simp [nonpos_iff_eq_zero.1 i_pos, c.sizeUpTo_zero]
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
⊢ 0 < ↑i

Next tactic:
by_contra! i_pos
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
i_pos : ↑i ≤ 0
⊢ False

Next tactic:
revert H
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    revert H
    

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
i_pos : ↑i ≤ 0
⊢ ↑j < sizeUpTo c ↑i → False

Next tactic:
simp [nonpos_iff_eq_zero.1 i_pos, c.sizeUpTo_zero]
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    revert H
    simp [nonpos_iff_eq_zero.1 i_pos, c.sizeUpTo_zero]
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
i_pos : 0 < ↑i
⊢ False

Next tactic:
let i₁ := (i : ℕ).pred
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    revert H
    simp [nonpos_iff_eq_zero.1 i_pos, c.sizeUpTo_zero]
  let i₁ := (i : ℕ).pred
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
i_pos : 0 < ↑i
i₁ : ℕ := Nat.pred ↑i
⊢ False

Next tactic:
have i₁_lt_i : i₁ < i := Nat.pred_lt (ne_of_gt i_pos)
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    revert H
    simp [nonpos_iff_eq_zero.1 i_pos, c.sizeUpTo_zero]
  let i₁ := (i : ℕ).pred
  have i₁_lt_i : i₁ < i := Nat.pred_lt (ne_of_gt i_pos)
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
i_pos : 0 < ↑i
i₁ : ℕ := Nat.pred ↑i
i₁_lt_i : i₁ < ↑i
⊢ False

Next tactic:
have i₁_succ : i₁.succ = i := Nat.succ_pred_eq_of_pos i_pos
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    revert H
    simp [nonpos_iff_eq_zero.1 i_pos, c.sizeUpTo_zero]
  let i₁ := (i : ℕ).pred
  have i₁_lt_i : i₁ < i := Nat.pred_lt (ne_of_gt i_pos)
  have i₁_succ : i₁.succ = i := Nat.succ_pred_eq_of_pos i_pos
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
i_pos : 0 < ↑i
i₁ : ℕ := Nat.pred ↑i
i₁_lt_i : i₁ < ↑i
i₁_succ : Nat.succ i₁ = ↑i
⊢ False

Next tactic:
have := Nat.find_min (c.index_exists j.2) i₁_lt_i
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    revert H
    simp [nonpos_iff_eq_zero.1 i_pos, c.sizeUpTo_zero]
  let i₁ := (i : ℕ).pred
  have i₁_lt_i : i₁ < i := Nat.pred_lt (ne_of_gt i_pos)
  have i₁_succ : i₁.succ = i := Nat.succ_pred_eq_of_pos i_pos
  have := Nat.find_min (c.index_exists j.2) i₁_lt_i
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
i_pos : 0 < ↑i
i₁ : ℕ := Nat.pred ↑i
i₁_lt_i : i₁ < ↑i
i₁_succ : Nat.succ i₁ = ↑i
this : ¬(↑j < sizeUpTo c (Nat.succ i₁) ∧ i₁ < length c)
⊢ False

Next tactic:
simp [lt_trans i₁_lt_i (c.index j).2, i₁_succ] at this
theorem sizeUpTo_index_le (j : Fin n) : c.sizeUpTo (c.index j) ≤ j := by
  by_contra H
  set i := c.index j
  push_neg at H
  have i_pos : (0 : ℕ) < i := by
    by_contra! i_pos
    revert H
    simp [nonpos_iff_eq_zero.1 i_pos, c.sizeUpTo_zero]
  let i₁ := (i : ℕ).pred
  have i₁_lt_i : i₁ < i := Nat.pred_lt (ne_of_gt i_pos)
  have i₁_succ : i₁.succ = i := Nat.succ_pred_eq_of_pos i_pos
  have := Nat.find_min (c.index_exists j.2) i₁_lt_i
  simp [lt_trans i₁_lt_i (c.index j).2, i₁_succ] at this
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c) := index c j
H : ↑j < sizeUpTo c ↑i
i_pos : 0 < ↑i
i₁ : ℕ := Nat.pred ↑i
i₁_lt_i : i₁ < ↑i
i₁_succ : Nat.succ i₁ = ↑i
this : sizeUpTo c ↑(index c j) ≤ ↑j
⊢ False

Next tactic:
exact Nat.lt_le_asymm H this
/-- Mapping an element `j` of `Fin n` to the element in the block containing it, identified with
`Fin (c.blocks_fun (c.index j))` through the canonical increasing bijection. -/
def invEmbedding (j : Fin n) : Fin (c.blocksFun (c.index j)) :=
  ⟨j - c.sizeUpTo (c.index j), by
    

Proof state:
n : ℕ
c : Composition n
j : Fin n
⊢ ↑j - sizeUpTo c ↑(index c j) < blocksFun c (index c j)

Next tactic:
rw [tsub_lt_iff_right, add_comm, ← sizeUpTo_succ']
/-- Mapping an element `j` of `Fin n` to the element in the block containing it, identified with
`Fin (c.blocks_fun (c.index j))` through the canonical increasing bijection. -/
def invEmbedding (j : Fin n) : Fin (c.blocksFun (c.index j)) :=
  ⟨j - c.sizeUpTo (c.index j), by
    rw [tsub_lt_iff_right, add_comm, ← sizeUpTo_succ']
    · 

Proof state:
n : ℕ
c : Composition n
j : Fin n
⊢ ↑j < sizeUpTo c (↑(index c j) + 1)

Next tactic:
exact lt_sizeUpTo_index_succ _ _
/-- Mapping an element `j` of `Fin n` to the element in the block containing it, identified with
`Fin (c.blocks_fun (c.index j))` through the canonical increasing bijection. -/
def invEmbedding (j : Fin n) : Fin (c.blocksFun (c.index j)) :=
  ⟨j - c.sizeUpTo (c.index j), by
    rw [tsub_lt_iff_right, add_comm, ← sizeUpTo_succ']
    · exact lt_sizeUpTo_index_succ _ _
    · 

Proof state:
n : ℕ
c : Composition n
j : Fin n
⊢ sizeUpTo c ↑(index c j) ≤ ↑j

Next tactic:
exact sizeUpTo_index_le _ _
theorem embedding_comp_inv (j : Fin n) : c.embedding (c.index j) (c.invEmbedding j) = j := by
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
⊢ (embedding c (index c j)) (invEmbedding c j) = j

Next tactic:
rw [Fin.ext_iff]
theorem embedding_comp_inv (j : Fin n) : c.embedding (c.index j) (c.invEmbedding j) = j := by
  rw [Fin.ext_iff]
  

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

Next tactic:
apply add_tsub_cancel_of_le (c.sizeUpTo_index_le j)
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
  

Proof state:
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
⊢ j ∈ Set.range ⇑(embedding c i) ↔ sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)

Next tactic:
constructor
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
  · 

Proof state:
case mp
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
⊢ j ∈ Set.range ⇑(embedding c i) → sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)

Next tactic:
intro h
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
    

Proof state:
case mp
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : j ∈ Set.range ⇑(embedding c i)
⊢ sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)

Next tactic:
rcases Set.mem_range.2 h with ⟨k, hk⟩
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⟩
    

Proof state:
case mp.intro
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : j ∈ Set.range ⇑(embedding c i)
k : Fin (blocksFun c i)
hk : (fun y => (embedding c i) y) k = j
⊢ sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)

Next tactic:
rw [Fin.ext_iff] at hk
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
    

Proof state:
case mp.intro
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : j ∈ Set.range ⇑(embedding c i)
k : Fin (blocksFun c i)
hk : ↑((fun y => (embedding c i) y) k) = ↑j
⊢ sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)

Next tactic:
dsimp at hk
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
    

Proof state:
case mp.intro
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : j ∈ Set.range ⇑(embedding c i)
k : Fin (blocksFun c i)
hk : sizeUpTo c ↑i + ↑k = ↑j
⊢ sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)

Next tactic:
rw [← hk]
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]
    

Proof state:
case mp.intro
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : j ∈ Set.range ⇑(embedding c i)
k : Fin (blocksFun c i)
hk : sizeUpTo c ↑i + ↑k = ↑j
⊢ sizeUpTo c ↑i ≤ sizeUpTo c ↑i + ↑k ∧ sizeUpTo c ↑i + ↑k < sizeUpTo c (Nat.succ ↑i)

Next tactic:
simp [sizeUpTo_succ', k.is_lt]
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]
  · 

Proof state:
case mpr
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
⊢ sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i) → 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) ↔ 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
    

Proof state:
case mpr
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)
⊢ j ∈ Set.range ⇑(embedding c i)

Next tactic:
apply Set.mem_range.2
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
    

Proof state:
case mpr
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)
⊢ ∃ y, (embedding c i) y = j

Next tactic:
refine' ⟨⟨j - c.sizeUpTo i, _⟩, _⟩
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, _⟩, _⟩
    · 

Proof state:
case mpr.refine'_1
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)
⊢ ↑j - sizeUpTo c ↑i < blocksFun c i

Next tactic:
rw [tsub_lt_iff_left, ← sizeUpTo_succ']
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']
      · 

Proof state:
case mpr.refine'_1
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)
⊢ ↑j < sizeUpTo c (↑i + 1)

Next tactic:
exact h.2
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
      · 

Proof state:
case mpr.refine'_1
n : ℕ
c : Composition n
j : Fin n
i : Fin (length c)
h : sizeUpTo c ↑i ≤ ↑j ∧ ↑j < sizeUpTo c (Nat.succ ↑i)
⊢ sizeUpTo c ↑i ≤ ↑j

Next tactic:
exact h.1