API#
The main class defining a problem is engibench.core.Problem
. It is defined as follows
- class engibench.core.Problem(**kwargs: Any)[source]#
Main class for defining an engineering design problem.
This class assumes there is:
an underlying simulator that is called to evaluate the performance of a design (see simulate method);
a dataset containing representations of designs and their performances (see design_space, dataset_id attributes);
The main API methods that users should use are:
simulate()
- to simulate a design and return the performance given some conditions.optimize()
- to optimize a design starting from a given point, e.g., using adjoint solver included inside the simulator.reset()
- to reset the simulator and numpy random to a given seed.render()
- to render a design in a human-readable format.random_design()
- to generate a valid random design.
There are some attributes that help understanding the problem:
objectives
- a dictionary with the names of the objectives and their types (minimize or maximize).conditions
- the conditions for the design problem.design_space
- the space of designs (outputs of algorithms).dataset_id
- a string identifier for the problem – useful to pull datasets.dataset
- the dataset with designs and performances.container_id
- a string identifier for the singularity container.
Having all these defined in the code allows to easily extract the columns we want from the dataset to train ML models.
Note
This class is generic and should be subclassed to define the specific problem.
Note
This class is parameterized with DesignType is the type of the design that is optimized (e.g. a Numpy array representing the design).
Note
Some simulators also ask for simulator related configurations. These configurations are generally defined in the problem implementation, do not appear in the problem.conditions, but sometimes appear in the dataset (for advanced usage). You can override them by using the config argument in the simulate or optimize method.
Dataset#
The dataset is a HuggingFace Dataset
object that defines the dataset of the problem. This is typically useful to train ML models for inverse design or surrogate modeling.
A dataset is generally composed of several columns:
optimal_design
: The optimal design of the problem.All columns listed in
problem.objectives
: The objectives of the problem.All columns listed in
problem.conditions
: The conditions of the problem.Additional columns which can be useful for advanced usage.
Methods#
- Problem.check_constraints(design: DesignType, config: dict[str, Any]) Violations [source]#
Check if config and design violate any constraints declared in Config and design_space.
Return a
constraint.Violations
object containing all violations.
- Problem.simulate(design: DesignType, config: dict[str, Any] | None = None) ndarray[Any, dtype[_ScalarType_co]] [source]#
Launch a simulation on the given design and return the performance.
- Parameters:
design (DesignType) – The design to simulate.
config (dict) – A dictionary with configuration (e.g., boundary conditions, filenames) for the optimization.
**kwargs – Additional keyword arguments.
- Returns:
np.array – The performance of the design – each entry corresponds to an objective value.
- Problem.optimize(starting_point: DesignType, config: dict[str, Any] | None = None) tuple[DesignType, Sequence[OptiStep]] [source]#
Some simulators have built-in optimization. This function optimizes the design starting from starting_point.
This is optional and will probably be implemented only for some problems.
- Parameters:
starting_point (DesignType) – The starting point for the optimization.
config (dict) – A dictionary with configuration (e.g., boundary conditions, filenames) for the optimization.
- Returns:
Tuple[DesignType, list[OptiStep]] – The optimized design and the optimization history.
Where an OptiStep is defined as:
- class OptiStep(obj_values: ndarray[Any, dtype[_ScalarType_co]], step: int)#
Optimization step.
- Problem.reset(seed: int | None = None) None [source]#
Reset the simulator and numpy random to a given seed.
- Parameters:
seed (int, optional) – The seed to reset to. If None, a random seed is used.
Attributes#
- Problem.objectives: tuple[tuple[str, ObjectiveDirection], ...]#
Objective names and types (minimize or maximize)
This attribute is a list of objectives that can be optimized. The objectives are defined as tuples where the first member is the objective name, and the second member is an enum saying ‘maximize’ or ‘minimize’.
>>> problem.objectives (("c", ObjectiveDirection.MINIMIZE),) >>> problem.objectives_keys ["c"]
- Problem.conditions: tuple[tuple[str, Any], ...]#
Conditions for the design problem
This attribute list the conditions of the problem. The conditions are defined as tuples where the first member is the boundary condition name, and the second member is the value. You can also access the condition keys only through problem.condition_keys.
>>> problem.conditions (("volfrac", 0.35), ("forcedist", 0.0),...) >>> problem.conditions_keys ["marchDist", "forcedist"]
- Problem.design_space: spaces.Space[DesignType]#
Design space (algorithm output)
This attribute is a gymnasium.spaces.Box object that defines the design space of the problem. This is typically useful to define your neural network input/output layer.
>>> problem.design_space Box(0.0, 1.0, (50, 100), float64)
- Problem.dataset_id: str#
String identifier for the problem (useful to pull datasets)
This attribute is a string that defines the dataset id of the problem. This is typically useful to fetch the dataset from our [dataset registry](https://huggingface.co/IDEALLab).
>>> problem.dataset_id 'IDEALLab/beams_2d_50_100_v0'
- Problem.dataset#
Pulls the dataset if it is not already loaded.
This attribute is a HuggingFace Dataset object that defines the dataset of the problem. This is typically useful to train your neural network.
>>> problem.dataset Dataset({ features: ["optimal_design", "volfrac", "forcedist", "c"], num_rows: 1000 })
- Problem.container_id: str | None#
String identifier for the singularity container
This attribute is a string that defines the container id of the problem. We use it to fetch the simulator containers (generally from DockerHub).
>>> problem.dataset_id 'mdolab/public:u22-gcc-ompi-stable'