gemseo_box_subdivision.subdivisions.multi_resolution#
A subdivision described by one categorical variable per level of refinement.
A BoxSubdivision spends \(n m\) binaries to reach \(m\)
subdivisions per component. This one spends \(n m L\) to reach
\(m^L\), by choosing a box with one categorical variable per level
instead of one over the whole subdivision: the levels are the digits of the box
index in base \(m\).
Classes
|
A subdivision of a design space into \(m^L\) boxes per component. |
- class gemseo_box_subdivision.subdivisions.multi_resolution.MultiResolution(lower_bounds, upper_bounds, branching, levels)[source]#
Bases:
objectA subdivision of a design space into \(m^L\) boxes per component.
The lower bound of a component is the sum of the fractions of the design space that its levels select,
\[\ell_j(\alpha) = L_j + \Delta_j \sum_{k=1}^{L} m^{-k} \, d_k(\alpha_j), \qquad u_j(\alpha) = \ell_j(\alpha) + \Delta_j \, m^{-L},\]with \(\Delta_j = U_j - L_j\) and \(d_k \in \{0, \dots, m-1\}\) the subdivision selected at level \(k\), one-hot encoded.
Two consequences make this usable where a flat subdivision is not.
The resolution grows as a power while the binaries grow as a product, so a resolution of \(1024\) over five variables costs \(100\) binaries instead of \(5120\). Since the density a budget can support is bounded by the binaries of the master and not by the boxes, this is what moves that bound.
The bounds stay affine in the one-hot variables and the width does not depend on them at all, so the mapping is bilinear in \((\xi, \alpha)\) exactly as the one-level mapping is, and the post-optimal sensitivity of the
Bendersformulation applies unchanged.
The counterpart is the model class: the cuts of the master are linear in the one-hot variables, so over the digits they are additive. They can represent what a level contributes on its own, and not that the contribution of a fine digit depends on the coarse digit it sits inside.
- Parameters:
lower_bounds (dict[str, ndarray])
upper_bounds (dict[str, ndarray])
branching (int)
levels (int)
- LEVEL_TEMPLATE: str = '{name}_level_{level}'#
The template naming the categorical variable of a level.
- NORMALIZED_SUFFIX: str = '_normalized'#
The suffix naming the normalized variable of a design variable.
- ONE_HOT_SUFFIX: str = '_box'#
The suffix naming the one-hot variable of a categorical variable.
- property variable_names: tuple[str, ...]#
The names of the design variables.
- property sizes: dict[str, int]#
The size of each design variable.
- property branching: int#
The number of subdivisions of a component at each level.
- property levels: int#
The number of levels.
- property resolution: int#
The number of subdivisions of a component the levels reach.
- property n_binaries: int#
The number of binaries of the master problem.
This is \(n m L\), against the \(n m^L\) a
BoxSubdivisionof the same resolution would need.
- property n_boxes: int#
The number of boxes the levels can select.
- property max_step: int#
The radius at which the trust region stops constraining the master.
The distance of the master counts the one-hot groups a candidate changes, and this subdivision has one group per level per component, against the one per component of a
BoxSubdivision.Note
As for a flat subdivision, this is not the radius to use: it marks where the region stops constraining. A radius letting the master move a couple of whole variables, that is
2 * levels, is what the measurements support.
- get_level_name(name, level)[source]#
Return the name of the categorical variable of a level.
- Parameters:
name (str) – The name of the design variable.
level (int) – The level, counted from one.
- Returns:
The name of the categorical variable.
- Return type:
str
- get_one_hot_name(name, level)[source]#
Return the name of the one-hot variable of a level.
A categorical variable is registered under the name of its one-hot encoding, as
create_box_design_space()does, so this is the name the design space, the master and the mapping all use.- Parameters:
name (str) – The name of the design variable.
level (int) – The level, counted from one.
- Returns:
The name of the one-hot variable.
- Return type:
str
- get_normalized_name(name)[source]#
Return the name of the normalized variable of a design variable.
- Parameters:
name (str) – The name of the design variable.
- Returns:
The name of the normalized variable.
- Return type:
str
- get_digit_values(level)[source]#
Return what each digit of a level is worth, as a fraction of a range.
- Parameters:
level (int) – The level, counted from one.
- Returns:
The fraction of the range each subdivision of the level selects.
- Return type:
ndarray
- compute_bounds(name, one_hots)[source]#
Return the bounds of the box the levels select.
- Parameters:
name (str) – The name of the design variable.
one_hots (Iterable[ndarray]) – The one-hot vector of each level, coarsest first.
- Returns:
The lower and upper bounds of the box.
- Return type:
tuple[ndarray, ndarray]
- locate(name, value)[source]#
Return the one-hot vector of each level holding a design value.
- Parameters:
name (str) – The name of the design variable.
value (ndarray) – The design value.
- Returns:
The one-hot vector of each level, coarsest first.
- Return type:
list[ndarray]
- create_design_space(design_space=None, value=None)[source]#
Return the design space of the master and of the sub-problem.
The normalized variables of the sub-problem span \([0, 1]\) whichever box is selected, and each level is a categorical variable weighted by ones, so that the distance of the trust region counts the digits a candidate changes.
- Parameters:
design_space (DesignSpace | None) – Unused, the bounds being held by this object.
value (dict | None) – The design value the levels should start from, by variable name. If
None, start from the center of the design space.
- Returns:
The design space.
- Return type:
CatalogueDesignSpace