Skip to content

Problem Definition and Sampling

sb_arch_opt.problem.ArchOptProblemBase(des_vars: Union[List[Variable], ArchDesignSpace], n_obj=1, n_ieq_constr=0, n_eq_constr=0, **kwargs)

Base class for an architecture optimization problem, featuring:

  • Mixed-discrete design variable definitions
  • Function for imputing a design vector and requesting the activeness vector (specifying which variables were active for the imputed design vector)
  • Interface to get a repair operator to implement design vector imputation

Design variable terminology:

  • Continuous: any value between some lower and upper bound (inclusive) --> for example [0, 1]: 0, 0.25, .667, 1
  • Discrete: integer or categorical
  • Integer: integer between 0 and some upper bound (inclusive); ordering and distance matters --> for example [0, 2]: 0, 1, 2
  • Categorical: one of n options, encoded as integers; ordering and distance are not defined --> for example [red, blue, yellow]: red, blue

Note that objectives (F) are always defined as minimization, inequality constraints (G) are satisfied when equal or lower than 0, and equality constraints (H) are satisfied when equal to 0. Conversion and normalization should be implemented in the evaluation function.

Also note that we are not exactly following the mixed-variable approach suggested by pymoo, but rather keeping the design vectors in a matrix with all different variable types in there. To facilitate this, categorical variables are encoded as integers, and the mixed-variable operators have been rewritten in SBArchOpt.

design_space = design_space instance-attribute

is_conditionally_active property

Boolean mask specifying for each design variable whether it is conditionally active or not

all_discrete_x: Tuple[Optional[np.ndarray], Optional[np.ndarray]] property

Generate all possible discrete design vectors, if the problem provides this function. Returns both the design vectors and activeness information. Active continuous variables may have any value within their bounds.

correct_x(x: np.ndarray) -> Tuple[np.ndarray, np.ndarray]

Imputes design vectors and returns activeness vectors

load_previous_results(results_folder) -> Optional[Population]

Return a Population (with X and F (optionally G and H) defined) created from previous results.

store_results(results_folder)

Callback function to store intermediate or final results in some results folder. Should include all previously evaluated design points.

get_categorical_values(x: np.ndarray, i_dv) -> np.ndarray

Gets the associated categorical variable values for some design variable

print_stats()

get_imputation_ratio() -> float

Returns the problem-level imputation ratio, a measure of how hierarchical the problem is. It is calculated from the product of the discrete and continuous imputation ratios.

get_correction_ratio() -> float

Returns the problem-level correction ratio, a measure of how much of the imputation ratio is due to a need for correction (i.e. value constraints). It is calculated from the product of the discrete and continuous correction ratios.

get_discrete_rates(force=False, show=False) -> Optional[pd.DataFrame]

Returns for each discrete value of the discrete design variables, how often the relatively occur over all possible design vectors. A value of -1 represents an inactive design variable. Results are returned in a pandas DataFrame with each column representing a design variable. Also adds a measure of rate diversity: difference between lowest and highest occurring values.

get_failure_rate() -> float

Estimate the failure rate: the fraction of randomly-sampled points of which evaluation will fail

get_n_declared_discrete() -> int

Returns the number of declared discrete design points (ignoring continuous dimensions), calculated from the cartesian product of discrete design variables

get_n_valid_discrete() -> Optional[int]

Return the number of valid discrete design points (ignoring continuous dimensions); enables calculation of the imputation ratio

get_n_correct_discrete() -> Optional[int]

Return the number of correct discrete design points (ignoring continuous dimensions); enables calculation of the correction ratio

_arch_evaluate(x: np.ndarray, is_active_out: np.ndarray, f_out: np.ndarray, g_out: np.ndarray, h_out: np.ndarray, *args, **kwargs)

Implement evaluation and write results in the provided output matrices: - x (design vectors): discrete variables have integer values, imputed design vectors can be output here (except if using an explicit design space definition) - is_active (activeness): vector specifying for each design variable whether it was active or not - f (objectives): written as a minimization - g (inequality constraints): written as "<= 0" - h (equality constraints): written as "= 0"

_correct_x(x: np.ndarray, is_active: np.ndarray)

Fill the activeness matrix and (if needed) correct any design variables that are partially inactive. Imputation of inactive design variables is always applied after this function.

Only needed if no explicit design space model is given. Only used if not all discrete design vectors all_discrete_x is available OR self.design_space.use_auto_corrector = False OR self.design_space.needs_cont_correction = True: --> set self.design_space.use_auto_corrector = False to prevent using an automatic corrector --> set self.design_space.needs_cont_correction = True if automatic correction can be used but also continuous variables might have to be corrected (the automatic corrector only corrects discrete variables)

