ProblemLite

ProblemLite features a minimal API, allowing users to wrap a problem model with a single line of code once the problem functions and constants are defined.

Define a problem using modOpt’s ProblemLite class

This example does not intend to cover all the features of the ProblemLite class. For more details on ProblemLite, please see the API Reference. In this example, we solve a constrained problem given by

\[ \begin{align}\begin{aligned} \underset{x_1, x_2 \in \mathbb{R}}{\text{minimize}} \quad x_1^2 + x_2^2\\\newline \text{subject to} \quad x_1 \geq 0 \newline \quad \quad \quad \quad x_1 + x_2 = 1 \newline \quad \quad \quad \quad x_1 - x_2 \geq 1 \end{aligned}\end{align} \]

We know the solution of this problem is \(x_1=1\), and \(x_2=0\). However, we start from an initial guess of \(x_1=500.0\), and \(x_2=5.0\) for the purposes of this tutorial.

The problem functions are first written as follows:

import numpy as np

# minimize x^2 + y^2 subject to x>=0, x+y=1, x-y>=1.

# Define problem constants
x0 = np.array([500., 5.])           # Initial guess
xl = np.array([0., -np.inf])        # Variable lower bounds
cl = np.array([1., 1.])             # Constraint lower bounds
cu = np.array([1., np.inf])         # Constraint upper bounds

# Define problem functions
def objective(x):
    return np.sum(x**2)

def objective_gradient(x):    
    return 2 * x

def constraint(x):
    return np.array([x[0] + x[1], x[0] - x[1]])

def constraint_jacobian(x):
    return np.array([[1., 1], [1., -1]])

If the problem functions and constants are all available as shown above, create a ProblemLite object by passing them in. Note that ProblemLite is just a container for the problem functions and constants, designed to simplify setups for straightforward problems and those modeled outside of modOpt. However, it requires users to combine all variables and constraints into single vectors.

import modopt as mo

prob = mo.ProblemLite(x0, 
                      obj=objective,
                      grad=objective_gradient,
                      con=constraint,
                      jac=constraint_jacobian,
                      cl=cl, 
                      cu=cu,
                      xl=xl,
                      name='quadratic_lite')
/Users/modopt/modopt/core/problem_lite.py:198: UserWarning: Objective Hessian function "obj_hess" not provided. Finite differences will be used if objective Hessian computation is necessary.
  warnings.warn('Objective Hessian function "obj_hess" not provided. Finite differences will be used if objective Hessian computation is necessary.')
/Users/modopt/modopt/core/problem_lite.py:209: UserWarning: Lagrangian Hessian function "lag_hess" not provided. Finite differences will be used if Lagrangian Hessian computation is necessary.
  warnings.warn('Lagrangian Hessian function "lag_hess" not provided. Finite differences will be used if Lagrangian Hessian computation is necessary.')

Solve your problem using an optimizer

Once your problem model is wrapped for modOpt, import your preferred optimizer from modOpt and solve it, following the standard procedure. Here we will use the SLSQP optimizer from the SciPy library.

# Setup your preferred optimizer (SLSQP) with the Problem object 
# Pass in the options for your chosen optimizer
optimizer = mo.SLSQP(prob, solver_options={'maxiter':20})

# Check first derivatives at the initial guess, if needed
optimizer.check_first_derivatives(prob.x0)

# Solve your optimization problem
optimizer.solve()

# Print results of optimization
optimizer.print_results()
----------------------------------------------------------------------------
Derivative type | Calc norm  | FD norm    | Abs error norm | Rel error norm 
----------------------------------------------------------------------------

Gradient        | 1.0000e+03 | 1.0000e+03 | 1.5473e-05     | 1.5472e-08    
Jacobian        | 2.0000e+00 | 2.0000e+00 | 5.0495e-09     | 2.5248e-09    
----------------------------------------------------------------------------


	Solution from Scipy SLSQP:
	----------------------------------------------------------------------------------------------------
	Problem                  : quadratic_lite
	Solver                   : scipy-slsqp
	Success                  : True
	Message                  : Optimization terminated successfully
	Status                   : 0
	Total time               : 0.0016057491302490234
	Objective                : 1.0000000068019972
	Gradient norm            : 2.000000006801997
	Total function evals     : 2
	Total gradient evals     : 2
	Major iterations         : 2
	Total callbacks          : 17
	Reused callbacks         : 0
	obj callbacks            : 5
	grad callbacks           : 3
	hess callbacks           : 0
	con callbacks            : 6
	jac callbacks            : 3
	----------------------------------------------------------------------------------------------------

Scaling API

Please refer to the code snippet below as a guide for scaling the design variables, objective, and constraints independent of their definitions.

Warning

The results provided by the optimizer will always be scaled, while the values from the models will remain unscaled.

prob = mo.ProblemLite(x0, 
                      obj=objective,
                      grad=objective_gradient,
                      con=constraint,
                      jac=constraint_jacobian,
                      cl=cl, 
                      cu=cu,
                      xl=xl,
                      x_scaler=2., # constant to scale all variables
                    # x_scaler=np.array([1., 2.]), # scaler to scale each variable differently
                      o_scaler=5., # objective function scaler
                    # c_scaler=10., # constant to scale all constraints
                      c_scaler=np.array([10., 100.]), # scaler to scale each constraint differently
                      name='quadratic_lite_scaled')

optimizer = mo.SLSQP(prob, solver_options={'maxiter':20})
optimizer.solve()
optimizer.print_results()
	Solution from Scipy SLSQP:
	----------------------------------------------------------------------------------------------------
	Problem                  : quadratic_lite_scaled
	Solver                   : scipy-slsqp
	Success                  : True
	Message                  : Optimization terminated successfully
	Status                   : 0
	Total time               : 0.0033338069915771484
	Objective                : 4.999999999999996
	Gradient norm            : 4.999999878155281
	Total function evals     : 3
	Total gradient evals     : 2
	Major iterations         : 2
	Total callbacks          : 11
	Reused callbacks         : 0
	obj callbacks            : 3
	grad callbacks           : 2
	hess callbacks           : 0
	con callbacks            : 4
	jac callbacks            : 2
	----------------------------------------------------------------------------------------------------