import Mathlib
import Optlib


open Set

theorem extracted_formal_statement_64.{u_1} {E : Type u_1} [inst : NormedAddCommGroup E] [inst_1 : InnerProductSpace ℝ E]
  [inst_2 : CompleteSpace E] [inst_3 : ProperSpace E] {x₀ : E} {f : E → ℝ} {f' : E → E} {h : E → ℝ}
  {alg : proximal_gradient_method f h f' x₀} (th : ContinuousOn (proximal_gradient_method.t f h f' x₀ • h) univ)
  (th' : ConvexOn ℝ univ (proximal_gradient_method.t f h f' x₀ • h)) :
  let Gt := fun x =>
    (1 / proximal_gradient_method.t f h f' x₀) •
      (x -
        prox_point_c' (proximal_gradient_method.t f h f' x₀ • h) (x - proximal_gradient_method.t f h f' x₀ • f' x) th
          th');
  let φ := fun x => f x + h x;
  (∀ (z : E), Gt z - f' z ∈ SubderivAt h (z - proximal_gradient_method.t f h f' x₀ • Gt z)) →
    (∀ (x : E),
        f (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
          f x - proximal_gradient_method.t f h f' x₀ * inner (f' x) (Gt x) +
            proximal_gradient_method.t f h f' x₀ ^ 2 * ↑(proximal_gradient_method.L f h f' x₀) / 2 * ‖Gt x‖ ^ 2) →
      (∀ (x : E),
          f (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
            f x - proximal_gradient_method.t f h f' x₀ * inner (f' x) (Gt x) +
              proximal_gradient_method.t f h f' x₀ / 2 * ‖Gt x‖ ^ 2) →
        (∀ (x z : E), f x + inner (f' x) (z - x) ≤ f z) →
          (∀ (x z : E),
              h (x - proximal_gradient_method.t f h f' x₀ • Gt x) +
                  inner (Gt x - f' x) (z - x + proximal_gradient_method.t f h f' x₀ • Gt x) ≤
                h z) →
            (∀ (x z : E),
                h (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
                  h z - inner (Gt x - f' x) (z - x + proximal_gradient_method.t f h f' x₀ • Gt x)) →
              (∀ (x z : E),
                  φ (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
                    φ z + inner (Gt x) (x - z) - proximal_gradient_method.t f h f' x₀ / 2 * ‖Gt x‖ ^ 2) →
                (∀ (x : E),
                    φ (x - proximal_gradient_method.t f h f' x₀ • Gt x) - φ (proximal_gradient_method.xm f h f' x₀) ≤
                      1 / (2 * proximal_gradient_method.t f h f' x₀) *
                        (‖x - proximal_gradient_method.xm f h f' x₀‖ ^ 2 -
                          ‖x - proximal_gradient_method.t f h f' x₀ • Gt x - proximal_gradient_method.xm f h f' x₀‖ ^
                            2)) →
                  (∀ (i : ℕ),
                      proximal_gradient_method.x f h f' x₀ (i + 1) =
                        proximal_gradient_method.x f h f' x₀ i -
                          proximal_gradient_method.t f h f' x₀ • Gt (proximal_gradient_method.x f h f' x₀ i)) →
                    (∀ (i : ℕ),
                        φ (proximal_gradient_method.x f h f' x₀ (i + 1)) ≤ φ (proximal_gradient_method.x f h f' x₀ i)) →
                      (∀ (i j : ℕ),
                          i ≤ j →
                            φ (proximal_gradient_method.x f h f' x₀ j) ≤ φ (proximal_gradient_method.x f h f' x₀ i)) →
                        ∀ (i k : ℕ),
                          i < k →
                            φ (proximal_gradient_method.x f h f' x₀ (i + 1)) -
                                  φ (proximal_gradient_method.xm f h f' x₀) ≤
                                1 / (2 * proximal_gradient_method.t f h f' x₀) *
                                  (‖proximal_gradient_method.x f h f' x₀ i - proximal_gradient_method.xm f h f' x₀‖ ^
                                      2 -
                                    ‖proximal_gradient_method.x f h f' x₀ (i + 1) -
                                          proximal_gradient_method.xm f h f' x₀‖ ^
                                      2) →
                              φ
                                    (proximal_gradient_method.x f h f' x₀ i -
                                      proximal_gradient_method.t f h f' x₀ •
                                        Gt (proximal_gradient_method.x f h f' x₀ i)) -
                                  φ (proximal_gradient_method.xm f h f' x₀) ≤
                                1 / (2 * proximal_gradient_method.t f h f' x₀) *
                                  (‖proximal_gradient_method.x f h f' x₀ i - proximal_gradient_method.xm f h f' x₀‖ ^
                                      2 -
                                    ‖proximal_gradient_method.x f h f' x₀ i -
                                            proximal_gradient_method.t f h f' x₀ •
                                              Gt (proximal_gradient_method.x f h f' x₀ i) -
                                          proximal_gradient_method.xm f h f' x₀‖ ^
                                      2) := sorry

Tactic state before:
E : Type u_1
inst✝³ : NormedAddCommGroup E
inst✝² : InnerProductSpace ℝ E
inst✝¹ : CompleteSpace E
inst✝ : ProperSpace E
x₀ : E
f : E → ℝ
f' : E → E
h : E → ℝ
alg : proximal_gradient_method f h f' x₀
k✝ : ℕ+
th : ContinuousOn (proximal_gradient_method.t f h f' x₀ • h) univ
th' : ConvexOn ℝ univ (proximal_gradient_method.t f h f' x₀ • h)
Gt : E → E :=
  fun x =>
    (1 / proximal_gradient_method.t f h f' x₀) •
      (x -
        prox_point_c' (proximal_gradient_method.t f h f' x₀ • h) (x - proximal_gradient_method.t f h f' x₀ • f' x) th
          th')
φ : E → ℝ := fun x => f x + h x
hG : ∀ (z : E), Gt z - f' z ∈ SubderivAt h (z - proximal_gradient_method.t f h f' x₀ • Gt z)
fieq1 :
  ∀ (x : E),
    f (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
      f x - proximal_gradient_method.t f h f' x₀ * inner (f' x) (Gt x) +
        proximal_gradient_method.t f h f' x₀ ^ 2 * ↑(proximal_gradient_method.L f h f' x₀) / 2 * ‖Gt x‖ ^ 2
fieq2 :
  ∀ (x : E),
    f (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
      f x - proximal_gradient_method.t f h f' x₀ * inner (f' x) (Gt x) +
        proximal_gradient_method.t f h f' x₀ / 2 * ‖Gt x‖ ^ 2
fieq3 : ∀ (x z : E), f x + inner (f' x) (z - x) ≤ f z
hieq1 :
  ∀ (x z : E),
    h (x - proximal_gradient_method.t f h f' x₀ • Gt x) +
        inner (Gt x - f' x) (z - x + proximal_gradient_method.t f h f' x₀ • Gt x) ≤
      h z
hieq2 :
  ∀ (x z : E),
    h (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
      h z - inner (Gt x - f' x) (z - x + proximal_gradient_method.t f h f' x₀ • Gt x)
univieq :
  ∀ (x z : E),
    φ (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
      φ z + inner (Gt x) (x - z) - proximal_gradient_method.t f h f' x₀ / 2 * ‖Gt x‖ ^ 2
φieq1 :
  ∀ (x : E),
    φ (x - proximal_gradient_method.t f h f' x₀ • Gt x) - φ (proximal_gradient_method.xm f h f' x₀) ≤
      1 / (2 * proximal_gradient_method.t f h f' x₀) *
        (‖x - proximal_gradient_method.xm f h f' x₀‖ ^ 2 -
          ‖x - proximal_gradient_method.t f h f' x₀ • Gt x - proximal_gradient_method.xm f h f' x₀‖ ^ 2)
iter :
  ∀ (i : ℕ),
    proximal_gradient_method.x f h f' x₀ (i + 1) =
      proximal_gradient_method.x f h f' x₀ i -
        proximal_gradient_method.t f h f' x₀ • Gt (proximal_gradient_method.x f h f' x₀ i)
φdecrease : ∀ (i : ℕ), φ (proximal_gradient_method.x f h f' x₀ (i + 1)) ≤ φ (proximal_gradient_method.x f h f' x₀ i)
φdecrease' :
  ∀ (i j : ℕ), i ≤ j → φ (proximal_gradient_method.x f h f' x₀ j) ≤ φ (proximal_gradient_method.x f h f' x₀ i)
i k : ℕ
ilt : i < k
⊢ φ (proximal_gradient_method.x f h f' x₀ (i + 1)) - φ (proximal_gradient_method.xm f h f' x₀) ≤
    1 / (2 * proximal_gradient_method.t f h f' x₀) *
      (‖proximal_gradient_method.x f h f' x₀ i - proximal_gradient_method.xm f h f' x₀‖ ^ 2 -
        ‖proximal_gradient_method.x f h f' x₀ (i + 1) - proximal_gradient_method.xm f h f' x₀‖ ^ 2)

Tactic:
rw [iter i]

Tactic state after:
[E : Type u_1
 inst✝³ : NormedAddCommGroup E
 inst✝² : InnerProductSpace ℝ E
 inst✝¹ : CompleteSpace E
 inst✝ : ProperSpace E
 x₀ : E
 f : E → ℝ
 f' : E → E
 h : E → ℝ
 alg : proximal_gradient_method f h f' x₀
 k✝ : ℕ+
 th : ContinuousOn (proximal_gradient_method.t f h f' x₀ • h) univ
 th' : ConvexOn ℝ univ (proximal_gradient_method.t f h f' x₀ • h)
 Gt : E → E :=
   fun x =>
     (1 / proximal_gradient_method.t f h f' x₀) •
       (x -
         prox_point_c' (proximal_gradient_method.t f h f' x₀ • h) (x - proximal_gradient_method.t f h f' x₀ • f' x) th
           th')
 φ : E → ℝ := fun x => f x + h x
 hG : ∀ (z : E), Gt z - f' z ∈ SubderivAt h (z - proximal_gradient_method.t f h f' x₀ • Gt z)
 fieq1 :
   ∀ (x : E),
     f (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
       f x - proximal_gradient_method.t f h f' x₀ * inner (f' x) (Gt x) +
         proximal_gradient_method.t f h f' x₀ ^ 2 * ↑(proximal_gradient_method.L f h f' x₀) / 2 * ‖Gt x‖ ^ 2
 fieq2 :
   ∀ (x : E),
     f (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
       f x - proximal_gradient_method.t f h f' x₀ * inner (f' x) (Gt x) +
         proximal_gradient_method.t f h f' x₀ / 2 * ‖Gt x‖ ^ 2
 fieq3 : ∀ (x z : E), f x + inner (f' x) (z - x) ≤ f z
 hieq1 :
   ∀ (x z : E),
     h (x - proximal_gradient_method.t f h f' x₀ • Gt x) +
         inner (Gt x - f' x) (z - x + proximal_gradient_method.t f h f' x₀ • Gt x) ≤
       h z
 hieq2 :
   ∀ (x z : E),
     h (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
       h z - inner (Gt x - f' x) (z - x + proximal_gradient_method.t f h f' x₀ • Gt x)
 univieq :
   ∀ (x z : E),
     φ (x - proximal_gradient_method.t f h f' x₀ • Gt x) ≤
       φ z + inner (Gt x) (x - z) - proximal_gradient_method.t f h f' x₀ / 2 * ‖Gt x‖ ^ 2
 φieq1 :
   ∀ (x : E),
     φ (x - proximal_gradient_method.t f h f' x₀ • Gt x) - φ (proximal_gradient_method.xm f h f' x₀) ≤
       1 / (2 * proximal_gradient_method.t f h f' x₀) *
         (‖x - proximal_gradient_method.xm f h f' x₀‖ ^ 2 -
           ‖x - proximal_gradient_method.t f h f' x₀ • Gt x - proximal_gradient_method.xm f h f' x₀‖ ^ 2)
 iter :
   ∀ (i : ℕ),
     proximal_gradient_method.x f h f' x₀ (i + 1) =
       proximal_gradient_method.x f h f' x₀ i -
         proximal_gradient_method.t f h f' x₀ • Gt (proximal_gradient_method.x f h f' x₀ i)
 φdecrease : ∀ (i : ℕ), φ (proximal_gradient_method.x f h f' x₀ (i + 1)) ≤ φ (proximal_gradient_method.x f h f' x₀ i)
 φdecrease' :
   ∀ (i j : ℕ), i ≤ j → φ (proximal_gradient_method.x f h f' x₀ j) ≤ φ (proximal_gradient_method.x f h f' x₀ i)
 i k : ℕ
 ilt : i < k
 ⊢ φ
         (proximal_gradient_method.x f h f' x₀ i -
           proximal_gradient_method.t f h f' x₀ • Gt (proximal_gradient_method.x f h f' x₀ i)) -
       φ (proximal_gradient_method.xm f h f' x₀) ≤
     1 / (2 * proximal_gradient_method.t f h f' x₀) *
       (‖proximal_gradient_method.x f h f' x₀ i - proximal_gradient_method.xm f h f' x₀‖ ^ 2 -
         ‖proximal_gradient_method.x f h f' x₀ i -
                 proximal_gradient_method.t f h f' x₀ • Gt (proximal_gradient_method.x f h f' x₀ i) -
               proximal_gradient_method.xm f h f' x₀‖ ^
           2)]