import Mathlib
import Optlib


open Set Real

open Set Real PNat

theorem extracted_formal_statement_16.{u_1} {E : Type u_1} [inst : NormedAddCommGroup E] [inst_1 : InnerProductSpace ℝ E]
  [inst_2 : CompleteSpace E] {f h : E → ℝ} {f' : E → E} {x0 : E} {alg : Nesterov_first f h f' x0} {xm : E}
  (minφ : IsMinOn (f + h) univ xm)
  (h1 :
    ∀ (k : ℕ),
      Nesterov_first.y f h f' x0 k - Nesterov_first.x f h f' x0 (k + 1) -
          Nesterov_first.t f h f' x0 k • f' (Nesterov_first.y f h f' x0 k) ∈
        SubderivAt (Nesterov_first.t f h f' x0 k • h) (Nesterov_first.x f h f' x0 (k + 1)))
  (hieq1 :
    ∀ (z : E) (k : ℕ),
      Nesterov_first.t f h f' x0 k * h (Nesterov_first.x f h f' x0 (k + 1)) +
          inner
            (Nesterov_first.y f h f' x0 k - Nesterov_first.x f h f' x0 (k + 1) -
              Nesterov_first.t f h f' x0 k • f' (Nesterov_first.y f h f' x0 k))
            (z - Nesterov_first.x f h f' x0 (k + 1)) ≤
        Nesterov_first.t f h f' x0 k * h z)
  (hieq2 :
    ∀ (z : E) (k : ℕ),
      h (Nesterov_first.x f h f' x0 (k + 1)) ≤
        h z +
          inner
            (f' (Nesterov_first.y f h f' x0 k) +
              (1 / Nesterov_first.t f h f' x0 k) • (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k))
            (z - Nesterov_first.x f h f' x0 (k + 1)))
  (fieq1 :
    ∀ (k : ℕ) (x y : E), f x ≤ f y + inner (f' y) (x - y) + 1 / (2 * Nesterov_first.t f h f' x0 k) * ‖x - y‖ ^ 2) :
  let φ := fun z => f z + h z;
  (∀ (z : E) (k : ℕ),
      φ (Nesterov_first.x f h f' x0 (k + 1)) ≤
        φ z +
            1 / Nesterov_first.t f h f' x0 k *
              inner (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k)
                (z - Nesterov_first.x f h f' x0 (k + 1)) +
          1 / (2 * Nesterov_first.t f h f' x0 k) *
            ‖Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k‖ ^ 2) →
    ∀ (k : ℕ),
      φ (Nesterov_first.x f h f' x0 (k + 1)) ≤
          φ (Nesterov_first.x f h f' x0 k) +
              (1 / Nesterov_first.t f h f' x0 k) •
                inner (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k)
                  (Nesterov_first.x f h f' x0 k - Nesterov_first.x f h f' x0 (k + 1)) +
            1 / (2 * Nesterov_first.t f h f' x0 k) *
              ‖Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k‖ ^ 2 →
        φ (Nesterov_first.x f h f' x0 (k + 1)) ≤
            φ xm +
                (1 / Nesterov_first.t f h f' x0 k) •
                  inner (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k)
                    (xm - Nesterov_first.x f h f' x0 (k + 1)) +
              1 / (2 * Nesterov_first.t f h f' x0 k) *
                ‖Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k‖ ^ 2 →
          φ (Nesterov_first.x f h f' x0 (k + 1)) - φ xm -
              (1 - Nesterov_first.γ f h f' x0 k) * (φ (Nesterov_first.x f h f' x0 k) - φ xm) ≤
            1 / Nesterov_first.t f h f' x0 k *
                inner (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k)
                  ((1 - Nesterov_first.γ f h f' x0 k) • Nesterov_first.x f h f' x0 k +
                      Nesterov_first.γ f h f' x0 k • xm -
                    Nesterov_first.x f h f' x0 (k + 1)) +
              1 / (2 * Nesterov_first.t f h f' x0 k) *
                ‖Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k‖ ^ 2 := sorry

Tactic state before:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : CompleteSpace E
f h : E → ℝ
f' : E → E
x0 : E
alg : Nesterov_first f h f' x0
xm : E
minφ : IsMinOn (f + h) univ xm
h1 :
  ∀ (k : ℕ),
    Nesterov_first.y f h f' x0 k - Nesterov_first.x f h f' x0 (k + 1) -
        Nesterov_first.t f h f' x0 k • f' (Nesterov_first.y f h f' x0 k) ∈
      SubderivAt (Nesterov_first.t f h f' x0 k • h) (Nesterov_first.x f h f' x0 (k + 1))
hieq1 :
  ∀ (z : E) (k : ℕ),
    Nesterov_first.t f h f' x0 k * h (Nesterov_first.x f h f' x0 (k + 1)) +
        inner
          (Nesterov_first.y f h f' x0 k - Nesterov_first.x f h f' x0 (k + 1) -
            Nesterov_first.t f h f' x0 k • f' (Nesterov_first.y f h f' x0 k))
          (z - Nesterov_first.x f h f' x0 (k + 1)) ≤
      Nesterov_first.t f h f' x0 k * h z
hieq2 :
  ∀ (z : E) (k : ℕ),
    h (Nesterov_first.x f h f' x0 (k + 1)) ≤
      h z +
        inner
          (f' (Nesterov_first.y f h f' x0 k) +
            (1 / Nesterov_first.t f h f' x0 k) • (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k))
          (z - Nesterov_first.x f h f' x0 (k + 1))
fieq1 : ∀ (k : ℕ) (x y : E), f x ≤ f y + inner (f' y) (x - y) + 1 / (2 * Nesterov_first.t f h f' x0 k) * ‖x - y‖ ^ 2
φ : E → ℝ := fun z => f z + h z
φieq2 :
  ∀ (z : E) (k : ℕ),
    φ (Nesterov_first.x f h f' x0 (k + 1)) ≤
      φ z +
          1 / Nesterov_first.t f h f' x0 k *
            inner (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k)
              (z - Nesterov_first.x f h f' x0 (k + 1)) +
        1 / (2 * Nesterov_first.t f h f' x0 k) * ‖Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k‖ ^ 2
k : ℕ
ieq1 :
  φ (Nesterov_first.x f h f' x0 (k + 1)) ≤
    φ (Nesterov_first.x f h f' x0 k) +
        (1 / Nesterov_first.t f h f' x0 k) •
          inner (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k)
            (Nesterov_first.x f h f' x0 k - Nesterov_first.x f h f' x0 (k + 1)) +
      1 / (2 * Nesterov_first.t f h f' x0 k) * ‖Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k‖ ^ 2
ieq2 :
  φ (Nesterov_first.x f h f' x0 (k + 1)) ≤
    φ xm +
        (1 / Nesterov_first.t f h f' x0 k) •
          inner (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k)
            (xm - Nesterov_first.x f h f' x0 (k + 1)) +
      1 / (2 * Nesterov_first.t f h f' x0 k) * ‖Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k‖ ^ 2
⊢ φ (Nesterov_first.x f h f' x0 (k + 1)) - φ xm -
      (1 - Nesterov_first.γ f h f' x0 k) * (φ (Nesterov_first.x f h f' x0 k) - φ xm) ≤
    1 / Nesterov_first.t f h f' x0 k *
        inner (Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k)
          ((1 - Nesterov_first.γ f h f' x0 k) • Nesterov_first.x f h f' x0 k + Nesterov_first.γ f h f' x0 k • xm -
            Nesterov_first.x f h f' x0 (k + 1)) +
      1 / (2 * Nesterov_first.t f h f' x0 k) * ‖Nesterov_first.x f h f' x0 (k + 1) - Nesterov_first.y f h f' x0 k‖ ^ 2

Tactic:
rw [add_rotate, ← sub_le_iff_le_add] at ieq1
    rw [add_rotate, ← sub_le_iff_le_add] at ieq2
    calc
  φ (alg.x (k + 1)) - φ xm - (1 - alg.γ k) * (φ (alg.x k) - φ xm) =
      (alg.γ k) * (φ (alg.x (k + 1)) - φ xm) + (1 - alg.γ k) * (φ (alg.x (k + 1)) - φ (alg.x k)) :=
    by
    to_theorem
      rw [mul_sub, mul_sub, mul_sub, sub_add_sub_comm, ← add_mul,
        add_comm
          (alg.γ k)]rw [sub_add_cancel, one_mul, ← sub_add, sub_add_eq_add_sub, sub_add]nth_rw 1 [← one_mul (φ xm)];
    rw [← sub_mul, sub_sub_cancel, sub_sub]
  _ ≤
      (alg.γ k) *
          ((1 / alg.t k) • ⟪alg.x (k + 1) - alg.y k, xm - alg.x (k + 1)⟫ +
            1 / (2 * alg.t k) * ‖alg.x (k + 1) - alg.y k‖ ^ 2) +
        (1 - alg.γ k) *
          ((1 / alg.t k) • ⟪alg.x (k + 1) - alg.y k, alg.x k - alg.x (k + 1)⟫ +
            1 / (2 * alg.t k) * ‖alg.x (k + 1) - alg.y k‖ ^ 2) :=
    by
    to_theorem
      apply
        add_le_add· rw [mul_le_mul_left]; exact ieq2;
        linarith [(alg.γbound k).1]· apply mul_le_mul_of_nonneg_left; exact ieq1; linarith [(alg.γbound k).2]
  _ =
      (alg.γ k) * (1 / alg.t k) * ⟪alg.x (k + 1) - alg.y k, xm - alg.x (k + 1)⟫ +
          (1 - alg.γ k) * (1 / alg.t k) * ⟪alg.x (k + 1) - alg.y k, alg.x k - alg.x (k + 1)⟫ +
        1 / (2 * alg.t k) * ‖alg.x (k + 1) - alg.y k‖ ^ 2 :=
    by
    rw [mul_add, mul_add, add_add_add_comm, ← add_mul, add_sub_cancel]
    rw [smul_eq_mul, smul_eq_mul, ← mul_assoc, ← mul_assoc, one_mul]
  _ =
      1 / (alg.t k) * ⟪alg.x (k + 1) - alg.y k, (1 - alg.γ k) • (alg.x k) + (alg.γ k) • xm - alg.x (k + 1)⟫ +
        1 / (2 * alg.t k) * ‖alg.x (k + 1) - alg.y k‖ ^ 2 :=
    by
    to_theorem
      rw [add_right_cancel_iff, mul_comm (alg.γ k),
        mul_comm
          (1 -
            alg.γ k)]rw [mul_assoc, mul_assoc, ← mul_add, ← inner_smul_right, ← inner_smul_right]rw [← inner_add_right]
    rw [smul_sub, smul_sub, sub_add_sub_comm, ← add_smul, add_comm (alg.γ k)]
    rw [sub_add_cancel, one_smul, add_comm (alg.γ k • xm)]

Tactic state after: