.. 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.scenarios.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-86 .. code-block:: Python design_space = DesignSpace() design_space.add_variable("x_local", lower_bound=0.0, upper_bound=10.0, value=ones(1)) design_space.add_variable( "x_shared", 2, lower_bound=(-10, 0.0), upper_bound=(10.0, 10.0), value=array([4.0, 3.0]), ) .. GENERATED FROM PYTHON SOURCE LINES 87-92 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 92-94 .. code-block:: Python scenario = create_scenario(disciplines, "obj", design_space, formulation_name="MDF") .. rst-class:: sphx-glr-script-out .. code-block:: none INFO - 20:38:32: Variable x_local was removed from the Design Space, it is not an input of any discipline. .. GENERATED FROM PYTHON SOURCE LINES 95-97 Note that the formulation settings passed to :func:`.create_scenario` can be provided via a Pydantic model. For more information, see :ref:`formulation_settings`. .. GENERATED FROM PYTHON SOURCE LINES 99-103 Add the constraints ^^^^^^^^^^^^^^^^^^^ Then, we have to set the design constraints .. GENERATED FROM PYTHON SOURCE LINES 103-106 .. code-block:: Python scenario.add_constraint("c_1", constraint_type="ineq") scenario.add_constraint("c_2", constraint_type="ineq") .. GENERATED FROM PYTHON SOURCE LINES 107-116 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.scenarios.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 116-117 .. code-block:: Python scenario.add_observable("y_1") .. GENERATED FROM PYTHON SOURCE LINES 118-120 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 120-122 .. code-block:: Python scenario.add_observable("y_2", observable_name="y2") .. GENERATED FROM PYTHON SOURCE LINES 123-129 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 129-131 .. code-block:: Python scenario.execute(algo_name="SLSQP", max_iter=10) .. rst-class:: sphx-glr-script-out .. code-block:: none INFO - 20:38:32: *** Start MDOScenario execution *** INFO - 20:38:32: MDOScenario INFO - 20:38:32: Disciplines: Sellar1 Sellar2 SellarSystem INFO - 20:38:32: MDO formulation: MDF INFO - 20:38:32: Optimization problem: INFO - 20:38:32: minimize obj(x_shared) INFO - 20:38:32: with respect to x_shared INFO - 20:38:32: under the inequality constraints INFO - 20:38:32: c_1(x_shared) <= 0 INFO - 20:38:32: c_2(x_shared) <= 0 INFO - 20:38:32: over the design space: INFO - 20:38:32: +-------------+-------------+-------+-------------+-------+ INFO - 20:38:32: | Name | Lower bound | Value | Upper bound | Type | INFO - 20:38:32: +-------------+-------------+-------+-------------+-------+ INFO - 20:38:32: | x_shared[0] | -10 | 4 | 10 | float | INFO - 20:38:32: | x_shared[1] | 0 | 3 | 10 | float | INFO - 20:38:32: +-------------+-------------+-------+-------------+-------+ INFO - 20:38:32: Solving optimization problem with algorithm SLSQP: INFO - 20:38:32: 10%|█ | 1/10 [00:00<00:00, 85.36 it/sec, obj=19.8] INFO - 20:38:32: 20%|██ | 2/10 [00:00<00:00, 83.33 it/sec, obj=5.38] INFO - 20:38:32: 30%|███ | 3/10 [00:00<00:00, 88.53 it/sec, obj=3.41] INFO - 20:38:32: 40%|████ | 4/10 [00:00<00:00, 91.49 it/sec, obj=3.19] INFO - 20:38:32: 50%|█████ | 5/10 [00:00<00:00, 93.82 it/sec, obj=3.18] INFO - 20:38:32: 60%|██████ | 6/10 [00:00<00:00, 94.25 it/sec, obj=3.18] INFO - 20:38:32: 70%|███████ | 7/10 [00:00<00:00, 94.28 it/sec, obj=3.18] INFO - 20:38:32: 80%|████████ | 8/10 [00:00<00:00, 101.79 it/sec, obj=3.18] INFO - 20:38:32: Optimization result: INFO - 20:38:32: Optimizer info: INFO - 20:38:32: Status: None INFO - 20:38:32: Message: Successive iterates of the objective function are closer than ftol_rel or ftol_abs. GEMSEO stopped the driver. INFO - 20:38:32: Number of calls to the objective function by the optimizer: 0 INFO - 20:38:32: Solution: INFO - 20:38:32: The solution is feasible. INFO - 20:38:32: Objective: 3.183393960638473 INFO - 20:38:32: Standardized constraints: INFO - 20:38:32: c_1 = 1.5724075375089797e-09 INFO - 20:38:32: c_2 = -20.244722684911245 INFO - 20:38:32: Design space: INFO - 20:38:32: +-------------+-------------+-------------------+-------------+-------+ INFO - 20:38:32: | Name | Lower bound | Value | Upper bound | Type | INFO - 20:38:32: +-------------+-------------+-------------------+-------------+-------+ INFO - 20:38:32: | x_shared[0] | -10 | 1.977638860218251 | 10 | float | INFO - 20:38:32: | x_shared[1] | 0 | 0 | 10 | float | INFO - 20:38:32: +-------------+-------------+-------------------+-------------+-------+ INFO - 20:38:32: *** End MDOScenario execution (time: 0:00:00.081586) *** .. GENERATED FROM PYTHON SOURCE LINES 132-134 Note that the algorithm settings passed to :meth:`.DriverLibrary.execute` can be provided via a Pydantic model. For more information, see :ref:`algorithm_settings`. .. GENERATED FROM PYTHON SOURCE LINES 136-142 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 142-143 .. code-block:: Python opt_problem = scenario.formulation.optimization_problem .. GENERATED FROM PYTHON SOURCE LINES 144-147 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 147-149 .. code-block:: Python dataset = opt_problem.to_dataset("sellar_problem") dataset .. raw:: html
GROUP designs functions
VARIABLE x_shared c_1 c_2 obj y2 y_1
COMPONENT 0 1 0 0 0 0 0
1 4.000000 3.000000e+00 -1.362071e+01 -12.903573 19.780730 11.096427 4.096427
2 2.518818 0.000000e+00 -2.216919e+00 -19.162364 5.384844 4.837636 2.318818
3 2.040791 4.248151e-10 -2.285105e-01 -20.118419 3.409129 3.881581 1.840791
4 1.978722 1.358050e-12 -3.852514e-03 -20.242556 3.187196 3.757444 1.778722
5 1.977639 0.000000e+00 -1.172903e-06 -20.244722 3.183395 3.755278 1.777639
6 1.977639 8.487813e-14 1.061817e-12 -20.244723 3.183394 3.755277 1.777639
7 1.977639 0.000000e+00 1.572408e-09 -20.244723 3.183394 3.755277 1.777639
8 1.977639 4.245252e-14 NaN NaN 3.183394 3.755277 1.777639


