PANOC-ALM  quadratic-penalty
Nonconvex constrained optimization
test.py
Go to the documentation of this file.
1 #%%
2 
3 import panocpy as pa
4 import numpy as np
5 from pprint import pprint
6 
7 print("1")
8 solver = pa.PANOCSolver(pa.PANOCParams(), pa.LBFGSDirection(pa.LBFGSParams()))
9 print("2")
10 assert str(solver) == "PANOCSolver<LBFGS>"
11 print("3")
13 print("4")
14 assert str(solver) == "PANOCSolver<LBFGS>"
15 
16 
18  def __init__(self):
19  super().__init__()
20 
21  def get_name(self):
22  return "Dir"
23 
24 
25 assert str(Dir()) == "Dir"
26 solver = pa.PANOCSolver(pa.PANOCParams(), Dir())
27 assert str(solver) == "PANOCSolver<Dir>"
28 
29 l = pa.LBFGSParams(cbfgs=pa.LBFGSParamsCBFGS(α=5))
30 assert l.cbfgs.α == 5
31 l.cbfgs.α = 100
32 assert l.cbfgs.α == 100
33 
34 import casadi as cs
35 
36 hess_prod = lambda L, x, v: cs.gradient(cs.jtimes(L, x, v, False), x)
37 
38 n = 2
39 m = 2
40 x = cs.SX.sym("x", n)
41 λ = cs.SX.sym("λ", m)
42 v = cs.SX.sym("v", n)
43 
44 Q = np.array([[1.5, 0.5], [0.5, 1.5]])
45 f_ = x.T @ Q @ x
46 g_ = x
47 L = f_ + cs.dot(λ, g_) if m > 0 else f_
48 
49 f = cs.Function("f", [x], [f_])
50 grad_f = cs.Function("grad_f", [x], [cs.gradient(f_, x)])
51 g = cs.Function("g", [x], [g_])
52 grad_g_prod = cs.Function("grad_g_prod", [x, λ], [cs.jtimes(g_, x, λ, True)])
53 grad_gi = lambda x, i: grad_g_prod(x, np.eye(1, m, i))
54 Hess_L = cs.Function("Hess_L", [x, λ], [cs.hessian(L, x)[0]])
55 Hess_L_prod = cs.Function("Hess_L_prod", [x, λ, v], [hess_prod(L, x, v)])
56 
57 p = pa.Problem(n, m)
58 p.f = f
59 p.grad_f = grad_f
60 p.g = g
61 p.grad_g_prod = grad_g_prod
62 p.grad_gi = grad_gi
63 p.hess_L = Hess_L
64 p.hess_L_prod = Hess_L_prod
65 p.D.lowerbound = [-np.inf, 0.5]
66 p.D.upperbound = [+np.inf, +np.inf]
67 
68 x0 = np.array([3, 3])
69 y0 = np.zeros((m,))
70 Σ = 1e3 * np.ones((m,))
71 ε = 1e-8
72 solver = pa.PANOCSolver(
73  pa.PANOCParams(max_iter=200, print_interval=1),
74  pa.LBFGSParams(memory=5),
75 )
76 x, y, err_z, stats = solver(p, Σ, ε, x0, y0)
77 print(x)
78 print(y)
79 print(err_z)
80 pprint(stats)
81 
82 solver = pa.PANOCSolver(
83  pa.PANOCParams(max_iter=200, print_interval=1),
84  pa.LBFGSParams(memory=5),
85 )
86 almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
87 almsolver = pa.ALMSolver(almparams, solver)
88 x, y, stats = almsolver(p, x=x0, y=y0)
89 
90 print(x)
91 print(y)
92 pprint(stats)
93 
95  pa.StructuredPANOCLBFGSParams(max_iter=200, print_interval=1),
96  pa.LBFGSParams(memory=5),
97 )
98 almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
99 almsolver = pa.ALMSolver(almparams, solver)
100 x, y, stats = almsolver(p, x=x0, y=y0)
101 
102 
103 class CustomInnerSolver(pa.InnerSolver):
104  def __init__(self):
105  super().__init__()
107  pa.PANOCParams(max_iter=200, print_interval=1),
108  pa.LBFGSParams(memory=5),
109  )
110 
111  def get_name(self):
112  return self.solver.get_name()
113 
114  def stop(self):
115  return self.solver.stop()
116 
117  def __call__(self, problem, Σ, ε, always_overwrite_results, x, y):
118  # TODO: always_overwrite_results
119  x, y, err_z, stats = self.solver(problem, Σ, ε, x, y)
120 
121  def accumulate(acc: dict, s: dict):
122  for k, v in s.items():
123  if not k in ["status", "ε", "accumulator"]:
124  acc[k] = acc[k] + v if k in acc else v
125 
126  stats["accumulator"] = {"accumulate": accumulate}
127  return x, y, err_z, stats
128 
129 
130 solver = CustomInnerSolver()
131 almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
132 almsolver = pa.ALMSolver(almparams, solver)
133 x, y, stats = almsolver(p, x=x0, y=y0)
134 
135 print(x)
136 print(y)
137 pprint(stats)
138 
139 try:
140  old_x0 = x0
141  x0 = np.zeros((666,))
142  sol = almsolver(p, x=x0, y=y0)
143 except ValueError as e:
144  assert e.args[0] == "Length of x does not match problem size problem.n"
145 
146 x0 = old_x0
147 
148 # %%
149 
150 import os
151 from os.path import join
152 from tempfile import TemporaryDirectory
153 
154 print(x.size)
155 print(g_.size1())
156 
157 n = 2
158 m = 2
159 x = cs.SX.sym("x", n)
160 λ = cs.SX.sym("λ", m)
161 v = cs.SX.sym("v", n)
162 
163 Q = np.array([[1.5, 0.5], [0.5, 1.5]])
164 f_ = 0.5 * x.T @ Q @ x
165 g_ = x
166 f = cs.Function("f", [x], [f_])
167 g = cs.Function("g", [x], [g_])
168 
169 name = "testproblem"
170 cgen, n, m, num_p = pa.generate_casadi_problem(f, g, name=name)
171 
172 with TemporaryDirectory(prefix="") as tmpdir:
173  cfile = cgen.generate(join(tmpdir, ""))
174  sofile = join(tmpdir, f"{name}.so")
175  os.system(f"cc -fPIC -shared -O3 {cfile} -o {sofile}")
176  print(sofile)
177  p = pa.load_casadi_problem(sofile, n, m)
178  p.D.lowerbound = [-np.inf, 0.5]
179  p.D.upperbound = [+np.inf, +np.inf]
181  pa.StructuredPANOCLBFGSParams(max_iter=200, print_interval=1),
182  pa.LBFGSParams(memory=5),
183 )
184 almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
185 almsolver = pa.ALMSolver(almparams, solver)
186 x, y, stats = almsolver(p, x=x0, y=y0)
187 
188 print(x)
189 print(y)
190 pprint(stats)
191 
192 # %%
193 
194 x, y, stats = almsolver(p) # without initial guess
195 
196 print(x)
197 print(y)
198 pprint(stats)
199 
200 # %%
201 
202 f = lambda x: float(np.cosh(x) - x * x + x)
203 grad_f = lambda x: np.sinh(x) - 2 * x + 1
204 C = pa.Box([10], [-2.5])
205 x0 = [5]
206 x, stats = pa.panoc(
207  f, grad_f, C, x0, 1e-12, pa.PANOCParams(print_interval=1), pa.LBFGSParams()
208 )
209 print(x)
210 pprint(stats)
211 
212 # %%
213 
214 f = lambda x: float(np.cosh(x) - x * x + x)
215 grad_f = lambda x: np.sinh(x) - 2 * x + 1
216 C = pa.Box([10], [-2.5])
217 x, stats = pa.panoc(f, grad_f, C, params=pa.PANOCParams(print_interval=1))
218 print(x)
219 pprint(stats)
panocpy.test.CustomInnerSolver
Definition: test.py:103
pa::StructuredPANOCLBFGSParams
Tuning parameters for the second order PANOC algorithm.
Definition: decl/structured-panoc-lbfgs.hpp:20
pa::StructuredPANOCLBFGSSolver
Second order PANOC solver for ALM.
Definition: decl/structured-panoc-lbfgs.hpp:80
panocpy.test.Dir
Definition: test.py:17
panocpy.test.CustomInnerSolver.get_name
def get_name(self)
Definition: test.py:111
pa::ALMSolver
Augmented Lagrangian Method solver.
Definition: decl/alm.hpp:82
pa::PANOCParams
Tuning parameters for the PANOC algorithm.
Definition: inner/decl/panoc.hpp:20
pa::ALMParams
Parameters for the Augmented Lagrangian solver.
Definition: decl/alm.hpp:13
pa::Box
Definition: box.hpp:7
panocpy.test.grad_g_prod
grad_g_prod
Definition: test.py:52
pa::LBFGSParams
Parameters for the LBFGS and SpecializedLBFGS classes.
Definition: decl/lbfgs.hpp:12
pa::PANOCSolver
PANOC solver for ALM.
Definition: inner/decl/panoc.hpp:88
panocpy.test.solver
solver
Definition: test.py:8
panocpy.test.CustomInnerSolver.solver
solver
Definition: test.py:106
pa::PANOCDirection
Definition: panoc-direction-update.hpp:8
pa::panoc
PANOCStats panoc(ObjFunT &ψ, ObjGradFunT &grad_ψ, const Box &C, rvec x, real_t ε, const PANOCParams &params, PANOCDirection< DirectionProviderT > direction)
Definition: standalone/panoc.hpp:385
panocpy.test.CustomInnerSolver.stop
def stop(self)
Definition: test.py:114
panocpy.test.Dir.get_name
def get_name(self)
Definition: test.py:21
panocpy.test.almsolver
almsolver
Definition: test.py:87
pa::Problem
Problem description for minimization problems.
Definition: include/panoc-alm/util/problem.hpp:24
panocpy.test.hess_prod
hess_prod
Definition: test.py:36