-- Mathlib/Combinatorics/HalesJewett.lean
theorem exists_mono_homothetic_copy {M κ : Type*} [AddCommMonoid M] (S : Finset M) [Finite κ]
    (C : M → κ) : ∃ a > 0, ∃ (b : M) (c : κ), ∀ s ∈ S, C (a • s + b) = c

Proof state:
case intro.intro.intro.intro.refine_3.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ s.card • x + ∑ i ∈ sᶜ, (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 = ∑ i : ι, ↑(↑l ⟨x, xs⟩ i)

Tactic:
rw [← Finset.sum_add_sum_compl s]

Result:
case intro.intro.intro.intro.refine_3.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ s.card • x + ∑ i ∈ sᶜ, (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 =
    ∑ i ∈ s, ↑(↑l ⟨x, xs⟩ i) + ∑ i ∈ sᶜ, ↑(↑l ⟨x, xs⟩ i)

Proof state:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
i : ι
hi : i ∈ sᶜ
⊢ (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 = ↑(↑l ⟨x, xs⟩ i)

Tactic:
rw [hs, Finset.compl_filter, Finset.mem_filter] at hi

Result:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
i : ι
hi : i ∈ Finset.univ ∧ ¬l.idxFun i = none
⊢ (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 = ↑(↑l ⟨x, xs⟩ i)

Proof state:
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
⊢ ∃ a > 0, ∃ b c, ∀ s ∈ S, C (a • s + b) = c

Tactic:
obtain ⟨ι, _inst, hι⟩ := Line.exists_mono_in_high_dimension S κ

Result:
case intro.intro
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
hι : ∀ (C : (ι → { x // x ∈ S }) → κ), ∃ l, Line.IsMono C l
⊢ ∃ a > 0, ∃ b c, ∀ s ∈ S, C (a • s + b) = c

Proof state:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ ∀ x_1 ∈ sᶜ, (Option.map (fun m => ↑m) (l.idxFun x_1)).getD 0 = ↑(↑l ⟨x, xs⟩ x_1)

Tactic:
intro i hi

Result:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
i : ι
hi : i ∈ sᶜ
⊢ (Option.map (fun m => ↑m) (l.idxFun i)).getD 0 = ↑(↑l ⟨x, xs⟩ i)

Proof state:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ ∑ _x ∈ s, x = ∑ i ∈ s, ↑(↑l ⟨x, xs⟩ i)

Tactic:
apply Finset.sum_congr rfl

Result:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ ∀ x_1 ∈ s, x = ↑(↑l ⟨x, xs⟩ x_1)

Proof state:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
⊢ ∀ x_1 ∈ s, x = ↑(↑l ⟨x, xs⟩ x_1)

Tactic:
intro i hi

Result:
case intro.intro.intro.intro.refine_3.e_a.e_a
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
x : M
xs : x ∈ S
i : ι
hi : i ∈ s
⊢ x = ↑(↑l ⟨x, xs⟩ i)

Proof state:
case intro.intro.intro.intro
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
hl : ∀ (x : { x // x ∈ S }), (fun v => C (∑ i : ι, ↑(v i))) (↑l x) = c
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
⊢ ∃ a > 0, ∃ b c, ∀ s ∈ S, C (a • s + b) = c

Tactic:
refine
  ⟨s.card, Finset.card_pos.mpr ⟨l.proper.choose, ?_⟩, ∑ i ∈ sᶜ, ((l.idxFun i).map ?_).getD 0,
    c, ?_⟩

Result:
case intro.intro.intro.intro.refine_1
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
hl : ∀ (x : { x // x ∈ S }), (fun v => C (∑ i : ι, ↑(v i))) (↑l x) = c
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
⊢ ⋯.choose ∈ s

case intro.intro.intro.intro.refine_2
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
hl : ∀ (x : { x // x ∈ S }), (fun v => C (∑ i : ι, ↑(v i))) (↑l x) = c
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
i : ι
⊢ { x // x ∈ S } → M

case intro.intro.intro.intro.refine_3
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
hl : ∀ (x : { x // x ∈ S }), (fun v => C (∑ i : ι, ↑(v i))) (↑l x) = c
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
⊢ ∀ s_1 ∈ S, C (s.card • s_1 + ∑ i ∈ sᶜ, (Option.map ?intro.intro.intro.intro.refine_2 (l.idxFun i)).getD 0) = c

Proof state:
case intro.intro.intro.intro.refine_2
M : Type u_5
κ : Type u_6
inst✝¹ : AddCommMonoid M
S : Finset M
inst✝ : Finite κ
C : M → κ
ι : Type
_inst : Fintype ι
l : Line { x // x ∈ S } ι
c : κ
hl : ∀ (x : { x // x ∈ S }), (fun v => C (∑ i : ι, ↑(v i))) (↑l x) = c
s : Finset ι := Finset.filter (fun i => l.idxFun i = none) Finset.univ
hs : s = Finset.filter (fun i => l.idxFun i = none) Finset.univ
i : ι
⊢ { x // x ∈ S } → M

Tactic:
exact fun m => m

Result:
no goals