Theorem: PseudoMetricSpace.le_two_mul_dist_ofPreNNDist
File: Mathlib/Topology/MetricSpace/MetrizableUniformity.lean

tactic: rw [dist_ofPreNNDist, ← NNReal.coe_two, ← NNReal.coe_mul, NNReal.mul_iInf, NNReal.coe_le_coe]
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x y : X
⊢ ↑(d x y) ≤ 2 * dist x y

tactic: refine' le_ciInf fun l => _
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x y : X
⊢ d x y ≤ ⨅ (i : List X), 2 * sum (zipWith d (x :: i) (i ++ [y]))

tactic: have hd₀_trans : Transitive fun x y => d x y = 0 := by
  intro a b c hab hbc
  rw [← nonpos_iff_eq_zero]
  simpa only [nonpos_iff_eq_zero, hab, hbc, dist_self c, max_self, mul_zero] using hd a b c c
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x y : X
l : List X
⊢ d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))

tactic: haveI : IsTrans X fun x y => d x y = 0 := ⟨hd₀_trans⟩
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x y : X
l : List X
hd₀_trans : Transitive fun x y => d x y = 0
⊢ d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))

tactic: induction' hn : length l using Nat.strong_induction_on with n ihn generalizing x y l
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x y : X
l : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
⊢ d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))

tactic: simp only at ihn
state_before: case h
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn✝ : length l✝ = x✝
n : ℕ
ihn : ∀ (m : ℕ), m < n → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
x y : X
l : List X
hn : length l = n
⊢ d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))

tactic: subst n
state_before: case h
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn✝ : length l✝ = x✝
n : ℕ
ihn : ∀ (m : ℕ), m < n → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
x y : X
l : List X
hn : length l = n
⊢ d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))

tactic: set L := zipWith d (x::l) (l ++ [y])
state_before: case h
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
⊢ d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))

tactic: have hL_len : length L = length l + 1 := by simp
state_before: case h
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
⊢ d x y ≤ 2 * sum L

tactic: cases' eq_or_ne (d x y) 0 with hd₀ hd₀
state_before: case h
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
⊢ d x y ≤ 2 * sum L

tactic: rsuffices ⟨z, z', hxz, hzz', hz'y⟩ : ∃ z z' : X, d x z ≤ L.sum ∧ d z z' ≤ L.sum ∧ d z' y ≤ L.sum
state_before: case h.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
⊢ d x y ≤ 2 * sum L

tactic: set s : Set ℕ := { m : ℕ | 2 * (take m L).sum ≤ L.sum }
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
⊢ ∃ z z', d x z ≤ sum L ∧ d z z' ≤ sum L ∧ d z' y ≤ sum L

tactic: have hs₀ : 0 ∈ s := by simp
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
⊢ ∃ z z', d x z ≤ sum L ∧ d z z' ≤ sum L ∧ d z' y ≤ sum L

tactic: have hsne : s.Nonempty := ⟨0, hs₀⟩
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
⊢ ∃ z z', d x z ≤ sum L ∧ d z z' ≤ sum L ∧ d z' y ≤ sum L

tactic: obtain ⟨M, hMl, hMs⟩ : ∃ M ≤ length l, IsGreatest s M := by
  have hs_ub : length l ∈ upperBounds s := by
    intro m hm
    rw [← not_lt, Nat.lt_iff_add_one_le, ← hL_len]
    intro hLm
    rw [mem_setOf_eq, take_all_of_le hLm, two_mul, add_le_iff_nonpos_left, nonpos_iff_eq_zero,
        sum_eq_zero_iff, ← all₂_iff_forall, all₂_zipWith, ← chain_append_singleton_iff_forall₂]
        at hm <;>
      [skip; simp]
    exact hd₀ (hm.rel (mem_append.2 <| Or.inr <| mem_singleton_self _))
  have hs_bdd : BddAbove s := ⟨length l, hs_ub⟩
  exact ⟨sSup s, csSup_le hsne hs_ub, ⟨Nat.sSup_mem hsne hs_bdd, fun k => le_csSup hs_bdd⟩⟩
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
⊢ ∃ z z', d x z ≤ sum L ∧ d z z' ≤ sum L ∧ d z' y ≤ sum L

