Note
Go to the end to download the full example code.
Create an MDO Scenario#
from __future__ import annotations
from numpy import ones
from gemseo import configure_logger
from gemseo import create_design_space
from gemseo import create_discipline
from gemseo import create_scenario
from gemseo import get_available_opt_algorithms
from gemseo import get_available_post_processings
configure_logger()
<RootLogger root (INFO)>
Let \((P)\) be a simple optimization problem:
In this subsection, we will see how to use GEMSEO to solve this problem \((P)\) by means of an optimization algorithm.
Define the discipline#
Firstly, by means of the high-level function create_discipline(),
we create an Discipline of AnalyticDiscipline type
from a Python function:
expressions = {"y": "sin(x)-exp(x)"}
discipline = create_discipline("AnalyticDiscipline", expressions=expressions)
We can quickly access the most relevant information of any discipline (name, inputs,
and outputs) with their string representations. Moreover, we can get the default
input values of a discipline with the attribute Discipline.default_input_data
discipline, discipline.default_input_data
(AnalyticDiscipline
Inputs: x
Outputs: y, {'x': array([0.])})
Now, we can minimize an output of this Discipline over a design space,
by means of a quasi-Newton method from the initial point \(0.5\).
Define the design space#
For that, by means of the high-level function create_design_space(),
we define the DesignSpace \([-2, 2]\) with initial value \(0.5\)
by using its DesignSpace.add_variable() method.
design_space = create_design_space()
design_space.add_variable("x", lower_bound=-2.0, upper_bound=2.0, value=-0.5 * ones(1))
Define the MDO scenario#
Then, by means of the create_scenario() API function,
we define an MDOScenario from the Discipline
and the DesignSpace defined above:
scenario = create_scenario(
discipline, "y", design_space, formulation_name="DisciplinaryOpt"
)
What about the differentiation method?#
The AnalyticDiscipline automatically differentiates the
expressions to obtain the Jacobian matrices. Therefore, there is no need to
define a differentiation method in this case. Keep in mind that for a
generic discipline with no defined Jacobian function, you can use the
Scenario.set_differentiation_method() method to define a numerical
approximation of the gradients.
scenario.set_differentiation_method("finite_differences")
Execute the MDO scenario#
Lastly, we solve the OptimizationProblem included in the
MDOScenario defined above by minimizing the objective function over
the DesignSpace. Precisely, we choose the L-BFGS-B algorithm implemented in the
function scipy.optimize.fmin_l_bfgs_b.
scenario.execute(algo_name="L-BFGS-B", max_iter=100)
INFO - 08:35:55:
INFO - 08:35:55: *** Start MDOScenario execution ***
INFO - 08:35:55: MDOScenario
INFO - 08:35:55: Disciplines: AnalyticDiscipline
INFO - 08:35:55: MDO formulation: DisciplinaryOpt
INFO - 08:35:55: Optimization problem:
INFO - 08:35:55: minimize y(x)
INFO - 08:35:55: with respect to x
INFO - 08:35:55: over the design space:
INFO - 08:35:55: +------+-------------+-------+-------------+-------+
INFO - 08:35:55: | Name | Lower bound | Value | Upper bound | Type |
INFO - 08:35:55: +------+-------------+-------+-------------+-------+
INFO - 08:35:55: | x | -2 | -0.5 | 2 | float |
INFO - 08:35:55: +------+-------------+-------+-------------+-------+
INFO - 08:35:55: Solving optimization problem with algorithm L-BFGS-B:
INFO - 08:35:55: 1%| | 1/100 [00:00<00:00, 484.89 it/sec, obj=-1.09]
INFO - 08:35:55: 2%|▏ | 2/100 [00:00<00:00, 576.10 it/sec, obj=-1.04]
INFO - 08:35:55: 3%|▎ | 3/100 [00:00<00:00, 696.54 it/sec, obj=-1.24]
INFO - 08:35:55: 4%|▍ | 4/100 [00:00<00:00, 723.47 it/sec, obj=-1.23]
INFO - 08:35:55: 5%|▌ | 5/100 [00:00<00:00, 745.02 it/sec, obj=-1.24]
INFO - 08:35:55: 6%|▌ | 6/100 [00:00<00:00, 752.48 it/sec, obj=-1.24]
INFO - 08:35:55: 7%|▋ | 7/100 [00:00<00:00, 760.53 it/sec, obj=-1.24]
INFO - 08:35:55: Optimization result:
INFO - 08:35:55: Optimizer info:
INFO - 08:35:55: Status: 0
INFO - 08:35:55: Message: CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL
INFO - 08:35:55: Number of calls to the objective function by the optimizer: 8
INFO - 08:35:55: Solution:
INFO - 08:35:55: Objective: -1.2361083418592416
INFO - 08:35:55: Design space:
INFO - 08:35:55: +------+-------------+--------------------+-------------+-------+
INFO - 08:35:55: | Name | Lower bound | Value | Upper bound | Type |
INFO - 08:35:55: +------+-------------+--------------------+-------------+-------+
INFO - 08:35:55: | x | -2 | -1.292695718944152 | 2 | float |
INFO - 08:35:55: +------+-------------+--------------------+-------------+-------+
INFO - 08:35:55: *** End MDOScenario execution (time: 0:00:00.013306) ***
The optimum results can be found in the execution log. It is also possible to
access them with Scenario.optimization_result:
optimization_result = scenario.optimization_result
f"The solution of P is (x*, f(x*)) = ({optimization_result.x_opt}, {optimization_result.f_opt})"
'The solution of P is (x*, f(x*)) = ([-1.29269572], -1.2361083418592416)'
See also
You can find the SciPy implementation of the L-BFGS-B algorithm algorithm by clicking here.
Available algorithms#
In order to get the list of available optimization algorithms, use:
get_available_opt_algorithms()
['Augmented_Lagrangian_order_0', 'Augmented_Lagrangian_order_1', 'MNBI', 'MultiStart', 'NLOPT_MMA', 'NLOPT_COBYLA', 'NLOPT_SLSQP', 'NLOPT_BOBYQA', 'NLOPT_BFGS', 'NLOPT_NEWUOA', 'DUAL_ANNEALING', 'SHGO', 'DIFFERENTIAL_EVOLUTION', 'INTERIOR_POINT', 'DUAL_SIMPLEX', 'Scipy_MILP', 'SLSQP', 'L-BFGS-B', 'TNC', 'NELDER-MEAD']
Available post-processing#
In order to get the list of available post-processing algorithms, use:
get_available_post_processings()
['Animation', 'BasicHistory', 'ConstraintsHistory', 'Correlations', 'GradientSensitivity', 'HessianHistory', 'ObjConstrHist', 'OptHistoryView', 'ParallelCoordinates', 'ParetoFront', 'QuadApprox', 'RadarChart', 'Robustness', 'SOM', 'ScatterPlotMatrix', 'TopologyView', 'VariableInfluence']
Exporting the problem data.#
After the execution of the scenario, you may want to export your data to use it
elsewhere. The Scenario.to_dataset() will allow you to export your
results to a Dataset, the basic GEMSEO class to store data.
dataset = scenario.to_dataset("a_name_for_my_dataset")
You can also look at the examples:
Total running time of the script: (0 minutes 0.033 seconds)