.. GENERATED FROM PYTHON SOURCE LINES 150-151 or by considering all features as default parameters: .. GENERATED FROM PYTHON SOURCE LINES 151-153 .. code-block:: Python dataset = opt_problem.to_dataset("sellar_problem", categorize=False) dataset .. raw:: html
GROUP parameters
VARIABLE x_shared c_1 c_2 obj y2 y_1
COMPONENT 0 1 0 0 0 0 0
0 4.000000 3.000000e+00 -1.362071e+01 -12.903573 19.780730 11.096427 4.096427
1 2.518818 0.000000e+00 -2.216919e+00 -19.162364 5.384844 4.837636 2.318818
2 2.040791 4.248151e-10 -2.285105e-01 -20.118419 3.409129 3.881581 1.840791
3 1.978722 1.358050e-12 -3.852514e-03 -20.242556 3.187196 3.757444 1.778722
4 1.977639 0.000000e+00 -1.172903e-06 -20.244722 3.183395 3.755278 1.777639
5 1.977639 8.487813e-14 1.061817e-12 -20.244723 3.183394 3.755277 1.777639
6 1.977639 0.000000e+00 1.572408e-09 -20.244723 3.183394 3.755277 1.777639
7 1.977639 4.245252e-14 NaN NaN 3.183394 3.755277 1.777639


.. GENERATED FROM PYTHON SOURCE LINES 154-155 or by using an input-output naming rather than an optimization naming: .. GENERATED FROM PYTHON SOURCE LINES 155-157 .. code-block:: Python dataset = opt_problem.to_dataset("sellar_problem", opt_naming=False) dataset .. raw:: html
GROUP inputs outputs
VARIABLE x_shared c_1 c_2 obj y2 y_1
COMPONENT 0 1 0 0 0 0 0
0 4.000000 3.000000e+00 -1.362071e+01 -12.903573 19.780730 11.096427 4.096427
1 2.518818 0.000000e+00 -2.216919e+00 -19.162364 5.384844 4.837636 2.318818
2 2.040791 4.248151e-10 -2.285105e-01 -20.118419 3.409129 3.881581 1.840791
3 1.978722 1.358050e-12 -3.852514e-03 -20.242556 3.187196 3.757444 1.778722
4 1.977639 0.000000e+00 -1.172903e-06 -20.244722 3.183395 3.755278 1.777639
5 1.977639 8.487813e-14 1.061817e-12 -20.244723 3.183394 3.755277 1.777639
6 1.977639 0.000000e+00 1.572408e-09 -20.244723 3.183394 3.755277 1.777639
7 1.977639 4.245252e-14 NaN NaN 3.183394 3.755277 1.777639


.. GENERATED FROM PYTHON SOURCE LINES 158-161 Access observables by name ~~~~~~~~~~~~~~~~~~~~~~~~~~ We can get the observable data by variable names: .. GENERATED FROM PYTHON SOURCE LINES 161-163 .. code-block:: Python dataset.get_view(variable_names=["y_1", "y2"]) .. raw:: html
GROUP outputs
VARIABLE y_1 y2
COMPONENT 0 0
0 4.096427 11.096427
1 2.318818 4.837636
2 1.840791 3.881581
3 1.778722 3.757444
4 1.777639 3.755278
5 1.777639 3.755277
6 1.777639 3.755277
7 1.777639 3.755277


.. GENERATED FROM PYTHON SOURCE LINES 164-169 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 169-176 .. code-block:: Python scenario.post_process( post_name="BasicHistory", variable_names=["obj", "y_1", "y2"], save=False, show=True, ) .. 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-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 177-180 Note that the post-processor settings passed to :func:`.BaseScenario.post_process` can be provided via a Pydantic model. For more information, see :ref:`post_processor_settings`. An example is shown below. .. GENERATED FROM PYTHON SOURCE LINES 180-189 .. code-block:: Python from gemseo.settings.post import ScatterPlotMatrix_Settings # noqa: E402 scenario.post_process( ScatterPlotMatrix_Settings( variable_names=["obj", "c_1", "c_2", "y2", "y_1"], save=False, show=True, ) ) .. 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-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.798 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 ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_store_observables.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_