Note
Go to the end to download the full example code.
Skip samples when using DOE#
from __future__ import annotations
from typing import TYPE_CHECKING
from numpy import array
from numpy import sqrt
from gemseo import create_design_space
from gemseo import create_scenario
from gemseo.core.discipline import Discipline
from gemseo.settings.doe import CustomDOE_Settings
from gemseo.settings.post import BasicHistory_Settings
if TYPE_CHECKING:
from gemseo.typing import StrKeyMapping
In this example, we show how to skip the evaluation at a DOE point during a
DOEScenario run. This is useful in situations where the evaluation of a
sample fails or when the user wants to avoid evaluating some samples when
certain conditions are met.
The DOE algorithms in GEMSEO are able to catch ValueError exceptions
(and only this specific type of exception) at runtime and
move to the next sample.
Let us consider a discipline implementing the function \(y=sqrt(a)\). The _run
method of this discipline raises a ValueError when \(a < 0\). Of course,
you may use any other set of conditions to raise the exception in your scripts.
class ValueErrorDiscipline(Discipline):
default_grammar_type = Discipline.GrammarType.SIMPLE
def __init__(self) -> None:
super().__init__()
self.input_grammar.update_from_names("a")
self.output_grammar.update_from_names("y")
def _run(self, input_data: StrKeyMapping):
a = input_data["a"]
if a < 0:
msg = "The sample is undefined for a < 0."
raise ValueError(msg)
return {"y": sqrt(a)}
discipline = ValueErrorDiscipline()
We define a design space with the variable \(a\in[-1,10]\):
design_space = create_design_space()
design_space.add_variable(
"a", type_=design_space.DesignVariableType.FLOAT, lower_bound=-1, upper_bound=10
)
We want to evaluate this discipline over this design space at points 1, -1 and 4:
samples = array([[1.0], [-1.0], [4.0]])
For that, we can create a scenario and execute it with a CustomDOE
with the setting "samples":
scenario = create_scenario(
[discipline],
"y",
design_space,
scenario_type="DOE",
formulation_name="DisciplinaryOpt",
)
custom_doe_settings = CustomDOE_Settings(samples=samples)
scenario.execute(custom_doe_settings)
INFO - 16:25:02: *** Start DOEScenario execution ***
INFO - 16:25:02: DOEScenario
INFO - 16:25:02: Disciplines: ValueErrorDiscipline
INFO - 16:25:02: MDO formulation: DisciplinaryOpt
INFO - 16:25:02: Optimization problem:
INFO - 16:25:02: minimize y(a)
INFO - 16:25:02: with respect to a
INFO - 16:25:02: over the design space:
INFO - 16:25:02: +------+-------------+-------+-------------+-------+
INFO - 16:25:02: | Name | Lower bound | Value | Upper bound | Type |
INFO - 16:25:02: +------+-------------+-------+-------------+-------+
INFO - 16:25:02: | a | -1 | None | 10 | float |
INFO - 16:25:02: +------+-------------+-------+-------------+-------+
INFO - 16:25:02: Solving optimization problem with algorithm CustomDOE:
INFO - 16:25:02: 33%|███▎ | 1/3 [00:00<00:00, 3542.49 it/sec, feas=True, obj=1]
ERROR - 16:25:02: Failed to evaluate function y
ValueError: The sample is undefined for a < 0.
ERROR - 16:25:02: The evaluation of the functions at point [-1.] raised a ValueError; skipping to the next point.
ValueError: The sample is undefined for a < 0.
INFO - 16:25:02: 67%|██████▋ | 2/3 [00:00<00:00, 1650.65 it/sec, feas=True, obj=2]
INFO - 16:25:02: Optimization result:
INFO - 16:25:02: Optimizer info:
INFO - 16:25:02: Status: None
INFO - 16:25:02: Message: None
INFO - 16:25:02: Solution:
INFO - 16:25:02: Objective: 1.0
INFO - 16:25:02: Design space:
INFO - 16:25:02: +------+-------------+-------+-------------+-------+
INFO - 16:25:02: | Name | Lower bound | Value | Upper bound | Type |
INFO - 16:25:02: +------+-------------+-------+-------------+-------+
INFO - 16:25:02: | a | -1 | 1 | 10 | float |
INFO - 16:25:02: +------+-------------+-------+-------------+-------+
INFO - 16:25:02: *** End DOEScenario execution (time: 0:00:00.003329) ***
The logger shows that
GEMSEO ignores the ValueError raised at the second point
and switches to the third point.
The post-processing of the scenario only includes two runs:
basic_history_settings = BasicHistory_Settings(
variable_names=["y"], save=False, show=True
)
scenario.post_process(basic_history_settings)

<gemseo.post.basic_history.BasicHistory object at 0x7c2f8ef94d70>
Warning
In order to be able to continue the execution of a DOEScenario, the
execution status and statistics of disciplines must be disabled. This is the
default behavior, but you can also disable them explicitly with the
configure() function.
Note that if your discipline is able to return a
NaN without raising any exceptions, you do not need to use the mechanism
explained here, in that case the NaN values will be handled by GEMSEO and stored
in the database of the scenario.
Total running time of the script: (0 minutes 0.088 seconds)