alpaqa 0.0.1
Nonconvex constrained optimization
rosenbrock.py
Go to the documentation of this file.
1## @example simple_optimization/python/rosenbrock.py
2# This code contains a minimal example of an optimization problem that can be
3# built and solved using `alpaqa`, it includes visualization of the iterates.
4
5# %% Build the problem for PANOC+ALM (CasADi code, independent of alpaqa)
6import casadi as cs
7
8# Make symbolic decision variables
9x1, x2 = cs.SX.sym("x1"), cs.SX.sym("x2")
10# Make a parameter symbol
11p = cs.SX.sym("p")
12
13# Expressions for the objective function f and the constraints g
14f_expr = (1 - x1) ** 2 + p * (x2 - x1 ** 2) ** 2
15g_expr = cs.vertcat(
16 (x1 - 0.5) ** 3 - x2 + 1,
17 x1 + x2 - 1.5,
18)
19
20# Collect decision variables into one vector
21x = cs.vertcat(x1, x2)
22# Convert the symbolic expressions to CasADi functions
23f = cs.Function("f", [x, p], [f_expr])
24g = cs.Function("g", [x, p], [g_expr])
25
26# %% Generate and compile C-code for the objective and constraints using alpaqa
27import alpaqa as pa
28
29# Compile and load the problem
30prob = pa.generate_and_compile_casadi_problem(f, g)
31
32# Set the bounds
33import numpy as np
34prob.C.lowerbound = [-0.25, -0.5] # -0.25 <= x1 <= 1.5
35prob.C.upperbound = [1.5, 2.5] # -0.5 <= x2 <= 2.5
36prob.D.lowerbound = [-np.inf, -np.inf] # g1 <= 0
37prob.D.upperbound = [0, 0] # g2 <= 0
38
39# Set parameter to some value
40prob.param = [10.]
41
42# %% Build an inner Structured PANOC solver with custom parameters
43innersolver = pa.StructuredPANOCLBFGSSolver(
44 pa.StructuredPANOCLBFGSParams(
45 max_iter=1000,
46 stop_crit=pa.PANOCStopCrit.ApproxKKT,
47 ),
48 pa.LBFGSParams(
49 memory=10,
50 ),
51)
52
53# You can attach a callback that is called on each iteration, and keeps track of
54# the iterates so they can be plotted later
55iterates = []
56def cb(it): iterates.append(np.copy(it.x))
57# Note: the iterate values like it.x are only valid within the callback, if you
58# want to save them for later, you have to make a copy.
59innersolver.set_progress_callback(cb)
60
61# %% Make an ALM solver with default parameters, using the PANOC solver
62solver = pa.ALMSolver(
63 pa.ALMParams(
64 ε=1e-10,
65 δ=1e-10,
66 Σ_0=0,
67 σ_0=2,
68 Δ=20,
69 ),
70 innersolver
71)
72
73# %% Compute a solution
74
75# Set initial guesses at arbitrary values
76x0 = np.array([0.1, 1.8]) # decision variables
77y0 = np.zeros((prob.m,)) # Lagrange multipliers for g(x)
78
79# Solve the problem
80x_sol, y_sol, stats = solver(prob, x0, y0)
81
82# Print the results
83print(stats["status"])
84print(f"Solution: {x_sol}")
85print(f"Multipliers: {y_sol}")
86print(f"Cost: {prob.f(x_sol)}")
87from pprint import pprint
88pprint(stats)
89
90# %% Plot the results
91
92import matplotlib.pyplot as plt
93from matplotlib import patheffects
94
95cost_function_v = np.vectorize(prob.f, signature='(n)->()')
96constraint_g_v = np.vectorize(prob.g, signature='(n)->(m)')
97
98x = np.linspace(-1.5, 1.5, 256)
99y = np.linspace(-0.5, 2.5, 256)
100X, Y = np.meshgrid(x, y)
101XY = np.vstack([[X], [Y]]).T
102
103plt.figure(figsize=(10, 6))
104# Draw objective function
106plt.contourf(X, Y, Zf, 32)
107plt.colorbar()
108# Draw constraints
110Zgc = Zg[:,:,0].T
111Zgl = Zg[:,:,1].T
112fx = [patheffects.withTickedStroke(spacing=7, linewidth=0.8)]
113cgc = plt.contour(X, Y, Zgc, [0], colors='black', linewidths=0.8, linestyles='-')
114plt.setp(cgc.collections, path_effects=fx)
115cgl = plt.contour(X, Y, Zgl, [0], colors='black', linewidths=0.8, linestyles='-')
116plt.setp(cgl.collections, path_effects=fx)
117xl = plt.contour(X, Y, -X, [-prob.C.lowerbound[0]], colors='black', linewidths=0.8, linestyles='-')
118plt.setp(xl.collections, path_effects=fx)
119
120plt.title("PANOC+ALM Rosenbrock example")
121plt.xlabel("$x_1$")
122plt.ylabel("$x_2$")
123
124# Draw iterates and solution
125xy = np.array(iterates)
126plt.plot(xy[:,0], xy[:,1], 'r:.', markersize=4, linewidth=1)
127plt.plot(x_sol[0], x_sol[1], 'ro', markersize=10, fillstyle='none')
128
129plt.tight_layout()
130plt.show()
def cb(it)
Definition: rosenbrock.py:56