alpaqa 0.0.1
Nonconvex constrained optimization
test.py
Go to the documentation of this file.
1#%%
2
3print("starting tests")
4
5import alpaqa as pa
6import numpy as np
7from pprint import pprint
8
9print("1")
10solver = pa.PANOCSolver(pa.PANOCParams(), pa.LBFGSDirection(pa.LBFGSParams()))
11print("2")
12assert str(solver) == "PANOCSolver<LBFGS>"
13print("3")
14solver = pa.PANOCSolver(pa.PANOCParams(), pa.LBFGSParams())
15print("4")
16assert str(solver) == "PANOCSolver<LBFGS>"
17
18
19class Dir(pa.PANOCDirection):
20 def __init__(self):
21 super().__init__()
22
23 def get_name(self):
24 return "Dir"
25
26
27assert str(Dir()) == "Dir"
28solver = pa.PANOCSolver(pa.PANOCParams(), Dir())
29assert str(solver) == "PANOCSolver<Dir>"
30
31l = pa.LBFGSParams(cbfgs=pa.LBFGSParamsCBFGS(α=5))
32assert l.cbfgs.α == 5
33l.cbfgs.α = 100
34assert l.cbfgs.α == 100
35
36import casadi as cs
37
38hess_prod = lambda L, x, v: cs.gradient(cs.jtimes(L, x, v, False), x)
39
40n = 2
41m = 2
42x = cs.SX.sym("x", n)
43λ = cs.SX.sym("λ", m)
44v = cs.SX.sym("v", n)
45
46Q = np.array([[1.5, 0.5], [0.5, 1.5]])
47f_ = x.T @ Q @ x
48g_ = x
49L = f_ + cs.dot(λ, g_) if m > 0 else f_
50
51f = cs.Function("f", [x], [f_])
52grad_f = cs.Function("grad_f", [x], [cs.gradient(f_, x)])
53g = cs.Function("g", [x], [g_])
54grad_g_prod = cs.Function("grad_g_prod", [x, λ], [cs.jtimes(g_, x, λ, True)])
55grad_gi = lambda x, i: grad_g_prod(x, np.eye(1, m, i))
56Hess_L = cs.Function("Hess_L", [x, λ], [cs.hessian(L, x)[0]])
57Hess_L_prod = cs.Function("Hess_L_prod", [x, λ, v], [hess_prod(L, x, v)])
58
59p = pa.Problem(n, m)
60p.f = f
61p.grad_f = grad_f
62p.g = g
63p.grad_g_prod = grad_g_prod
64p.grad_gi = grad_gi
65p.hess_L = Hess_L
66p.hess_L_prod = Hess_L_prod
67p.D.lowerbound = [-np.inf, 0.5]
68p.D.upperbound = [+np.inf, +np.inf]
69
70x0 = np.array([3, 3])
71y0 = np.zeros((m,))
72Σ = 1e3 * np.ones((m,))
73ε = 1e-8
74solver = pa.PANOCSolver(
75 pa.PANOCParams(max_iter=200, print_interval=1),
76 pa.LBFGSParams(memory=5),
77)
78x, y, err_z, stats = solver(p, Σ, ε, x0, y0)
79print(x)
80print(y)
81print(err_z)
82pprint(stats)
83
84solver = pa.PANOCSolver(
85 pa.PANOCParams(max_iter=200, print_interval=1),
86 pa.LBFGSParams(memory=5),
87)
88almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
89almsolver = pa.ALMSolver(almparams, solver)
90x, y, stats = almsolver(p, x=x0, y=y0)
91
92print(x)
93print(y)
94pprint(stats)
95
96solver = pa.StructuredPANOCLBFGSSolver(
97 pa.StructuredPANOCLBFGSParams(max_iter=200, print_interval=1),
98 pa.LBFGSParams(memory=5),
99)
100almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
101almsolver = pa.ALMSolver(almparams, solver)
102x, y, stats = almsolver(p, x=x0, y=y0)
103
104
105class CustomInnerSolver(pa.InnerSolver):
106 def __init__(self):
107 super().__init__()
108 self.solversolver = pa.PANOCSolver(
109 pa.PANOCParams(max_iter=200, print_interval=1),
110 pa.LBFGSParams(memory=5),
111 )
112
113 def get_name(self):
114 return self.solversolver.get_name()
115
116 def stop(self):
117 return self.solversolver.stop()
118
119 def __call__(self, problem, Σ, ε, always_overwrite_results, x, y):
120 # TODO: always_overwrite_results
121 x, y, err_z, stats = self.solversolver(problem, Σ, ε, x, y)
122
123 def accumulate(acc: dict, s: dict):
124 for k, v in s.items():
125 if not k in ["status", "ε", "accumulator"]:
126 acc[k] = acc[k] + v if k in acc else v
127
128 stats["accumulator"] = {"accumulate": accumulate}
129 return x, y, err_z, stats
130
131
132solver = CustomInnerSolver()
133almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
134almsolver = pa.ALMSolver(almparams, solver)
135x, y, stats = almsolver(p, x=x0, y=y0)
136
137print(x)
138print(y)
139pprint(stats)
140
141try:
142 old_x0 = x0
143 x0 = np.zeros((666,))
144 sol = almsolver(p, x=x0, y=y0)
145except ValueError as e:
146 assert e.args[0] == "Length of x does not match problem size problem.n"
147
148x0 = old_x0
149
150# %%
151
152n = 2
153m = 2
154x = cs.SX.sym("x", n)
155λ = cs.SX.sym("λ", m)
156v = cs.SX.sym("v", n)
157
158Q = np.array([[1.5, 0.5], [0.5, 1.5]])
159f_ = 0.5 * x.T @ Q @ x
160g_ = x
161f = cs.Function("f", [x], [f_])
162g = cs.Function("g", [x], [g_])
163
164name = "testproblem"
165p = pa.generate_and_compile_casadi_problem(f, g, name=name)
166p.D.lowerbound = [-np.inf, 0.5]
167p.D.upperbound = [+np.inf, +np.inf]
168solver = pa.StructuredPANOCLBFGSSolver(
169 pa.StructuredPANOCLBFGSParams(max_iter=200, print_interval=1),
170 pa.LBFGSParams(memory=5),
171)
172almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
173almsolver = pa.ALMSolver(almparams, solver)
174x, y, stats = almsolver(p, x=x0, y=y0)
175
176print(x)
177print(y)
178pprint(stats)
179
180# %%
181
182n = 2
183m = 2
184x = cs.SX.sym("x", n)
185p = cs.SX.sym("p", 3)
186
187p0 = np.array([1.5, 0.5, 1.5])
188
189Q = cs.vertcat(cs.horzcat(p[0], p[1]), cs.horzcat(p[1], p[2]))
190f_ = 0.5 * x.T @ Q @ x
191g_ = x
192f = cs.Function("f", [x, p], [f_])
193g = cs.Function("g", [x, p], [g_])
194
195name = "testproblem"
196prob = pa.generate_and_compile_casadi_problem(f, g, name=name)
197prob.D.lowerbound = [-np.inf, 0.5]
198prob.D.upperbound = [+np.inf, +np.inf]
199prob.param = p0
200solver = pa.StructuredPANOCLBFGSSolver(
201 pa.StructuredPANOCLBFGSParams(max_iter=200, print_interval=1),
202 pa.LBFGSParams(memory=5),
203)
204almparams = pa.ALMParams(max_iter=20, print_interval=1, preconditioning=False)
205almsolver = pa.ALMSolver(almparams, solver)
206x, y, stats = almsolver(prob, x=x0, y=y0)
207
208print(x)
209print(y)
210pprint(stats)
211
212# %% Make sure that the problem is copied
213
214prob.param = [1, 2, 3]
215assert np.all(prob.param == [1, 2, 3])
216prob1 = pa.ProblemWithParamWithCounters(prob)
217print(prob.param)
218print(prob1.param)
219assert np.all(prob.param == [1, 2, 3])
220assert np.all(prob1.param == [1, 2, 3])
221prob1.param = [42, 43, 44]
222print(prob.param)
223print(prob1.param)
224assert np.all(prob.param == [1, 2, 3])
225assert np.all(prob1.param == [42, 43, 44])
226print(prob.f([1, 2]))
227print(prob1.f([1, 2]))
228assert prob.f([1, 2]) == 21 / 2
229assert prob1.f([1, 2]) == 390 / 2
230assert prob1.evaluations.f == 2
231
232prob2 = pa.ProblemWithCounters(prob) # params are not copied!
233print(prob.f([1, 2]))
234print(prob2.f([1, 2]))
235assert prob.f([1, 2]) == 21 / 2
236assert prob2.f([1, 2]) == 21 / 2
237prob.param = [2, 1, 3]
238print(prob.f([1, 2]))
239print(prob2.f([1, 2]))
240assert prob.f([1, 2]) == 18 / 2
241assert prob2.f([1, 2]) == 18 / 2
242assert prob1.evaluations.f == 2
243assert prob2.evaluations.f == 4
244
245# %%
246
247prob1.param = p0
248x, y, stats = almsolver(prob1) # without initial guess
249
250print(x)
251print(y)
252pprint(stats)
253print(prob1.evaluations.f)
254print(prob1.evaluations.grad_f)
255print(prob1.evaluations.g)
256print(prob1.evaluations.grad_g_prod)
257
258# %%
259
260f = lambda x: float(np.cosh(x) - x * x + x)
261grad_f = lambda x: np.sinh(x) - 2 * x + 1
262C = pa.Box([10], [-2.5])
263x0 = [5]
264x, stats = pa.panoc(
265 f, grad_f, C, x0, 1e-12, pa.PANOCParams(print_interval=1), pa.LBFGSParams()
266)
267print(x)
268pprint(stats)
269
270# %%
271
272f = lambda x: float(np.cosh(x) - x * x + x)
273grad_f = lambda x: np.sinh(x) - 2 * x + 1
274C = pa.Box([10], [-2.5])
275x, stats = pa.panoc(f, grad_f, C, params=pa.PANOCParams(print_interval=1))
276print(x)
277pprint(stats)
278
279# %%
280
281try:
282 pa.PANOCParams(max_iter=1e3)
283 assert False
284except RuntimeError as e:
285 print(e)
286
287# %%
288
289print("Success!")
def get_name(self)
Definition: test.py:23
hess_prod
Definition: test.py:38
grad_g_prod
Definition: test.py:54
almsolver
Definition: test.py:89