tactic: have hM_lt : M < length L := by rwa [hL_len, Nat.lt_succ_iff]
state_before: case intro.intro
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M ≤ length l
hMs : IsGreatest s M
⊢ ∃ z z', d x z ≤ sum L ∧ d z z' ≤ sum L ∧ d z' y ≤ sum L

tactic: have hM_ltx : M < length (x::l) := lt_length_left_of_zipWith hM_lt
state_before: case intro.intro
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
⊢ ∃ z z', d x z ≤ sum L ∧ d z z' ≤ sum L ∧ d z' y ≤ sum L

tactic: have hM_lty : M < length (l ++ [y]) := lt_length_right_of_zipWith hM_lt
state_before: case intro.intro
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
⊢ ∃ z z', d x z ≤ sum L ∧ d z z' ≤ sum L ∧ d z' y ≤ sum L

tactic: refine' ⟨(x::l).get ⟨M, hM_ltx⟩, (l ++ [y]).get ⟨M, hM_lty⟩, _, _, _⟩
state_before: case intro.intro
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
⊢ ∃ z z', d x z ≤ sum L ∧ d z z' ≤ sum L ∧ d z' y ≤ sum L

tactic: intro a b c hab hbc
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x y : X
l : List X
⊢ Transitive fun x y => d x y = 0

tactic: rw [← nonpos_iff_eq_zero]
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x y : X
l : List X
a b c : X
hab : d a b = 0
hbc : d b c = 0
⊢ d a c = 0

tactic: simpa only [nonpos_iff_eq_zero, hab, hbc, dist_self c, max_self, mul_zero] using hd a b c c
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x y : X
l : List X
a b c : X
hab : d a b = 0
hbc : d b c = 0
⊢ d a c ≤ 0

tactic: simp
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
⊢ length L = length l + 1

tactic: simp only [hd₀, zero_le]
state_before: case h.inl
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y = 0
⊢ d x y ≤ 2 * sum L

tactic: exact (hd x z z' y).trans (mul_le_mul_left' (max_le hxz (max_le hzz' hz'y)) _)
state_before: case h.inr.intro.intro.intro.intro
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
z z' : X
hxz : d x z ≤ sum L
hzz' : d z z' ≤ sum L
hz'y : d z' y ≤ sum L
⊢ d x y ≤ 2 * sum L

tactic: simp
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
⊢ 0 ∈ s

tactic: have hs_ub : length l ∈ upperBounds s := by
  intro m hm
  rw [← not_lt, Nat.lt_iff_add_one_le, ← hL_len]
  intro hLm
  rw [mem_setOf_eq, take_all_of_le hLm, two_mul, add_le_iff_nonpos_left, nonpos_iff_eq_zero,
      sum_eq_zero_iff, ← all₂_iff_forall, all₂_zipWith, ← chain_append_singleton_iff_forall₂]
      at hm <;>
    [skip; simp]
  exact hd₀ (hm.rel (mem_append.2 <| Or.inr <| mem_singleton_self _))
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
⊢ ∃ M, M ≤ length l ∧ IsGreatest s M

tactic: have hs_bdd : BddAbove s := ⟨length l, hs_ub⟩
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
hs_ub : length l ∈ upperBounds s
⊢ ∃ M, M ≤ length l ∧ IsGreatest s M

tactic: exact ⟨sSup s, csSup_le hsne hs_ub, ⟨Nat.sSup_mem hsne hs_bdd, fun k => le_csSup hs_bdd⟩⟩
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
hs_ub : length l ∈ upperBounds s
hs_bdd : BddAbove s
⊢ ∃ M, M ≤ length l ∧ IsGreatest s M

tactic: intro m hm
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
⊢ length l ∈ upperBounds s

tactic: rw [← not_lt, Nat.lt_iff_add_one_le, ← hL_len]
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
m : ℕ
hm : m ∈ s
⊢ m ≤ length l

tactic: intro hLm
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
m : ℕ
hm : m ∈ s
⊢ ¬length L ≤ m

tactic: rw [mem_setOf_eq, take_all_of_le hLm, two_mul, add_le_iff_nonpos_left, nonpos_iff_eq_zero,
    sum_eq_zero_iff, ← all₂_iff_forall, all₂_zipWith, ← chain_append_singleton_iff_forall₂]
    at hm <;>
  [skip; simp]
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
m : ℕ
hm : m ∈ s
hLm : length L ≤ m
⊢ False

tactic: exact hd₀ (hm.rel (mem_append.2 <| Or.inr <| mem_singleton_self _))
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
m : ℕ
hm : Chain (fun x y => d x y = 0) x (l ++ [y])
hLm : length L ≤ m
⊢ False

tactic: rwa [hL_len, Nat.lt_succ_iff]
state_before: X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M ≤ length l
hMs : IsGreatest s M
⊢ M < length L

tactic: cases M with
| zero =>
  simp [dist_self, List.get]
| succ M =>
  rw [Nat.succ_le_iff] at hMl
  have hMl' : length (take M l) = M := (length_take _ _).trans (min_eq_left hMl.le)
  simp only [List.get]
  refine' (ihn _ hMl _ _ _ hMl').trans _
  convert hMs.1.out
  rw [zipWith_distrib_take, take, take_succ, get?_append hMl, get?_eq_get hMl, ← Option.coe_def,
    Option.to_list_some, take_append_of_le_length hMl.le]
state_before: case intro.intro.refine'_1
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
⊢ d x (List.get (x :: l) { val := M, isLt := hM_ltx }) ≤ sum L

tactic: simp [dist_self, List.get]
state_before: case intro.intro.refine'_1.zero
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
hMl : Nat.zero ≤ length l
hMs : IsGreatest s Nat.zero
hM_lt : Nat.zero < length L
hM_ltx : Nat.zero < length (x :: l)
hM_lty : Nat.zero < length (l ++ [y])
⊢ d x (List.get (x :: l) { val := Nat.zero, isLt := hM_ltx }) ≤ sum L

tactic: rw [Nat.succ_le_iff] at hMl
state_before: case intro.intro.refine'_1.succ
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : Nat.succ M ≤ length l
hMs : IsGreatest s (Nat.succ M)
hM_lt : Nat.succ M < length L
hM_ltx : Nat.succ M < length (x :: l)
hM_lty : Nat.succ M < length (l ++ [y])
⊢ d x (List.get (x :: l) { val := Nat.succ M, isLt := hM_ltx }) ≤ sum L

tactic: have hMl' : length (take M l) = M := (length_take _ _).trans (min_eq_left hMl.le)
state_before: case intro.intro.refine'_1.succ
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M < length l
hMs : IsGreatest s (Nat.succ M)
hM_lt : Nat.succ M < length L
hM_ltx : Nat.succ M < length (x :: l)
hM_lty : Nat.succ M < length (l ++ [y])
⊢ d x (List.get (x :: l) { val := Nat.succ M, isLt := hM_ltx }) ≤ sum L

tactic: simp only [List.get]
state_before: case intro.intro.refine'_1.succ
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M < length l
hMs : IsGreatest s (Nat.succ M)
hM_lt : Nat.succ M < length L
hM_ltx : Nat.succ M < length (x :: l)
hM_lty : Nat.succ M < length (l ++ [y])
hMl' : length (take M l) = M
⊢ d x (List.get (x :: l) { val := Nat.succ M, isLt := hM_ltx }) ≤ sum L

