This is a minimal example of an optimization problem that can be built and solved using the alpaqa
Python interface.
This is a minimal example of an optimization problem that can be built and solved using the alpaqa
Python interface. It includes visualization of the iterates.
1
2import casadi as cs
3import numpy as np
4
5
6x1, x2 = cs.SX.sym("x1"), cs.SX.sym("x2")
7x = cs.vertcat(x1, x2)
8
9p = cs.SX.sym("p")
10
11
12f = (1 - x1) ** 2 + p * (x2 - x1**2) ** 2
13g = cs.vertcat(
14 (x1 - 0.5) ** 3 - x2 + 1,
15 x1 + x2 - 1.5,
16)
17
18
19C = [-0.25, -0.5], [1.5, 2.5]
20D = [-np.inf, -np.inf], [0, 0]
21
22
23from alpaqa import minimize
24
25problem = (
26 minimize(f, x)
27 .subject_to_box(C)
28 .subject_to(g, D)
29 .with_param(p, [10])
30).compile()
31
32
33import alpaqa as pa
34
35inner_solver = pa.PANOCSolver()
36solver = pa.ALMSolver(inner_solver)
37
38
39inner_solver = pa.PANOCSolver(
40 dict(
41 max_iter=50,
42 stop_crit=pa.PANOCStopCrit.ApproxKKT,
43 print_interval=1,
44 ),
45 dict(memory=10),
46)
47
48
49
50iterates = []
51def callback(it: pa.PANOCProgressInfo):
52 if it.k == 0:
53 iterates.append([])
54 iterates[-1].append(np.copy(it.x))
55
56
57inner_solver.set_progress_callback(callback)
58
59alm_params = pa.ALMParams(
60 tolerance=1e-8,
61 dual_tolerance=1e-8,
62 initial_penalty=50,
63 penalty_update_factor=20,
64 print_interval=1,
65)
66solver = pa.ALMSolver(
67 alm_params,
68 inner_solver,
69)
70
71
72
73x0 = [0.1, 1.8]
74y0 = [0.0, 0.0]
75
76
77x_sol, y_sol, stats = solver(problem, x0, y0)
78
79
80print(solver)
81print(stats["status"])
82print(f"Solution: {x_sol}")
83print(f"Multipliers: {y_sol}")
84print(f"Cost: {problem.eval_f(x_sol)}")
85from pprint import pprint
86pprint(stats)
87
88
89
90import matplotlib.pyplot as plt
91from matplotlib import patheffects
92
93cost_function_v = np.vectorize(problem.eval_f, signature="(n)->()")
94constr_function_v = np.vectorize(problem.eval_g, signature="(n)->(m)")
95
96x = np.linspace(-1.5, 1.5, 256)
97y = np.linspace(-0.5, 2.5, 256)
98X, Y = np.meshgrid(x, y)
99XY = np.vstack([[X], [Y]]).T
100
101plt.figure(figsize=(10, 6))
102
103Zf = cost_function_v(XY).T
104plt.contourf(X, Y, Zf, 32)
105plt.colorbar()
106
107Zgc, Zgl = constr_function_v(XY).T
108line_opts = dict(colors="black", linewidths=0.8, linestyles="-")
109fx = [patheffects.withTickedStroke(spacing=7, linewidth=0.8)]
110cgc = plt.contour(X, Y, Zgc, [0], **line_opts)
111plt.setp(cgc, path_effects=fx)
112cgl = plt.contour(X, Y, Zgl, [0], **line_opts)
113plt.setp(cgl, path_effects=fx)
114xl = plt.contour(X, Y, -X, [-problem.C.lowerbound[0]], **line_opts)
115plt.setp(xl, path_effects=fx)
116
117plt.title("PANOC+ALM Rosenbrock example")
118plt.xlabel("$x_1$")
119plt.ylabel("$x_2$")
120
121
122for xy in map(np.array, iterates):
123 plt.plot(xy[:, 0], xy[:, 1], "r:.", markersize=4, linewidth=1)
124plt.plot(x_sol[0], x_sol[1], "ro", markersize=10, fillstyle="none")
125
126plt.tight_layout()
127plt.show()