PhysicsOptimizer¶
PhysicsOptimizer(parameters, objective, constraints) (pinneapple_core.optim, also pp.PhysicsOptimizer) states a
constrained design or calibration problem once and solves it with any of six methods. Every method returns the same
OptimizeResult (parameters, value, largest constraint violation, feasibility, evaluations, family, history, time).
from pinneapple_core.optim import PhysicsOptimizer, eq, ineq
opt = PhysicsOptimizer({"a": (0.5, 2.0, 1.6), "b": (0.5, 2.0, 0.8)}, # name: (lo, hi, start)
objective=lambda x: -rigidity(x), # torch function of the vector x
constraints=[eq(lambda x: x[0] * x[1] - 1.0)]) # a*b = 1
opt.minimize("slsqp") # or "adjoint", "penalty", "augmented_lagrangian", "differential_evolution", "bayesian"
opt.compare() # all of them on the same problem
| Method | Family | Needs |
|---|---|---|
slsqp |
sequential quadratic programming with autograd gradients of objective and constraints | torch objective |
adjoint |
the same SQP with the objective gradient you supply (an adjoint solve, implicit_solve, torch.func.grad) |
grad= |
penalty |
projected Adam on the objective plus a growing quadratic penalty | torch objective |
augmented_lagrangian |
projected Adam with multiplier updates, so constraints are met exactly | torch objective |
differential_evolution |
population search; equality constraints as a thin band of width tol/2 |
nothing |
bayesian |
Gaussian-process expected improvement times the probability of feasibility, one GP per constraint | nothing |
Constraints are ineq(fn) for fn(x) <= 0 and eq(fn) for fn(x) == 0; a function may return a vector. With
backend="numpy" the functions are plain numpy and gradient methods use finite differences; argument="dict" passes the
parameters by name. A point is feasible when every violation is at most tol (default 1e-3); an impossible problem is
reported as feasible=False, never hidden.
Reference problem¶
examples/physics_optimizer/01_constrained_shape_six_methods.py: the torsional rigidity (integral of u for
-laplace(u) = 1, u = 0 on the boundary) of an a x b rectangle from the differentiable finite-element solver,
maximised at fixed area. The square a = b = 1 is the known optimum. All six methods find it:
| Method | a, b | value | violation | evaluations |
|---|---|---|---|---|
| slsqp | 1, 1 | -0.0340297 | 1e-14 | 17 |
| adjoint | 1, 1 | -0.0340297 | 1e-14 | 17 |
| penalty | 1.001, 0.999 | -0.0340298 | 3e-6 | 3001 |
| augmented_lagrangian | 1, 1 | -0.0340297 | 2e-9 | 2001 |
| differential_evolution | 1, 1 | -0.0340637 | 5e-4 | 605 |
| bayesian | 0.998, 1.003 | -0.0340975 | 1e-3 | 61 |
The gradient methods are the cheapest in evaluations when gradients exist; Bayesian optimisation reaches the same answer in
61 evaluations without gradients, which is the one to use when each evaluation is an expensive simulation. Optimal control
and MPC are not part of this interface (roadmap X32); the existing pinneapple_design.design_optimizer pipeline is unchanged.