tactic: refine' (ihn _ hMl _ _ _ hMl').trans _
state_before: case intro.intro.refine'_1.succ
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M < length l
hMs : IsGreatest s (Nat.succ M)
hM_lt : Nat.succ M < length L
hM_ltx : Nat.succ M < length (x :: l)
hM_lty : Nat.succ M < length (l ++ [y])
hMl' : length (take M l) = M
⊢ d x (List.get l { val := M, isLt := (_ : Nat.succ M ≤ length l) }) ≤ sum (zipWith d (x :: l) (l ++ [y]))

tactic: convert hMs.1.out
state_before: case intro.intro.refine'_1.succ
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M < length l
hMs : IsGreatest s (Nat.succ M)
hM_lt : Nat.succ M < length L
hM_ltx : Nat.succ M < length (x :: l)
hM_lty : Nat.succ M < length (l ++ [y])
hMl' : length (take M l) = M
⊢ 2 * sum (zipWith d (x :: take M l) (take M l ++ [List.get l { val := M, isLt := (_ : Nat.succ M ≤ length l) }])) ≤
    sum (zipWith d (x :: l) (l ++ [y]))

tactic: rw [zipWith_distrib_take, take, take_succ, get?_append hMl, get?_eq_get hMl, ← Option.coe_def,
  Option.to_list_some, take_append_of_le_length hMl.le]
state_before: case h.e'_3.h.e'_6.h.e'_4
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M < length l
hMs : IsGreatest s (Nat.succ M)
hM_lt : Nat.succ M < length L
hM_ltx : Nat.succ M < length (x :: l)
hM_lty : Nat.succ M < length (l ++ [y])
hMl' : length (take M l) = M
⊢ zipWith d (x :: take M l) (take M l ++ [List.get l { val := M, isLt := (_ : Nat.succ M ≤ length l) }]) =
    take (Nat.succ M) L

tactic: exact single_le_sum (fun x _ => zero_le x) _ (mem_iff_get.2 ⟨⟨M, hM_lt⟩, get_zipWith⟩)
state_before: case intro.intro.refine'_2
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
⊢ d (List.get (x :: l) { val := M, isLt := hM_ltx }) (List.get (l ++ [y]) { val := M, isLt := hM_lty }) ≤ sum L

tactic: rcases hMl.eq_or_lt with (rfl | hMl)
state_before: case intro.intro.refine'_3
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
⊢ d (List.get (l ++ [y]) { val := M, isLt := hM_lty }) y ≤ sum L

tactic: rw [get_append _ hMl]
state_before: case intro.intro.refine'_3.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
⊢ d (List.get (l ++ [y]) { val := M, isLt := hM_lty }) y ≤ sum L

tactic: have hlen : length (drop (M + 1) l) = length l - (M + 1) := length_drop _ _
state_before: case intro.intro.refine'_3.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
⊢ d (List.get l { val := M, isLt := hMl }) y ≤ sum L

tactic: have hlen_lt : length l - (M + 1) < length l := Nat.sub_lt_of_pos_le _ _ M.succ_pos hMl
state_before: case intro.intro.refine'_3.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
hlen : length (drop (M + 1) l) = length l - (M + 1)
⊢ d (List.get l { val := M, isLt := hMl }) y ≤ sum L

tactic: refine' (ihn _ hlen_lt _ y _ hlen).trans _
state_before: case intro.intro.refine'_3.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
hlen : length (drop (M + 1) l) = length l - (M + 1)
hlen_lt : length l - (M + 1) < length l
⊢ d (List.get l { val := M, isLt := hMl }) y ≤ sum L

tactic: rw [cons_get_drop_succ]
state_before: case intro.intro.refine'_3.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
hlen : length (drop (M + 1) l) = length l - (M + 1)
hlen_lt : length l - (M + 1) < length l
⊢ 2 * sum (zipWith d (List.get l { val := M, isLt := hMl } :: drop (M + 1) l) (drop (M + 1) l ++ [y])) ≤ sum L

tactic: have hMs' : L.sum ≤ 2 * (L.take (M + 1)).sum :=
  not_lt.1 fun h => (hMs.2 h.le).not_lt M.lt_succ_self
