Scenario

from __future__ import annotations

from gemseo.api import configure_logger
from gemseo.api import create_design_space
from gemseo.api import create_discipline
from gemseo.api import create_scenario
from gemseo.api import get_available_scenario_types
from gemseo.api import get_scenario_differentiation_modes
from gemseo.api import get_scenario_inputs_schema
from gemseo.api import get_scenario_options_schema
from gemseo.api import monitor_scenario

configure_logger()
<RootLogger root (INFO)>

In this example, we will discover the different functions of the API to related to scenarios, which are the GEMSEO’ objects dedicated to the resolution of a problem, e.g. optimization or trade-off, associated with a list of disciplines and a design space. All classes implementing scenarios inherit from Scenario which is an abstract class. Classical concrete classes are MDOScenario and DOEScenario, respectively dedicated to optimization and trade-off problems.

Get available scenario type

The API function get_available_scenario_types() can be used to get the available scenario types (MDOScenario and DOEScenario).

print(get_available_scenario_types())
['MDO', 'DOE']

Get scenario options schema

The get_scenario_options_schema() function can be used to get the options of a given scenario type:

print(get_scenario_options_schema("MDO"))
{'$schema': 'http://json-schema.org/draft-04/schema', 'type': 'object', 'properties': {'linearization_mode': {'description': 'Linearization mode', 'enum': ['auto', 'direct', 'reverse', 'adjoint'], 'type': 'string'}, 'jac_approx_type': {'description': 'Jacobian approximation type', 'enum': ['finite_differences', 'complex_step'], 'type': 'string'}, 'jax_approx_step': {'minimum': 0, 'exclusiveMinimum': True, 'description': 'Step for finite differences or complex step for Jacobian approximation', 'type': 'number'}, 'jac_approx_use_threading': {'description': 'if True, use Threads instead of processes\n to parallelize the execution. \nMultiprocessing will serialize all the disciplines, \nwhile multithreading will share all the memory.\n This is important to note if you want to execute the same\n  discipline multiple times, you shall use multiprocessing', 'type': 'boolean'}, 'jac_approx_wait_time': {'description': 'Time waited between two forks of the process or thread when using parallel jacobian approximations (parallel=True)', 'minimum': 0, 'type': 'number'}, 'jac_approx_n_processes': {'minimum': 1, 'description': 'maximum number of processors or threads on \nwhich the jacobian approximation is performed\n by default, 1 means no parallel calculations', 'type': 'integer'}, 'cache_type': {'description': 'Type of cache to be used.  \nBy default, simple cache stores the last execution inputs and outputs  \nin memory only to avoid computation of the outputs if the inputs are identical.\n To store more executions, use HDF5 caches, which stores data on the disk.\n There is a hashing mechanism which avoids reading on the disk for every calculation.', 'type': 'string'}, 'cache_tolerance': {'minimum': 0, 'description': 'Numerical tolerance on the relative norm of input vectors \n to consider that two sets of inputs are equal, and that the outputs may therefore be returned from the cache without calculations.', 'type': 'number'}, 'cache_hdf_file': {'format': 'uri', 'description': 'Path to the HDF5 file to store the cache data.', 'type': 'string'}, 'cache_hdf_node_name': {'description': 'Name of the HDF dataset to store the discipline\n data. If None, the discipline name is used.', 'type': 'string'}, 'name': {'description': 'The name to be given to this scenario. If ``None``, use the name of the class.', 'type': 'null'}, 'grammar_type': {'description': 'The type of grammar to declare the input and output variables either :attr:`~.MDODiscipline.JSON_GRAMMAR_TYPE` or :attr:`~.MDODiscipline.SIMPLE_GRAMMAR_TYPE`.', 'type': 'string'}, 'maximize_objective': {'description': 'Whether to maximize the objective.', 'type': 'boolean'}}, 'required': ['grammar_type', 'maximize_objective']}

Create a scenario

