Scenario

from __future__ import division, unicode_literals

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

configure_logger()

Out:

<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())

Out:

['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"))

Out:

{'$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 use for IO declaration , e.g. JSON_GRAMMAR_TYPE or SIMPLE_GRAMMAR_TYPE.', 'type': 'string'}}, 'required': ['grammar_type']}

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_dict={"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", variables_list=["x1", "x2", "y"], save=False, show=True
)

Out:

    INFO - 14:42:45:
    INFO - 14:42:45: *** Start DOE Scenario execution ***
    INFO - 14:42:45: DOEScenario
    INFO - 14:42:45:    Disciplines: AnalyticDiscipline
    INFO - 14:42:45:    MDOFormulation: DisciplinaryOpt
    INFO - 14:42:45:    Algorithm: fullfact
    INFO - 14:42:45: Optimization problem:
    INFO - 14:42:45:    Minimize: y(x1, x2)
    INFO - 14:42:45:    With respect to: x1, x2
    INFO - 14:42:45: Full factorial design required. Number of samples along each direction for a design vector of size 2 with 25 samples: 5
    INFO - 14:42:45: Final number of samples for DOE = 25 vs 25 requested
    INFO - 14:42:45: DOE sampling:   0%|          | 0/25 [00:00<?, ?it]
    INFO - 14:42:45: DOE sampling: 100%|██████████| 25/25 [00:00<00:00, 2094.47 it/sec, obj=2]
    INFO - 14:42:45: Optimization result:
    INFO - 14:42:45: Objective value = 0.0
    INFO - 14:42:45: The result is feasible.
    INFO - 14:42:45: Status: None
    INFO - 14:42:45: Optimizer message: None
    INFO - 14:42:45: Number of calls to the objective function by the optimizer: 25
    INFO - 14:42:45: Design space:
    INFO - 14:42:45: +------+-------------+-------+-------------+-------+
    INFO - 14:42:45: | name | lower_bound | value | upper_bound | type  |
    INFO - 14:42:45: +------+-------------+-------+-------------+-------+
    INFO - 14:42:45: | x1   |      0      |   0   |      1      | float |
    INFO - 14:42:45: | x2   |      0      |   0   |      1      | float |
    INFO - 14:42:45: +------+-------------+-------+-------------+-------+
    INFO - 14:42:45: *** DOE Scenario run terminated ***

<gemseo.post.scatter_mat.ScatterPlotMatrix object at 0x7fcaa462b5e0>
print(get_scenario_inputs_schema(scenario))

Out:

{'$schema': 'http://json-schema.org/draft-04/schema', 'type': 'object', 'properties': {'eval_jac': {'type': 'boolean'}, 'algo': {'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': '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())

Out:

['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(object):
    """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})

Out:

DOEScenario(RUNNING)
    INFO - 14:42:46:
    INFO - 14:42:46: *** Start DOE Scenario execution ***
    INFO - 14:42:46: DOEScenario
    INFO - 14:42:46:    Disciplines: AnalyticDiscipline
    INFO - 14:42:46:    MDOFormulation: DisciplinaryOpt
    INFO - 14:42:46:    Algorithm: fullfact
    INFO - 14:42:46: Optimization problem:
    INFO - 14:42:46:    Minimize: y(x1, x2)
    INFO - 14:42:46:    With respect to: x1, x2
    INFO - 14:42:46: Full factorial design required. Number of samples along each direction for a design vector of size 2 with 25 samples: 5
    INFO - 14:42:46: Final number of samples for DOE = 25 vs 25 requested
    INFO - 14:42:46: DOE sampling:   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:42:46: DOE sampling: 100%|██████████| 25/25 [00:00<00:00, 1257.80 it/sec, obj=2]
    INFO - 14:42:46: Optimization result:
    INFO - 14:42:46: Objective value = 0.0
    INFO - 14:42:46: The result is feasible.
    INFO - 14:42:46: Status: None
    INFO - 14:42:46: Optimizer message: None
    INFO - 14:42:46: Number of calls to the objective function by the optimizer: 25
    INFO - 14:42:46: Design space:
    INFO - 14:42:46: +------+-------------+-------+-------------+-------+
    INFO - 14:42:46: | name | lower_bound | value | upper_bound | type  |
    INFO - 14:42:46: +------+-------------+-------+-------------+-------+
    INFO - 14:42:46: | x1   |      0      |   0   |      1      | float |
    INFO - 14:42:46: | x2   |      0      |   0   |      1      | float |
    INFO - 14:42:46: +------+-------------+-------+-------------+-------+
    INFO - 14:42:46: *** DOE Scenario run terminated ***
AnalyticDiscipline(DONE)
DOEScenario(DONE)

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

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

Gallery generated by Sphinx-Gallery