.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/scenario/plot_store_observables.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_scenario_plot_store_observables.py: Store observables ================= .. GENERATED FROM PYTHON SOURCE LINES 26-44 Introduction ------------ In this example, we will learn how to store the history of state variables using the :meth:`~gemseo.core.scenario.Scenario.add_observable` method. This is useful in situations where we wish to access, post-process, or save the values of discipline outputs that are not design variables, constraints or objective functions. The Sellar problem ------------------ We will consider in this example the Sellar problem: .. include:: /problems/sellar_problem_definition.inc Imports ------- All the imports needed for the tutorials are performed here. .. GENERATED FROM PYTHON SOURCE LINES 44-57 .. code-block:: Python from __future__ import annotations from numpy import array from numpy import ones from gemseo import configure_logger from gemseo import create_discipline from gemseo import create_scenario from gemseo.algos.design_space import DesignSpace configure_logger() .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 58-66 Create the problem disciplines ------------------------------ In this section, we use the available classes :class:`.Sellar1`, :class:`.Sellar2` and :class:`.SellarSystem` to define the disciplines of the problem. The :func:`.create_discipline` API function allows us to carry out this task easily, as well as store the instances in a list to be used later on. .. GENERATED FROM PYTHON SOURCE LINES 66-68 .. code-block:: Python disciplines = create_discipline(["Sellar1", "Sellar2", "SellarSystem"]) .. GENERATED FROM PYTHON SOURCE LINES 69-76 Create and execute the scenario ------------------------------- Create the design space ^^^^^^^^^^^^^^^^^^^^^^^ In this section, we define the design space which will be used for the creation of the MDOScenario. .. GENERATED FROM PYTHON SOURCE LINES 76-82 .. code-block:: Python design_space = DesignSpace() design_space.add_variable("x_local", l_b=0.0, u_b=10.0, value=ones(1)) design_space.add_variable( "x_shared", 2, l_b=(-10, 0.0), u_b=(10.0, 10.0), value=array([4.0, 3.0]) ) .. GENERATED FROM PYTHON SOURCE LINES 83-88 Create the scenario ^^^^^^^^^^^^^^^^^^^ In this section, we build the MDO scenario which links the disciplines with the formulation, the design space and the objective function. .. GENERATED FROM PYTHON SOURCE LINES 88-92 .. code-block:: Python scenario = create_scenario( disciplines, formulation="MDF", objective_name="obj", design_space=design_space ) .. GENERATED FROM PYTHON SOURCE LINES 93-97 Add the constraints ^^^^^^^^^^^^^^^^^^^ Then, we have to set the design constraints .. GENERATED FROM PYTHON SOURCE LINES 97-100 .. code-block:: Python scenario.add_constraint("c_1", "ineq") scenario.add_constraint("c_2", "ineq") .. GENERATED FROM PYTHON SOURCE LINES 101-110 Add the observables ^^^^^^^^^^^^^^^^^^^ Only the design variables, objective function and constraints are stored by default. In order to be able to recover the data from the state variables, y1 and y2, we have to add them as observables. All we have to do is enter the variable name as a string to the :meth:`~gemseo.core.scenario.Scenario.add_observable` method. If more than one output name is provided (as a list of strings), the observable function returns a concatenated array of the output values. .. GENERATED FROM PYTHON SOURCE LINES 110-111 .. code-block:: Python scenario.add_observable("y_1") .. GENERATED FROM PYTHON SOURCE LINES 112-114 It is also possible to add the observable with a custom name, using the option `observable_name`. Let us store the variable `y_2` as `y2`. .. GENERATED FROM PYTHON SOURCE LINES 114-116 .. code-block:: Python scenario.add_observable("y_2", observable_name="y2") .. GENERATED FROM PYTHON SOURCE LINES 117-123 Execute the scenario ^^^^^^^^^^^^^^^^^^^^ Then, we execute the MDO scenario with the inputs of the MDO scenario as a dictionary. In this example, the gradient-based `SLSQP` optimizer is selected, with 10 iterations at maximum: .. GENERATED FROM PYTHON SOURCE LINES 123-125 .. code-block:: Python scenario.execute(input_data={"max_iter": 10, "algo": "SLSQP"}) .. rst-class:: sphx-glr-script-out .. code-block:: none INFO - 10:51:25: INFO - 10:51:25: *** Start MDOScenario execution *** INFO - 10:51:25: MDOScenario INFO - 10:51:25: Disciplines: Sellar1 Sellar2 SellarSystem INFO - 10:51:25: MDO formulation: MDF INFO - 10:51:25: Optimization problem: INFO - 10:51:25: minimize obj(x_local, x_shared) INFO - 10:51:25: with respect to x_local, x_shared INFO - 10:51:25: subject to constraints: INFO - 10:51:25: c_1(x_local, x_shared) <= 0.0 INFO - 10:51:25: c_2(x_local, x_shared) <= 0.0 INFO - 10:51:25: over the design space: INFO - 10:51:25: +-------------+-------------+-------+-------------+-------+ INFO - 10:51:25: | Name | Lower bound | Value | Upper bound | Type | INFO - 10:51:25: +-------------+-------------+-------+-------------+-------+ INFO - 10:51:25: | x_local | 0 | 1 | 10 | float | INFO - 10:51:25: | x_shared[0] | -10 | 4 | 10 | float | INFO - 10:51:25: | x_shared[1] | 0 | 3 | 10 | float | INFO - 10:51:25: +-------------+-------------+-------+-------------+-------+ INFO - 10:51:25: Solving optimization problem with algorithm SLSQP: INFO - 10:51:25: 10%|█ | 1/10 [00:00<00:00, 36.69 it/sec, obj=21.8+j] /home/docs/checkouts/readthedocs.org/user_builds/gemseo/envs/stable/lib/python3.9/site-packages/scipy/optimize/_slsqp_py.py:422: ComplexWarning: Casting complex values to real discards the imaginary part slsqp(m, meq, x, xl, xu, fx, c, g, a, acc, majiter, mode, w, jw, INFO - 10:51:25: 20%|██ | 2/10 [00:00<00:00, 25.79 it/sec, obj=5.39+j] INFO - 10:51:25: 30%|███ | 3/10 [00:00<00:00, 24.10 it/sec, obj=3.41+j] INFO - 10:51:26: 40%|████ | 4/10 [00:00<00:00, 23.42 it/sec, obj=3.19+j] INFO - 10:51:26: 50%|█████ | 5/10 [00:00<00:00, 22.96 it/sec, obj=3.18+j] INFO - 10:51:26: 60%|██████ | 6/10 [00:00<00:00, 22.70 it/sec, obj=3.18+j] INFO - 10:51:26: 70%|███████ | 7/10 [00:00<00:00, 22.52 it/sec, obj=3.18+j] INFO - 10:51:26: 80%|████████ | 8/10 [00:00<00:00, 24.96 it/sec, obj=3.18+j] INFO - 10:51:26: Optimization result: INFO - 10:51:26: Optimizer info: INFO - 10:51:26: Status: None INFO - 10:51:26: Message: Successive iterates of the objective function are closer than ftol_rel or ftol_abs. GEMSEO Stopped the driver INFO - 10:51:26: Number of calls to the objective function by the optimizer: 9 INFO - 10:51:26: Solution: INFO - 10:51:26: The solution is feasible. INFO - 10:51:26: Objective: (3.183393951638041+0j) INFO - 10:51:26: Standardized constraints: INFO - 10:51:26: c_1 = (3.419042826635632e-12+0j) INFO - 10:51:26: c_2 = (-20.24472223307516+0j) INFO - 10:51:26: Design space: INFO - 10:51:26: +-------------+-------------+-----------------------+-------------+-------+ INFO - 10:51:26: | Name | Lower bound | Value | Upper bound | Type | INFO - 10:51:26: +-------------+-------------+-----------------------+-------------+-------+ INFO - 10:51:26: | x_local | 0 | 0 | 10 | float | INFO - 10:51:26: | x_shared[0] | -10 | 1.977638883461871 | 10 | float | INFO - 10:51:26: | x_shared[1] | 0 | 8.135637827350935e-13 | 10 | float | INFO - 10:51:26: +-------------+-------------+-----------------------+-------------+-------+ INFO - 10:51:26: *** End MDOScenario execution (time: 0:00:00.337101) *** {'max_iter': 10, 'algo': 'SLSQP'} .. GENERATED FROM PYTHON SOURCE LINES 126-132 Access the observable variables ------------------------------- Retrieve observables from a dataset ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In order to create a dataset, we use the corresponding :class:`.OptimizationProblem`: .. GENERATED FROM PYTHON SOURCE LINES 132-133 .. code-block:: Python opt_problem = scenario.formulation.opt_problem .. GENERATED FROM PYTHON SOURCE LINES 134-137 We can easily build an :class:`.OptimizationDataset` from this :class:`.OptimizationProblem`: either by separating the design parameters from the functions (default option): .. GENERATED FROM PYTHON SOURCE LINES 137-139 .. code-block:: Python dataset = opt_problem.to_dataset("sellar_problem") dataset .. raw:: html
GROUP designs functions
VARIABLE x_local x_shared c_1 c_2 obj y2 y_1
COMPONENT 0 0 1 0 0 0 0 0
1 1.000000e+00 4.000000 3.000000e+00 -1.459721e+01 -12.786069 21.757227 11.213931 4.213931
2 4.681980e-10 2.520049 2.513834e-10 -2.222628e+00 -19.159902 5.390534 4.840098 2.320049
3 3.071206e-03 2.040410 0.000000e+00 -2.300221e-01 -20.118389 3.410649 3.881611 1.841201
4 1.464893e-13 1.978711 0.000000e+00 -3.811869e-03 -20.242579 3.187156 3.757421 1.778711
5 3.546167e-14 1.977639 0.000000e+00 -1.148173e-06 -20.244722 3.183395 3.755278 1.777639
6 0.000000e+00 1.977639 0.000000e+00 7.136514e-13 -20.244722 3.183394 3.755278 1.777639
7 0.000000e+00 1.977639 8.135638e-13 3.419043e-12 -20.244722 3.183394 3.755278 1.777639
8 0.000000e+00 1.977639 3.103425e-13 NaN NaN 3.183394 3.755278 1.777639


.. GENERATED FROM PYTHON SOURCE LINES 140-141 or by considering all features as default parameters: .. GENERATED FROM PYTHON SOURCE LINES 141-143 .. code-block:: Python dataset = opt_problem.to_dataset("sellar_problem", categorize=False) dataset .. raw:: html
GROUP parameters
VARIABLE x_local x_shared c_1 c_2 obj y2 y_1
COMPONENT 0 0 1 0 0 0 0 0
0 1.000000e+00 4.000000 3.000000e+00 -1.459721e+01 -12.786069 21.757227 11.213931 4.213931
1 4.681980e-10 2.520049 2.513834e-10 -2.222628e+00 -19.159902 5.390534 4.840098 2.320049
2 3.071206e-03 2.040410 0.000000e+00 -2.300221e-01 -20.118389 3.410649 3.881611 1.841201
3 1.464893e-13 1.978711 0.000000e+00 -3.811869e-03 -20.242579 3.187156 3.757421 1.778711
4 3.546167e-14 1.977639 0.000000e+00 -1.148173e-06 -20.244722 3.183395 3.755278 1.777639
5 0.000000e+00 1.977639 0.000000e+00 7.136514e-13 -20.244722 3.183394 3.755278 1.777639
6 0.000000e+00 1.977639 8.135638e-13 3.419043e-12 -20.244722 3.183394 3.755278 1.777639
7 0.000000e+00 1.977639 3.103425e-13 NaN NaN 3.183394 3.755278 1.777639


.. GENERATED FROM PYTHON SOURCE LINES 144-145 or by using an input-output naming rather than an optimization naming: .. GENERATED FROM PYTHON SOURCE LINES 145-147 .. code-block:: Python dataset = opt_problem.to_dataset("sellar_problem", opt_naming=False) dataset .. raw:: html
GROUP inputs outputs
VARIABLE x_local x_shared c_1 c_2 obj y2 y_1
COMPONENT 0 0 1 0 0 0 0 0
0 1.000000e+00 4.000000 3.000000e+00 -1.459721e+01 -12.786069 21.757227 11.213931 4.213931
1 4.681980e-10 2.520049 2.513834e-10 -2.222628e+00 -19.159902 5.390534 4.840098 2.320049
2 3.071206e-03 2.040410 0.000000e+00 -2.300221e-01 -20.118389 3.410649 3.881611 1.841201
3 1.464893e-13 1.978711 0.000000e+00 -3.811869e-03 -20.242579 3.187156 3.757421 1.778711
4 3.546167e-14 1.977639 0.000000e+00 -1.148173e-06 -20.244722 3.183395 3.755278 1.777639
5 0.000000e+00 1.977639 0.000000e+00 7.136514e-13 -20.244722 3.183394 3.755278 1.777639
6 0.000000e+00 1.977639 8.135638e-13 3.419043e-12 -20.244722 3.183394 3.755278 1.777639
7 0.000000e+00 1.977639 3.103425e-13 NaN NaN 3.183394 3.755278 1.777639


.. GENERATED FROM PYTHON SOURCE LINES 148-151 Access observables by name ~~~~~~~~~~~~~~~~~~~~~~~~~~ We can get the observable data by variable names: .. GENERATED FROM PYTHON SOURCE LINES 151-153 .. code-block:: Python dataset.get_view(variable_names=["y_1", "y2"]) .. raw:: html
GROUP outputs
VARIABLE y_1 y2
COMPONENT 0 0
0 4.213931 11.213931
1 2.320049 4.840098
2 1.841201 3.881611
3 1.778711 3.757421
4 1.777639 3.755278
5 1.777639 3.755278
6 1.777639 3.755278
7 1.777639 3.755278


.. GENERATED FROM PYTHON SOURCE LINES 154-159 Use the observables in a post-processing method ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Finally, we can generate plots with the observable variables. Have a look at the Basic History plot and the Scatter Plot Matrix: .. GENERATED FROM PYTHON SOURCE LINES 159-171 .. code-block:: Python scenario.post_process( "BasicHistory", variable_names=["obj", "y_1", "y2"], save=False, show=True, ) scenario.post_process( "ScatterPlotMatrix", variable_names=["obj", "c_1", "c_2", "y2", "y_1"], save=False, show=True, ) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /examples/scenario/images/sphx_glr_plot_store_observables_001.png :alt: History plot :srcset: /examples/scenario/images/sphx_glr_plot_store_observables_001.png :class: sphx-glr-multi-img * .. image-sg:: /examples/scenario/images/sphx_glr_plot_store_observables_002.png :alt: plot store observables :srcset: /examples/scenario/images/sphx_glr_plot_store_observables_002.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.772 seconds) .. _sphx_glr_download_examples_scenario_plot_store_observables.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_store_observables.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_store_observables.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_