The API function create_scenario() can be used to create a scenario:

  • The four first arguments are mandatory:

    • disciplines: the list of MDODiscipline (or possibly, a single MDODiscipline),

    • formulation: the formulation name,

    • objective_name: the name of the objective function (one of the discipline outputs)

    • design_space: the DesignSpace or the file path of the design space

  • The other arguments are optional:

    • name: scenario name,

    • scenario_type: type of scenario, either “MDO” (default) or “DOE” ,

    • **options: options passed to the formulation.

  • This function returns an instance of MDOScenario or DOEScenario.

discipline = create_discipline("AnalyticDiscipline", expressions={"y": "x1+x2"})
design_space = create_design_space()
design_space.add_variable("x1", 1, "float", 0.0, 1.0)
design_space.add_variable("x2", 1, "float", 0.0, 1.0)

scenario = create_scenario(
    discipline, "DisciplinaryOpt", "y", design_space, scenario_type="DOE"
)
scenario.execute({"algo": "fullfact", "n_samples": 25})
scenario.post_process(
    "ScatterPlotMatrix", variable_names=["x1", "x2", "y"], save=False, show=True
)
    INFO - 14:48:14:
    INFO - 14:48:14: *** Start DOEScenario execution ***
    INFO - 14:48:14: DOEScenario
    INFO - 14:48:14:    Disciplines: AnalyticDiscipline
    INFO - 14:48:14:    MDO formulation: DisciplinaryOpt
    INFO - 14:48:14: Optimization problem:
    INFO - 14:48:14:    minimize y(x1, x2)
    INFO - 14:48:14:    with respect to x1, x2
    INFO - 14:48:14:    over the design space:
    INFO - 14:48:14:    +------+-------------+-------+-------------+-------+
    INFO - 14:48:14:    | name | lower_bound | value | upper_bound | type  |
    INFO - 14:48:14:    +------+-------------+-------+-------------+-------+
    INFO - 14:48:14:    | x1   |      0      |  None |      1      | float |
    INFO - 14:48:14:    | x2   |      0      |  None |      1      | float |
    INFO - 14:48:14:    +------+-------------+-------+-------------+-------+
    INFO - 14:48:14: Solving optimization problem with algorithm fullfact:
    INFO - 14:48:14: ...   0%|          | 0/25 [00:00<?, ?it]
    INFO - 14:48:14: ... 100%|██████████| 25/25 [00:00<00:00, 2301.73 it/sec, obj=2]
    INFO - 14:48:14: Optimization result:
    INFO - 14:48:14:    Optimizer info:
    INFO - 14:48:14:       Status: None
    INFO - 14:48:14:       Message: None
    INFO - 14:48:14:       Number of calls to the objective function by the optimizer: 25
    INFO - 14:48:14:    Solution:
    INFO - 14:48:14:       Objective: 0.0
    INFO - 14:48:14:       Design space:
    INFO - 14:48:14:       +------+-------------+-------+-------------+-------+
    INFO - 14:48:14:       | name | lower_bound | value | upper_bound | type  |
    INFO - 14:48:14:       +------+-------------+-------+-------------+-------+
    INFO - 14:48:14:       | x1   |      0      |   0   |      1      | float |
    INFO - 14:48:14:       | x2   |      0      |   0   |      1      | float |
    INFO - 14:48:14:       +------+-------------+-------+-------------+-------+
    INFO - 14:48:14: *** End DOEScenario execution (time: 0:00:00.019528) ***

<gemseo.post.scatter_mat.ScatterPlotMatrix object at 0x7f3b0a74dca0>
print(get_scenario_inputs_schema(scenario))
{'$schema': 'http://json-schema.org/draft-04/schema', 'algo': {'type': 'string', 'enum': ['CustomDOE', 'DiagonalDOE', 'OT_SOBOL', 'OT_RANDOM', 'OT_HASELGROVE', 'OT_REVERSE_HALTON', 'OT_HALTON', 'OT_FAURE', 'OT_MONTE_CARLO', 'OT_FACTORIAL', 'OT_COMPOSITE', 'OT_AXIAL', 'OT_OPT_LHS', 'OT_LHS', 'OT_LHSC', 'OT_FULLFACT', 'OT_SOBOL_INDICES', 'fullfact', 'ff2n', 'pbdesign', 'bbdesign', 'ccdesign', 'lhs']}, 'type': 'object', 'properties': {'eval_jac': {'type': 'boolean'}, 'algo': {'type': 'string'}, 'algo_options': {'type': 'object'}, 'n_samples': {'minimum': 1, 'type': 'integer'}}, 'required': ['algo']}

