OpenMDAO example

This examples uses the paropt_driver for OpenMDAO to solve the following optimization problem:

\[\begin{split}\begin{align} \text{min} \qquad & (x-3)^2 + xy + (y+4)^2 - 3 \\ \text{with respect to} \qquad & -50 \le x, y \le 50 \\ \text{subject to} \qquad & x + y \ge 0 \\ \end{align}\end{split}\]

Python implementation

The python implementation of this problem is as follows

from openmdao.api import (
    Problem,
    ScipyOptimizeDriver,
    pyOptSparseDriver,
    ExecComp,
    IndepVarComp,
)
from paropt.paropt_driver import ParOptDriver
import argparse

# Create an argument parser
parser = argparse.ArgumentParser()
parser.add_argument(
    "--driver",
    default="paropt",
    choices=["paropt", "scipy", "pyoptsparse"],
    help="driver",
)
parser.add_argument(
    "--algorithm", default="ip", choices=["ip", "tr", "mma"], help="optimizer type"
)
args = parser.parse_args()
driver = args.driver
algorithm = args.algorithm

# Build the model
prob = Problem()

# Define the independent variables
indeps = prob.model.add_subsystem("indeps", IndepVarComp())
indeps.add_output("x", 3.0)
indeps.add_output("y", -4.0)

# Define the objective and the constraint functions
prob.model.add_subsystem("paraboloid", ExecComp("f = (x-3)**2 + x*y + (y+4)**2 - 3"))
prob.model.add_subsystem("con", ExecComp("c = x**2 + y**2"))

# Connect the model
prob.model.connect("indeps.x", "paraboloid.x")
prob.model.connect("indeps.y", "paraboloid.y")
prob.model.connect("indeps.x", "con.x")
prob.model.connect("indeps.y", "con.y")

# Define the optimization problem
prob.model.add_design_var("indeps.x", lower=-50, upper=50)
prob.model.add_design_var("indeps.y", lower=-50, upper=50)
prob.model.add_objective("paraboloid.f")
prob.model.add_constraint("con.c", equals=27.0)

# Create and set the ParOpt driver
if driver == "paropt":
    prob.driver = ParOptDriver()
    prob.driver.options["algorithm"] = algorithm
elif driver == "scipy":
    prob.driver = ScipyOptimizeDriver()
elif driver == "pyoptsparse":
    prob.driver = pyOptSparseDriver()
    prob.driver.options["optimizer"] = "ParOpt"

# Run the problem
prob.setup()
prob.run_driver()

# Print the minimum value
print("Minimum value = {fmin:.2f}".format(fmin=prob["paraboloid.f"][0]))

# Print the x/y location of the minimum
print(
    "(x, y) = ({x:.2f}, {y:.2f})".format(x=prob["indeps.x"][0], y=prob["indeps.y"][0])
)
print("x**2 + y**2 = ", prob["indeps.x"][0] ** 2 + prob["indeps.y"][0] ** 2)

This code results in the output:

Minimum value = -27.00
(x, y) = (7.00, -7.00)