Optimization¶
Optimization problems can be solved with driver Optimizer
.
Optimizer
seeks a user-defined parameter set that minimizes a scalar objective.
Define an optimization problem¶
Optimization problems are defined using three driver methods:
set_minimum
orset_maximum
(as required)add_unknown
add_constraints
Add driver¶
from cosapp.drivers import Optimizer
s = SomeSystem('s')
optim = s.add_driver(Optimizer('optim'))
Set minimization or maximization objective¶
The argument passed to set_minimum
(resp. set_maximum
) must be a scalar expression evaluable in the context of owner system:
optim.set_minimum("a**2 + b.x * exp(c.p_out.y / 2)")
Define optimization parameters¶
Optimization parameters are declared with method add_unknown
, akin to nonlinear problem unknowns:
optim.add_unknown(['u', 'v'])
optim.add_unknown('alpha', lower_bound=0, upper_bound=1)
When specified, lower and upper bounds are used as linear constraints during resolution.
Define constraints¶
General constraints are given as plain strings (or a list thereof) in add_constraints
. Each constraint can either be an equality or an inequality. Inequalities are translated into non-negative constraints, whether the inequality is strict or not. For instance, x < y
will translate into y - x >= 0
.
Note that multiple constraints can be expressed in a single expression, as in: "a > b > c"
.
optim.add_constraints("0 <= b.y <= 2 * c.x") # yields two constraints
optim.add_constraints([
"0.1 <= h == sqrt(A)", # h >= 0.1 and h == sqrt(A)
"a + b < c", # interpreted as c - (a + b) >= 0
])
Options¶
Driver Optimizer
encapsulates function scipy.optimize.minimize. All methods implemented in minimize
(SLSQP, Conjugate Gradient, Nelder-Mead, etc.) are available, through optional argument method
.
The list of available methods is given by:
[1]:
from cosapp.drivers import Optimizer
Optimizer.available_methods()
[1]:
['Nelder-Mead',
'Powell',
'CG',
'BFGS',
'Newton-CG',
'L-BFGS-B',
'TNC',
'COBYLA',
'SLSQP',
'dogleg',
'trust-constr',
'trust-ncg',
'trust-exact',
'trust-krylov']
Other options are:
tol
[float]: Relative tolerance on objective value between two iterations (default: 1.5e-8).eps
[float]: Relative step size used for numerical approximation of the Jacobian (default: 2^(-26) ~ 1.49e-8).max_iter
[int]: Maximum number of iterations (default: 100).monitor
[bool]: IfTrue
, data are recorded into driver recorder (if any) at all iterations; ifFalse
(default), only the final state is recorded.
Options may be set at driver construction (as keyword arguments), or by setting the desired key in dict attribute options
, as in:
optim.options['tol'] = 1e-9
optim.options['max_iter'] = 50