sb_arch_opt.sampling.HierarchicalSampling(repair: Repair = None, sobol=True, seed=None)

Hierarchical mixed-discrete sampling. There are two ways the random sampling is performed: A: Generate and select: 1. Generate all possible discrete design vectors 2. Separate discrete design vectors based on discrete rate diversity 3. Within each group, uniformly sample discrete design vectors 4. Concatenate and randomize active continuous variables B: One-shot: 1. Randomly select design variable values 2. Repair/impute design vectors

The first way yields better results, as there is an even chance of selecting every valid discrete design vector, however it takes more memory and might be too much for very large design spaces.

sample_get_x(problem: ArchOptProblemBase, n_samples: int) -> Tuple[np.ndarray, np.ndarray]

Sample design points using the hierarchical sampling algorithm and return is_active information.

sb_arch_opt.design_space.ArchDesignSpace()

Base class for a hierarchical architecture design space definition. The basic information optimization algorithms need from a design space is as follows:

  • Design variable definition: types, bounds, options
  • Some way to exhaustively sample all discrete design vectors (aka full factorial; grid)
  • Activeness information: for a given matrix of design vectors, a boolean matrix specifying which vars are active
  • Imputation: correction of design vectors to canonical design vectors, setting inactive variables to some default value and correcting invalid variable values
  • Optionally calculate the design of the design space: number of valid discrete design vectors

Design variable terminology:

  • Continuous: any value between some lower and upper bound (inclusive) --> for example [0, 1]: 0, 0.25, .667, 1
  • Discrete: integer or categorical
  • Integer: integer between 0 and some upper bound (inclusive); ordering and distance matters --> for example [0, 2]: 0, 1, 2
  • Categorical: one of n options, encoded as integers; ordering and distance are not defined --> for example [red, blue, yellow]: red, blue

all_discrete_x: Tuple[Optional[np.ndarray], Optional[np.ndarray]] cached property

Generate all possible discrete design vectors, if the problem provides this function. Returns both the design vectors and activeness information. Active continuous variables may have any value within their bounds.

corrector: Optional[CorrectorInterface] cached property

Correction algorithm for problem-agnostic optimal correction in case all design vectors (all_discrete_x) are available. Set use_auto_corrector = False to force to use the problem-specific _correct_x function.

des_vars: List[Variable] cached property

Returns the defined design variables. Categorical variables (Choice) are encoded as integer values from 0 to n_opts-1. Use get_categorical_values to get the associated categorical values.

imputation_ratio: float cached property

Returns the problem-level imputation ratio, a measure of how hierarchical the problem is. It is calculated from the product of the discrete and continuous imputation ratios.

correction_ratio: float cached property

Returns the problem-level correction ratio, a measure of how much of the imputation ratio is due to a need for correction (i.e. value constraints). It is calculated from the product of the discrete and continuous correction ratios.

is_conditionally_active: np.ndarray cached property

Returns a mask specifying for each design variable whether it is conditionally active (i.e. may become inactive at some point).

is_cat_mask: np.ndarray cached property

Boolean vector specifying whether each variable is a categorical variable

is_cont_mask: np.ndarray cached property

Boolean vector specifying whether each variable is a continuous variable

is_discrete_mask: np.ndarray cached property

Boolean vector specifying whether each variable is a discrete (integer or categorical) variable

is_int_mask: np.ndarray cached property

Boolean vector specifying whether each variable is an integer (ordinal) variable

xl: np.ndarray cached property

Vector containing lower bounds of variables

xu: np.ndarray cached property

Vector containing upper bounds of variables

correct_x(x: np.ndarray) -> Tuple[np.ndarray, np.ndarray]

Imputes design vectors and returns activeness vectors

quick_sample_discrete_x(n: int) -> Tuple[np.ndarray, np.ndarray]

Sample n design vectors (also return is_active) without generating all design vectors first

get_categorical_values(x: np.ndarray, i_dv) -> np.ndarray

Gets the associated categorical variable values for some design variable

get_discrete_rates(force=False, show=False) -> Optional[pd.DataFrame]

Returns for each discrete value of the discrete design variables, how often the relatively occur over all possible design vectors. A value of -1 represents an inactive design variable. Results are returned in a pandas DataFrame with each column representing a design variable. Also adds a measure of rate diversity: difference between lowest and highest occurring values.

get_n_declared_discrete() -> int

Returns the number of declared discrete design points (ignoring continuous dimensions), calculated from the cartesian product of discrete design variables

get_n_valid_discrete() -> Optional[int]

Return the number of valid discrete design points (ignoring continuous dimensions); enables calculation of the imputation ratio

get_n_correct_discrete() -> Optional[int]

Return the number of correct design points (ignoring continuous dimensions); enables calculation of the correction ratio