state_before: case intro.intro.refine'_3.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
hlen : length (drop (M + 1) l) = length l - (M + 1)
hlen_lt : length l - (M + 1) < length l
⊢ 2 * sum (zipWith d (drop (↑{ val := M, isLt := hMl }) l) (drop (M + 1) l ++ [y])) ≤ sum L

tactic: rw [← sum_take_add_sum_drop L (M + 1), two_mul, add_le_add_iff_left, ← add_le_add_iff_right,
  sum_take_add_sum_drop, ← two_mul] at hMs'
state_before: case intro.intro.refine'_3.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
hlen : length (drop (M + 1) l) = length l - (M + 1)
hlen_lt : length l - (M + 1) < length l
hMs' : sum L ≤ 2 * sum (take (M + 1) L)
⊢ 2 * sum (zipWith d (drop (↑{ val := M, isLt := hMl }) l) (drop (M + 1) l ++ [y])) ≤ sum L

tactic: convert hMs'
state_before: case intro.intro.refine'_3.inr
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
hlen : length (drop (M + 1) l) = length l - (M + 1)
hlen_lt : length l - (M + 1) < length l
hMs'✝ : sum (drop (M + 1) L) ≤ sum (take (M + 1) L)
hMs' : 2 * sum (drop (M + 1) L) ≤ sum L
⊢ 2 * sum (zipWith d (drop (↑{ val := M, isLt := hMl }) l) (drop (M + 1) l ++ [y])) ≤ sum L

tactic: rwa [zipWith_distrib_drop, drop, drop_append_of_le_length]
state_before: case h.e'_3.h.e'_6.h.e'_4
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
M : ℕ
hMl✝ : M ≤ length l
hMs : IsGreatest s M
hM_lt : M < length L
hM_ltx : M < length (x :: l)
hM_lty : M < length (l ++ [y])
hMl : M < length l
hlen : length (drop (M + 1) l) = length l - (M + 1)
hlen_lt : length l - (M + 1) < length l
hMs'✝ : sum (drop (M + 1) L) ≤ sum (take (M + 1) L)
hMs' : 2 * sum (drop (M + 1) L) ≤ sum L
⊢ zipWith d (drop (↑{ val := M, isLt := hMl }) l) (drop (M + 1) l ++ [y]) = drop (M + 1) L

tactic: simp only [get_append_right' le_rfl, sub_self, get_singleton, dist_self, zero_le]
state_before: case intro.intro.refine'_3.inl
X : Type u_1
d : X → X → ℝ≥0
dist_self : ∀ (x : X), d x x = 0
dist_comm : ∀ (x y : X), d x y = d y x
hd : ∀ (x₁ x₂ x₃ x₄ : X), d x₁ x₄ ≤ 2 * max (d x₁ x₂) (max (d x₂ x₃) (d x₃ x₄))
x✝¹ y✝ : X
l✝ : List X
hd₀_trans : Transitive fun x y => d x y = 0
this : IsTrans X fun x y => d x y = 0
x✝ : ℕ
hn : length l✝ = x✝
x y : X
l : List X
ihn : ∀ (m : ℕ), m < length l → ∀ (x y : X) (l : List X), length l = m → d x y ≤ 2 * sum (zipWith d (x :: l) (l ++ [y]))
L : List ℝ≥0 := zipWith d (x :: l) (l ++ [y])
hL_len : length L = length l + 1
hd₀ : d x y ≠ 0
s : Set ℕ := {m | 2 * sum (take m L) ≤ sum L}
hs₀ : 0 ∈ s
hsne : Set.Nonempty s
hMl : length l ≤ length l
hMs : IsGreatest s (length l)
hM_lt : length l < length L
hM_ltx : length l < length (x :: l)
hM_lty : length l < length (l ++ [y])
⊢ d (List.get (l ++ [y]) { val := length l, isLt := hM_lty }) y ≤ sum L