This repository accompanies the manuscript.
We present a novel methodology for optimization algorithm design, using ideas from electric RLC circuits and the performance estimation problem. Our methodology provides a quick and systematic recipe for designing new, provably convergent optimization algorithms, including distributed optimization algorithms.
In this repository, we provide ciropt
package implementing this methodology.
With ciropt
, you can easily explore a wide range of algorithms that have a convergence guarantee.
To install ciropt
1) activate virtual environment, 2) clone the repo, 3) from inside the directory run
pip install -e .
Requirements
- python == 3.10
- pepit == 0.2.1
- numpy >= 1.26
- scipy >= 1.11.3
- casadi == 3.6.4
- sympy == 1.12
- cvxpy == 1.4.1
- matplotlib >= 3.5.3
- Start with the optimization problem.
-
Create the static interconnect (SI) respresenting the optimality conditions.
-
Replace wires of SI with RLC components to derive the admissible dynamic interconnect (DI) that relaxes to SI in equilibrium.
-
Using
ciropt
find discretization parameters for DI that produce convergent algorithm. -
Use the resulting algorithm to solve your problem.
Note that in step 3, there are infinitely many admissible DIs that can be designed. Each of these, when discretized, results in a different optimization algorithm. Feel free to experiment with various DIs to discover new algorithms suitable for your problem at hand.
See the examples/hello_world.ipynb
notebook or explanation below.
- As a hello world example we consider the problem given below, where
$f$ is convex function.
-
The optimality condition for this problem is to find
$x$ such that$0 \in \partial f(x)$ . The corresponding SI for this condition follows, see circuit. -
We consider the following admissible DI, see circuit.
-
Now let's discretize this DI using
ciropt
.
Step 1. Define a problem.
import ciropt as co
problem = co.CircuitOpt()
Step 2. Define function class, in this example
f = co.def_function(problem, mu, M)
Step 3. Define optimal points.
x_star, y_star, f_star = f.stationary_point(return_gradient_and_function_value=True)
Step 4. Define values for the RLC components and
discretization parameters, here for simplicity
we take
R, C = 1, 10
h, eta = problem.h, problem.eta
Step 5. Define the one step transition of the discretized V-I relations.
z_1 = problem.set_initial_point()
e2_1 = problem.set_initial_point()
x_1 = co.proximal_step(z_1, f, R/2)[0]
y_1 = (2 / R) * (z_1 - x_1)
e1_1 = (e2_1 - R * y_1) / 2
v_C1_1 = e2_1 / 2 - z_1
v_C2_1 = e2_1
e2_2 = e2_1 - h / (2 * R * C) * (R * y_1 + 3 * e2_1)
z_2 = z_1 - h / (4 * R * C) * (5 * R * y_1 + 3 * e2_1)
x_2 = co.proximal_step(z_2, f, R/2)[0]
y_2 = (2 / R) * (z_2 - x_2)
v_C1_2 = e2_2 / 2 - z_2
v_C2_2 = e2_2
Step 6. Define dissipative term and set the objective to maximize descent coefficients. Solve the final problem.
E_1 = (C/2) * (v_C1_1 + x_star)**2 + (C/2) * (v_C2_1)**2
E_2 = (C/2) * (v_C1_2 + x_star)**2 + (C/2) * (v_C2_2)**2
Delta_1 = eta * (x_1 - x_star) * (y_1 - y_star)
problem.set_performance_metric(E_2 - (E_1 - Delta_1))
params = problem.solve()[:1]
The resulting provably convergent algorithm is
- Solve your problem using new algorithm. We consider the primal problem
where
We apply our discretization to solve the dual problem
The relative error versus iteration is plotted here.
See notebooks in examples/
folder
that show how to use ciropt
to discretize various circuits.
Centralized methods:
- gradient descent, proximal gradient, proximal point method, Nesterov acceleration
- primal decomposition, dual decomposition, Douglas-Rachford splitting, proximal decomposition, Davis-Yin splitting
Decentralized methods:
- DGD
- diffusion
- DADMM
- PG-EXTRA
Please consult our manuscript for the details of mentioned problems.
Since we are using Ipopt which does not solve the nonconvex optimization problem to global optimality, here are some tips we found useful.
- Vary resistances, capacitances, inductances if the Ipopt does not find a proof for given values.
- Try changing smoothness of your function class from
$M=\infty$ to finite value. - Consider the full dissipative term
- Vary the mixing weight
$w$ in the objective$\eta + w\rho$ , by settingproblem.obj = eta + w * rho
, which increases the descent in energy. - Change solvers in the
problem.solve
from"ipopt", "ipopt_qcqp", "ipopt_qcqp_matrix"
.