Get scenario differentiation modes

The get_scenario_differentiation_modes() can be used to get the available differentiation modes of a scenario:

print(get_scenario_differentiation_modes())
['user', 'complex_step', 'finite_differences', 'no_derivatives']

Monitor a scenario

To monitor a scenario execution programmatically, ie get a notification when a discipline status is changed, use monitor_scenario(). The first argument is the scenario to monitor, and the second is an observer object, that is notified by its update(atom) method, which takes an AtomicExecSequence as argument. This method will be called every time a discipline status changes. The atom represents a discipline’s position in the process. One discipline can have multiple atoms, since one discipline can be used in multiple positions in the MDO formulation.

class Observer:
    """Observer."""

    def update(self, atom):
        """Update method.

        :param AtomicExecSequence atom: atomic execution sequence.
        """
        print(atom)


scenario = create_scenario(
    discipline, "DisciplinaryOpt", "y", design_space, scenario_type="DOE"
)
monitor_scenario(scenario, Observer())
scenario.execute({"algo": "fullfact", "n_samples": 25})
DOEScenario(RUNNING)
    INFO - 14:48:14:
    INFO - 14:48:14: *** Start DOEScenario execution ***
    INFO - 14:48:14: DOEScenario
    INFO - 14:48:14:    Disciplines: AnalyticDiscipline
    INFO - 14:48:14:    MDO formulation: DisciplinaryOpt
    INFO - 14:48:15: Optimization problem:
    INFO - 14:48:15:    minimize y(x1, x2)
    INFO - 14:48:15:    with respect to x1, x2
    INFO - 14:48:15:    over the design space:
    INFO - 14:48:15:    +------+-------------+-------+-------------+-------+
    INFO - 14:48:15:    | name | lower_bound | value | upper_bound | type  |
    INFO - 14:48:15:    +------+-------------+-------+-------------+-------+
    INFO - 14:48:15:    | x1   |      0      |   0   |      1      | float |
    INFO - 14:48:15:    | x2   |      0      |   0   |      1      | float |
    INFO - 14:48:15:    +------+-------------+-------+-------------+-------+
    INFO - 14:48:15: Solving optimization problem with algorithm fullfact:
    INFO - 14:48:15: ...   0%|          | 0/25 [00:00<?, ?it]
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
AnalyticDiscipline(RUNNING)
AnalyticDiscipline(PENDING)
    INFO - 14:48:15: ... 100%|██████████| 25/25 [00:00<00:00, 2066.73 it/sec, obj=2]
    INFO - 14:48:15: Optimization result:
    INFO - 14:48:15:    Optimizer info:
    INFO - 14:48:15:       Status: None
    INFO - 14:48:15:       Message: None
    INFO - 14:48:15:       Number of calls to the objective function by the optimizer: 25
    INFO - 14:48:15:    Solution:
    INFO - 14:48:15:       Objective: 0.0
    INFO - 14:48:15:       Design space:
    INFO - 14:48:15:       +------+-------------+-------+-------------+-------+
    INFO - 14:48:15:       | name | lower_bound | value | upper_bound | type  |
    INFO - 14:48:15:       +------+-------------+-------+-------------+-------+
    INFO - 14:48:15:       | x1   |      0      |   0   |      1      | float |
    INFO - 14:48:15:       | x2   |      0      |   0   |      1      | float |
    INFO - 14:48:15:       +------+-------------+-------+-------------+-------+
    INFO - 14:48:15: *** End DOEScenario execution (time: 0:00:00.024695) ***
AnalyticDiscipline(DONE)
DOEScenario(DONE)

{'eval_jac': False, 'algo': 'fullfact', 'n_samples': 25}

Total running time of the script: ( 0 minutes 0.573 seconds)

Gallery generated by Sphinx-Gallery