L2PenaltyEq
Options table
Option |
Type |
Default Value |
Description |
|---|---|---|---|
problem |
Problem or ProblemLite |
None |
Object containing the problem to be solved. |
recording |
bool |
False |
If |
out_dir |
str |
None |
The directory to store all the output files generated from the optimization. |
hot_start_from |
str |
None |
The record file from which to hot-start the optimization. |
hot_start_atol |
float |
0. |
The absolute tolerance check for the inputs when reusing outputs from the hot-start record. |
hot_start_rtol |
float |
0. |
The relative tolerance check for the inputs when reusing outputs from the hot-start record. |
visualize |
list |
[] |
The list of scalar variables to visualize during the optimization. |
keep_viz_open |
bool |
False |
If |
turn_off_outputs |
bool |
False |
If |
maxiter |
int |
1000 |
Maximum number of iterations. |
opt_tol |
float |
1e-6 |
Optimality tolerance. Certifies convergence when the 2-norm of the gradient of the Quadratic Penalty function is less than this value. |
feas_tol |
float |
1e-6 |
Feasibility tolerance. Certifies convergence when the 2-norm of the constraints (constraint violations) is less than this value. |
rho |
float |
1000000. |
Penalty parameter. |
readable_outputs |
list |
[] |
List of outputs to be written to readable text output files. Available outputs are: ‘itr’, ‘obj’, ‘con’, ‘x’, ‘opt’, ‘feas’, ‘time’, ‘nfev’, ‘ngev’, ‘step’, ‘merit’. |
Source code
import numpy as np
import time
from modopt import Optimizer
from modopt.line_search_algorithms import ScipyLS, BacktrackingArmijo
from modopt.merit_functions import AugmentedLagrangianEq, L2Eq
# from modopt.approximate_hessians import BFGS
from modopt.approximate_hessians import BFGSM1 as BFGS
from modopt.core.approximate_hessians.bfgs_function import bfgs_update
class L2PenaltyEq(Optimizer):
"""
Quadratic penalty method for equality-constrained optimization.
Parameters
----------
problem : Problem or ProblemLite
Object containing the problem to be solved.
recording : bool, default=False
If ``True``, record all outputs from the optimization.
This needs to be enabled for hot-starting the same problem later,
if the optimization is interrupted.
out_dir : str, optional
The directory to store all the output files generated from the optimization.
hot_start_from : str, optional
The record file from which to hot-start the optimization.
hot_start_atol : float, default=0.
The absolute tolerance check for the inputs
when reusing outputs from the hot-start record.
hot_start_rtol : float, default=0.
The relative tolerance check for the inputs
when reusing outputs from the hot-start record.
visualize : list, default=[]
The list of scalar variables to visualize during the optimization.
keep_viz_open : bool, default=False
If ``True``, keep the visualization window open after the optimization is complete.
turn_off_outputs : bool, default=False
If ``True``, prevent modOpt from generating any output files.
maxiter : int, default=1000
Maximum number of iterations.
opt_tol : float, default=1e-6
Optimality tolerance.
Certifies convergence when the 2-norm of the gradient of
the Quadratic Penalty function is less than this value.
feas_tol : float, default=1e-6
Feasibility tolerance.
Certifies convergence when the 2-norm of the constraints (constraint violations)
is less than this value.
rho : float, default=1000000.
Penalty parameter.
readable_outputs : list, default=[]
List of outputs to be written to readable text output files.
Available outputs are: 'itr', 'obj', 'con', 'x', 'opt', 'feas',
'time', 'nfev', 'ngev', 'step', 'merit'.
"""
def initialize(self):
self.solver_name = 'l2_penalty_eq'
self.obj = self.problem._compute_objective
self.grad = self.problem._compute_objective_gradient
self.con = self.problem._compute_constraints
self.jac = self.problem._compute_constraint_jacobian
self.options.declare('maxiter', default=1000, types=int)
self.options.declare('opt_tol', default=1e-6, types=float)
self.options.declare('feas_tol', default=1e-6, types=float)
self.options.declare('rho', types=float, default=1000000.)
self.options.declare('readable_outputs', types=list, default=[])
self.available_outputs = {
'itr': int,
'obj': float,
'con': (float, (self.problem.nc, )),
# for arrays from each iteration, sizes need to be declared
'x': (float, (self.problem.nx, )),
'opt': float,
'feas': float,
'time': float,
'nfev': int,
'ngev': int,
'step': float,
'merit': float,
}
def setup(self):
nx = self.problem.nx
nc = self.problem.nc
self.OF = L2Eq(nx=nx,
nc=nc,
f=self.obj,
c=self.con,
g=self.grad,
j=self.jac)
self.LS = BacktrackingArmijo(f=self.OF.compute_function,
g=self.OF.compute_gradient)
# self.LS = ScipyLS(f=self.OF.compute_function,
# g=self.OF.compute_gradient)
self.QN = BFGS(nx=self.problem.nx)
def solve(self):
# Assign shorter names to variables and methods
nx = self.problem.nx
nc = self.problem.nc
x0 = self.problem.x0
opt_tol = self.options['opt_tol']
feas_tol = self.options['feas_tol']
maxiter = self.options['maxiter']
rho = self.options['rho']
obj = self.obj
grad = self.grad
con = self.con
jac = self.jac
LS = self.LS
QN = self.QN
OF = self.OF
start_time = time.time()
# Set intial values for current iterates
x_k = x0 * 1.
f_k = obj(x_k)
g_k = grad(x_k)
c_k = con(x_k)
J_k = jac(x_k)
OF.set_rho(rho)
of_k = OF.evaluate_function(x_k, f_k, c_k)
ofg_k = OF.evaluate_gradient(x_k, f_k, c_k, g_k, J_k)
# Iteration counter
itr = 0
opt = np.linalg.norm(ofg_k)
feas = np.linalg.norm(c_k)
nfev = 1
ngev = 1
# Initializing declared outputs
self.update_outputs(itr=0,
x=x_k,
obj=f_k,
con=c_k,
opt=opt,
feas=feas,
time=time.time() - start_time,
nfev=nfev,
ngev=ngev,
step=0.,
merit=of_k)
# B_k = np.identity(nx)
while ((opt > opt_tol or feas > feas_tol) and itr < maxiter):
itr_start = time.time()
itr += 1
# Hessian approximation
B_k = QN.B_k
# if itr % 2 == 0:
# B_k = np.diag(np.diag(B_k))
# ALGORITHM STARTS HERE
# >>>>>>>>>>>>>>>>>>>>>
# Compute the search direction toward the next iterate
p_k = np.linalg.solve(B_k, -ofg_k)
# print((x_k + p_k))
# Compute the step length along the search direction via a line search
# alpha, of_k, ofg_new, of_slope_new, new_f_evals, new_g_evals, converged = LS.search(
# x=x_k, p=p_k, f0=of_k, g0=ofg_k)
alpha, of_k, new_f_evals, new_g_evals, converged = LS.search(
x=x_k, p=p_k, f0=of_k, g0=ofg_k)
nfev += new_f_evals
ngev += new_g_evals
# A step of length 1e-4 is taken along p_k if line search does not converge
if not converged:
alpha = None
d_k = p_k * 1.
x_k += d_k
f_k = obj(x_k)
g_k = grad(x_k)
c_k = con(x_k)
J_k = jac(x_k)
of_k = OF.evaluate_function(x_k, f_k, c_k)
ofg_new = OF.evaluate_gradient(x_k, f_k, c_k, g_k, J_k)
w_k = (ofg_new - ofg_k)
ofg_k = ofg_new
else:
d_k = alpha * p_k
x_k += d_k
f_k = obj(x_k)
g_k = grad(x_k)
c_k = con(x_k)
J_k = jac(x_k)
# if ofg_new == 'Unavailable':
ofg_new = OF.evaluate_gradient(x_k, f_k, c_k, g_k, J_k)
w_k = (ofg_new - ofg_k)
ofg_k = ofg_new
nfev += 1
ngev += 1
opt = np.linalg.norm(ofg_k)
feas = np.linalg.norm(c_k)
# print(pi_k)
# Update the Hessian approximation
QN.update(d_k, w_k)
# B_k = self.problem.compute_lagrangian_hessian(x_k, pi_k)
# B_k = bfgs_update(B_k, d_k[:nx], w_k[:nx])
# <<<<<<<<<<<<<<<<<<<
# ALGORITHM ENDS HERE
# Update arrays inside outputs dict with new values from the current iteration
self.update_outputs(itr=itr,
x=x_k,
obj=f_k,
con=c_k,
opt=opt,
feas=feas,
time=time.time() - start_time,
nfev=nfev,
ngev=ngev,
step=alpha,
merit=of_k)
self.total_time = time.time() - start_time
converged = (opt <= opt_tol and feas <= feas_tol)
self.results = {
'x': x_k,
'objective': f_k,
'c': c_k,
'rho': rho,
'optimality': opt,
'feasibility': feas,
'nfev': nfev,
'ngev': ngev,
'niter': itr,
'time': self.total_time,
'converged': converged,
}
# Run post-processing for the Optimizer() base class
self.run_post_processing()
return self.results
API
- class modopt.L2PenaltyEq(problem, recording=False, out_dir=None, hot_start_from=None, hot_start_atol=0.0, hot_start_rtol=0.0, visualize=[], keep_viz_open=False, turn_off_outputs=False, **kwargs)[source]
Quadratic penalty method for equality-constrained optimization.
- Parameters
- problemProblem or ProblemLite
Object containing the problem to be solved.
- recordingbool, default=False
If
True, record all outputs from the optimization. This needs to be enabled for hot-starting the same problem later, if the optimization is interrupted.- out_dirstr, optional
The directory to store all the output files generated from the optimization.
- hot_start_fromstr, optional
The record file from which to hot-start the optimization.
- hot_start_atolfloat, default=0.
The absolute tolerance check for the inputs when reusing outputs from the hot-start record.
- hot_start_rtolfloat, default=0.
The relative tolerance check for the inputs when reusing outputs from the hot-start record.
- visualizelist, default=[]
The list of scalar variables to visualize during the optimization.
- keep_viz_openbool, default=False
If
True, keep the visualization window open after the optimization is complete.- turn_off_outputsbool, default=False
If
True, prevent modOpt from generating any output files.- maxiterint, default=1000
Maximum number of iterations.
- opt_tolfloat, default=1e-6
Optimality tolerance. Certifies convergence when the 2-norm of the gradient of the Quadratic Penalty function is less than this value.
- feas_tolfloat, default=1e-6
Feasibility tolerance. Certifies convergence when the 2-norm of the constraints (constraint violations) is less than this value.
- rhofloat, default=1000000.
Penalty parameter.
- readable_outputslist, default=[]
List of outputs to be written to readable text output files. Available outputs are: ‘itr’, ‘obj’, ‘con’, ‘x’, ‘opt’, ‘feas’, ‘time’, ‘nfev’, ‘ngev’, ‘step’, ‘merit’.
Methods
check_first_derivatives([x, step, formulation])Check the first derivatives of the optimization problem using finite differences.
print_results([summary_table, all])Print the results of the optimization problem to the terminal.
solve()Run the optimization algorithm to solve the problem.
- check_first_derivatives(x=None, step=1e-06, formulation='rs')
Check the first derivatives of the optimization problem using finite differences.
- Parameters
- xnp.ndarray, optional
The design variables at which the derivatives are to be checked. If not provided, the initial design variables are used.
- stepfloat, default=1e-6
The step size for the finite differences.
- print_results(summary_table=False, all=False)
Print the results of the optimization problem to the terminal.
- Parameters
- summary_tablebool, default=False
If
True, print the summary table for the optimization.- allbool, default=False
If
False, print only the scalar outputs of the optimization problem. Otherwise, print all the outputs of the optimization problem.
- solve()[source]
Run the optimization algorithm to solve the problem.