Optimization¤
The optimizers that solve constrained form-finding problems, plus recorders to replay an optimization history.
Base optimizers¤
Optimizer
¤
The base class for optimizers backed by scipy.optimize.minimize.
Parameters:
-
disp(bool, default:False) –Whether the SciPy backend prints its own console output. Off by default since jax_fdm prints its own progress.
Notes
Subclasses set name to their SciPy method identity and override the
gradient, hessian, constraint, or minimization hooks as needed. problem
assembles the objective, its gradient, bounds, and goal collections into an
OptProblem, which solve then minimizes.
pm
property
writable
¤
pm: ParameterManager
The parameter manager, set up by problem() before a solve.
loads_static
property
writable
¤
loads_static: LoadsStatic
The static edge and face loads, set up by problem() before a solve.
constraints
¤
constraints(constraints: Sequence[Constraint], model: EquilibriumModel, structure: EquilibriumStructure, params_opt: Float[Array, parameters]) -> list[Any] | None
Convert constraints into the form the SciPy backend expects.
Parameters:
-
constraints(Sequence[Constraint]) –The constraints to convert.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure the constraints are defined on.
-
params_opt(Float[Array, parameters]) –The initial optimization parameters.
Returns:
gradient
¤
hessian
¤
loss
¤
loss(params_opt: Float[Array, parameters], loss: Loss, model: EquilibriumModel, structure: EquilibriumStructure) -> Float[Array, '']
Evaluate the loss from a flat optimization parameter vector.
Parameters:
-
params_opt(Float[Array, parameters]) –The flat optimization parameter vector.
-
loss(Loss) –The loss function to evaluate.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure that provides the connectivity.
Returns:
-
loss(Float[Array, '']) –The scalar loss value.
Notes
Expands the optimization vector into FDM parameters before calling the loss, so the optimizer can work in the reduced parameter space.
goals
¤
goals(loss: Loss, model: EquilibriumModel, structure: EquilibriumStructure) -> None
Collect and bind the loss's goals to a structure ahead of the solve.
Parameters:
-
loss(Loss) –The loss function whose error terms hold the goals.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure the goals are bound to.
Notes
Goals are batched into collections; each collection resolves its own index against the structure inside the jitted objective, once at trace time.
problem
¤
problem(model: EquilibriumModel, structure: EquilibriumStructure, datastructure: FDNetwork | FDMesh, loss: Loss, parameters: Sequence[Parameter] | None = None, constraints: Sequence[Constraint] | None = None, maxiter: int = 100, tol: float = 1e-06, callback: Callable | None = None, jit_fn: bool = True) -> OptProblem
Assemble an optimization problem from a model, loss, and parameters.
Parameters:
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure that provides the connectivity.
-
datastructure(FDNetwork | FDMesh) –The network or mesh being optimized.
-
loss(Loss) –The loss function to minimize.
-
parameters(Sequence[Parameter] | None, default:None) –The optimization parameters. If None, every edge force density is used.
-
constraints(Sequence[Constraint] | None, default:None) –The constraints to enforce. If None, the problem is unconstrained.
-
maxiter(int, default:100) –The maximum number of optimizer iterations.
-
tol(float, default:1e-06) –The convergence tolerance.
-
callback(Callable | None, default:None) –A function invoked once per iteration.
-
jit_fn(bool, default:True) –Whether to just-in-time compile the objective and hessian.
Returns:
-
problem(OptProblem) –The assembled optimization problem.
Notes
Warms up the compiled objective once and asserts the gradient is nan-free before returning, so compilation cost and gradient bugs surface up front.
options
¤
Assemble the backend options dictionary.
Parameters:
-
extra(dict[str, Any] | None, default:None) –Extra options to merge in, such as
maxiter. None-valued entries are skipped.
Returns:
Raises:
-
ValueError–If
extrais given but is not a dictionary.
solve
¤
solve(opt_problem: OptProblem) -> Float[Array, parameters]
Minimize an assembled optimization problem.
Parameters:
-
opt_problem(OptProblem) –The problem to minimize.
Returns:
-
params_opt(Float[Array, parameters]) –The optimized parameter vector.
Notes
Also stores the full SciPy result on self.result and prints the final
loss, gradient norm, and iteration counts.
parameters_bounds
¤
Return the lower and upper bounds of the optimization parameters.
Most backends consume a scipy Bounds object; IPOPT overrides this
to return a list of (low, high) pairs instead.
parameters_value
¤
parameters_value() -> Float[Array, parameters]
Return the initial values of the optimization parameters.
Returns:
-
values(Float[Array, parameters]) –The flat initial optimization parameter vector.
parameters_fdm
¤
parameters_fdm(params_opt: Float[Array, parameters]) -> EquilibriumParametersState
Expand optimization parameters into a full FDM parameter state.
Parameters:
-
params_opt(Float[Array, parameters]) –The flat optimization parameter vector.
Returns:
-
params_state(EquilibriumParametersState) –The force densities, fixed coordinates, and loads, with the static edge and face loads restored.
ConstrainedOptimizer
¤
A gradient-based optimizer that handles constraints.
constraints
¤
constraints(constraints: Sequence[Constraint], model: EquilibriumModel, structure: EquilibriumStructure, params_opt: Float[Array, parameters]) -> list[Any] | None
Convert constraints into SciPy NonlinearConstraint objects.
Parameters:
-
constraints(Sequence[Constraint]) –The constraints to convert.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure the constraints are defined on.
-
params_opt(Float[Array, parameters]) –The initial optimization parameters, used to warm up the jitted constraint and its Jacobian.
Returns:
Notes
Each constraint carries a jitted value function and a forward-mode Jacobian.
Subclasses may return a different container: IPOPT returns cyipopt
constraint dictionaries instead.
constraint
¤
constraint(params_opt: Float[Array, parameters], constraint: Constraint, model: EquilibriumModel, structure: EquilibriumStructure) -> Float[Array, constraints]
Evaluate a constraint from a flat optimization parameter vector.
Parameters:
-
params_opt(Float[Array, parameters]) –The flat optimization parameter vector.
-
constraint(Constraint) –The constraint to evaluate.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure that provides the connectivity.
Returns:
-
values(Float[Array, constraints]) –The constrained quantity for each element, flattened.
Notes
A constraint maps one element to one value, so a collection is reduced the
equinox way: solve for equilibrium once, then vmap the single-element
constraint over the collection's leading axis and flatten. The optimizer
owns the vmap, mirroring how Error maps a goal over its collection.
GradientFreeOptimizer
¤
The base class for optimizers that minimize without gradients.
Notes
Overrides problem to build an objective without a gradient or hessian,
so the loss is only jitted for its value. Constraints are not supported.
problem
¤
problem(model: EquilibriumModel, structure: EquilibriumStructure, datastructure: FDNetwork | FDMesh, loss: Loss, parameters: Sequence[Parameter] | None = None, constraints: Sequence[Constraint] | None = None, maxiter: int = 100, tol: float = 1e-06, callback: Callable | None = None, jit_fn: bool = True) -> OptProblem
Assemble a gradient-free optimization problem.
Parameters:
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure that provides the connectivity.
-
datastructure(FDNetwork | FDMesh) –The network or mesh being optimized.
-
loss(Loss) –The loss function to minimize.
-
parameters(Sequence[Parameter] | None, default:None) –The optimization parameters. If None, every edge force density is used.
-
constraints(Sequence[Constraint] | None, default:None) –Ignored; gradient-free optimizers do not support constraints.
-
maxiter(int, default:100) –The maximum number of optimizer iterations.
-
tol(float, default:1e-06) –The convergence tolerance.
-
callback(Callable | None, default:None) –A function invoked once per iteration.
-
jit_fn(bool, default:True) –Whether to just-in-time compile the objective.
Returns:
-
problem(OptProblem) –The assembled optimization problem, without a gradient or hessian.
solve
¤
solve(opt_problem: OptProblem) -> Float[Array, parameters]
Minimize an assembled gradient-free problem.
Parameters:
-
opt_problem(OptProblem) –The problem to minimize.
Returns:
-
params_opt(Float[Array, parameters]) –The optimized parameter vector.
SecondOrderOptimizer
¤
A gradient-based optimizer that uses the hessian to accelerate convergence.
hessian
¤
Build the hessian of a loss function by nested autodiff.
Parameters:
-
loss(Callable) –The loss function to differentiate twice.
Returns:
-
hessian(Callable) –The hessian with respect to the optimization parameters.
Notes
Composed as jacfwd(jacrev(...)), which matches the speed of a dedicated
hessian, whereas jacrev(jacfwd(...)) is about three times slower.
Gradient-based optimizers¤
GradientDescent
¤
A vanilla gradient descent optimizer with a fixed learning rate.
Parameters:
-
learning_rate(float, default:0.01) –The step size applied to the negative gradient at each iteration.
LBFGSB
¤
LBFGSB(disp: bool = False, maxfun: int | None = None, maxls: int | None = None, maxcor: int | None = None, **kwargs: Any)
The limited-memory BFGS optimizer with box bounds (L-BFGS-B).
Parameters:
-
disp(bool, default:False) –Whether the SciPy backend prints its own console output.
-
maxfun(int | None, default:None) –The maximum number of function evaluations. If None, the backend default.
-
maxls(int | None, default:None) –The maximum number of line-search steps per iteration. If None, the backend default.
-
maxcor(int | None, default:None) –The number of correction pairs approximating the hessian. If None, the backend default.
LBFGSBS
¤
LBFGSBS(disp: bool = False, maxfun: int | None = None, maxls: int | None = None, maxcor: int | None = None, **kwargs: Any)
An L-BFGS-B variant that converts JAX gradients to NumPy for SciPy.
Notes
Wrapping each gradient in a NumPy array sidesteps SciPy compatibility issues with JAX arrays, at the cost of being slower than LBFGSB.
SLSQP
¤
The sequential least-squares programming optimizer.
TruncatedNewton
¤
Minimize a scalar function of one or more variables using a truncated Newton (TNC) algorithm.
TrustRegionConstrained
¤
A trust-region algorithm for constrained optimization.
Second-order optimizers¤
NewtonCG
¤
The truncated Newton method. It uses a CG method to the compute the search direction.
TrustRegionExact
¤
A nearly exact trust-region optimization algorithm.
TrustRegionKrylov
¤
A trust-region optimization algorithm.
It uses a nearly exact trust-region algorithm that only requires matrix vector products with the hessian matrix.
TrustRegionNewton
¤
A Newton conjugate gradient trust-region algorithm. A trust-region algorithm for unconstrained optimization.
Interior-point optimizers¤
Requires the ipopt extra.
IPOPT
¤
The interior point optimizer (Ipopt) for large-scale nonlinear optimization.
Parameters:
-
acc_tol(float, default:1e-09) –The acceptable convergence tolerance Ipopt may settle for.
Notes
Supports box bounds and both equality and inequality constraints. Ipopt expects the loss and constraint functions to be twice differentiable, so this optimizer supplies hessians and constraint hessian-vector products.
constraint_eq
¤
constraint_eq(params_opt: Float[Array, parameters], constraint: Constraint, model: EquilibriumModel, structure: EquilibriumStructure) -> Float[Array, constraints]
The residual of an equality constraint, zero when satisfied.
Parameters:
-
params_opt(Float[Array, parameters]) –The flat optimization parameter vector.
-
constraint(Constraint) –The constraint to evaluate.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure that provides the connectivity.
Returns:
-
residual(Float[Array, constraints]) –The constrained quantity minus its (shared) bound.
constraint_ineq_up
¤
constraint_ineq_up(params_opt: Float[Array, parameters], constraint: Constraint, model: EquilibriumModel, structure: EquilibriumStructure) -> Float[Array, constraints]
The slack against a constraint's upper bound, non-negative when satisfied.
Parameters:
-
params_opt(Float[Array, parameters]) –The flat optimization parameter vector.
-
constraint(Constraint) –The constraint to evaluate.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure that provides the connectivity.
Returns:
-
slack(Float[Array, constraints]) –The upper bound minus the constrained quantity.
constraint_ineq_low
¤
constraint_ineq_low(params_opt: Float[Array, parameters], constraint: Constraint, model: EquilibriumModel, structure: EquilibriumStructure) -> Float[Array, constraints]
The slack against a constraint's lower bound, non-negative when satisfied.
Parameters:
-
params_opt(Float[Array, parameters]) –The flat optimization parameter vector.
-
constraint(Constraint) –The constraint to evaluate.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure that provides the connectivity.
Returns:
-
slack(Float[Array, constraints]) –The constrained quantity minus its lower bound.
hvp
staticmethod
¤
hvp(x: Float[Array, parameters], v: Float[Array, constraints], f: Callable) -> Float[Array, 'parameters parameters']
The constraint hessian contracted with the Lagrange multipliers.
Parameters:
-
x(Float[Array, parameters]) –The point to evaluate the hessian-vector product at.
-
v(Float[Array, constraints]) –The vector of Lagrange multipliers, one per constraint component.
-
f(Callable) –The vector-valued constraint function.
Returns:
-
hvp(Float[Array, 'parameters parameters']) –The sum of each constraint component's hessian scaled by its multiplier, applied at
x.
parameters_bounds
¤
constraints
¤
constraints(constraints: Sequence[Constraint], model: EquilibriumModel, structure: EquilibriumStructure, params_opt: Float[Array, parameters]) -> list[dict[str, Any]]
Convert constraints into cyipopt constraint dictionaries.
Parameters:
-
constraints(Sequence[Constraint]) –The constraints to convert.
-
model(EquilibriumModel) –The equilibrium model.
-
structure(EquilibriumStructure) –The structure the constraints are defined on.
-
params_opt(Float[Array, parameters]) –The initial optimization parameters, used to warm up the jitted functions.
Returns:
-
constraints(list[dict[str, Any]]) –One dictionary per constraint side, each with a value function, its Jacobian, and its hessian-vector product.
Notes
An equal lower and upper bound yields a single equality constraint; otherwise each finite bound becomes its own one-sided inequality.
Gradient-free optimizers¤
NelderMead
¤
The Nelder-Mead gradient-free optimizer with box constraints.
Powell
¤
The modified Powell algorithm for gradient-free optimization with box constraints.
DifferentialEvolution
¤
DifferentialEvolution(popsize: int = 20, vectorized: bool = False, num_workers: int = 1, seed: int = 43, **kwargs: Any)
A differential evolution global optimizer with box bounds.
Parameters:
-
popsize(int, default:20) –The population size multiplier.
-
vectorized(bool, default:False) –If True, the objective is vmapped over the whole population per generation.
-
num_workers(int, default:1) –The number of parallel workers used to evaluate the population.
-
seed(int, default:43) –The random seed. This algorithm has stochastic components, so mind the seed for reproducibility.
Notes
Local polishing is disabled, so the result is the best population member found.
DualAnnealing
¤
Recording¤
optimization
¤
OptimizationRecorder
¤
OptimizationRecorder(optimizer: Optimizer | None = None)
A COMPAS data object that logs the parameters visited during optimization.
Parameters:
-
optimizer(Optimizer | None, default:None) –The optimizer whose iterates are recorded. If given, each iterate is expanded into FDM parameters before storing; if None, raw iterates are stored as a flat list.
Notes
As a COMPAS Data subclass the history serializes to and from JSON, so an
optimization run can be saved and replayed.
__call__
¤
__call__(xk: Float[Array, parameters], *args: Any, **kwargs: Any) -> None
Record one optimizer iterate; suitable as an optimizer callback.
Parameters:
-
xk(Float[Array, parameters]) –The current flat optimization parameter vector.
-
args(Any, default:()) –Extra positional callback arguments, ignored.
-
kwargs(Any, default:{}) –Extra keyword callback arguments, ignored.
record
¤
record(parameters: Any) -> None
Append one set of parameters to the history.
Parameters:
-
parameters(Any) –The parameters to store. With an optimizer, a parameter state whose leaves are appended into the history's matching leaves; without one, a single value appended to the flat history list.