### Install arch_sbo dependencies with pip Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Install the optional dependencies required for the ArchSBO algorithm. Run this command before using the ArchSBO example. ```bash pip install sb-arch-opt[arch_sbo] ``` -------------------------------- ### Install sb-arch-opt with BoTorch support Source: https://sbarchopt.readthedocs.io/en/stable/algo/botorch Install the package with the botorch extra to enable BoTorch functionality. ```bash pip install sb-arch-opt[botorch] ``` -------------------------------- ### Install sb-arch-opt with Egor support Source: https://sbarchopt.readthedocs.io/en/stable/algo/egor Install the sb-arch-opt package with the egor extra to enable the Egor optimizer interface. ```bash pip install sb-arch-opt[egor] ``` -------------------------------- ### Install HEBO with pip Source: https://sbarchopt.readthedocs.io/en/stable/algo/hebo Install the sb-arch-opt package with the HEBO extra using pip. ```bash pip install sb-arch-opt[hebo] ``` -------------------------------- ### Install ArchSBO with pip Source: https://sbarchopt.readthedocs.io/en/stable/algo/arch_sbo Install the sb-arch-opt package with the arch_sbo extra to use the ArchSBO algorithm. ```bash pip install sb-arch-opt[arch_sbo] ``` -------------------------------- ### Getting a ready-to-use NSGA2 Source: https://sbarchopt.readthedocs.io/en/stable/algo/pymoo Retrieves a pre-configured NSGA2 algorithm instance. ```python from sb_arch_opt.algo.pymoo_interface import get_nsga2 nsga2 = get_nsga2(pop_size=100) ``` -------------------------------- ### Install TPE algorithm Source: https://sbarchopt.readthedocs.io/en/stable/algo/tpe Use pip to install the package with the TPE dependency. ```bash pip install sb-arch-opt[tpe] ``` -------------------------------- ### Initialize and run TPE algorithm Source: https://sbarchopt.readthedocs.io/en/stable/algo/tpe Configure the TPEAlgorithm with a results folder and integrate it with the pymoo minimize interface. The example demonstrates initializing from previous results to skip initial evaluations. ```python from pymoo.optimize import minimize from sb_arch_opt.algo.tpe_interface import * problem = ... # Subclass of ArchOptProblemBase # Enable intermediate results storage results_folder_path = 'path/to/results/folder' # Get TPE algorithm n_init = 100 algo = TPEAlgorithm(n_init=n_init, results_folder=results_folder_path) # Start from previous results (skipped if no previous results are available) if initialize_from_previous_results(algo, problem, results_folder_path): # No need to evaluate any initial points, as they already have been evaluated n_init = 0 n_infill = 10 result = minimize(problem, algo, termination=('n_eval', n_init + n_infill)) ``` -------------------------------- ### Run Evolutionary Algorithm (SBO) Optimization Source: https://sbarchopt.readthedocs.io/en/stable/tutorial This example initializes a HierZDT1Small problem, configures the SBO algorithm with parallel evaluation, and executes the optimization process. ```python from sb_arch_opt.algo.pymoo_interface import plot from pymoo.optimize import minimize from sb_arch_opt.problems.hierarchical import HierZDT1Small from sb_arch_opt.algo.arch_sbo.api import get_arch_sbo_gp # Create the problem problem = HierZDT1Small() # Create the algorithm (with an initial database size of 10*n_var = 10*6 = 60) n_init = problem.n_var*10 sbo = get_arch_sbo_gp(problem, n_parallel=4, init_size=n_init) # Run the optimization: 100 infill points (60 + 100 = 160 evaluations) # NOTE: remove "seed" argument when using in production! n_infill = 100 result_sbo = minimize(problem, sbo, termination=('n_eval', n_init+n_infill), seed=42) # Plot results plot(result_nsga2.opt.get('F'), result_sbo.opt.get('F'), labels=['NSGA2 (2000 evaluations)', 'SBO (160 evaluations)']) ``` -------------------------------- ### Install SBArchOpt Package Source: https://sbarchopt.readthedocs.io/en/stable Install the required dependencies and the SBArchOpt package via Conda and pip. ```bash conda install numpy pip install sb-arch-opt ``` -------------------------------- ### Continue optimization from previous DoE results Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Example of loading previous results and continuing an NSGA2 optimization. ```python # Continue with an optimization from previous DoE results nsga2 = get_nsga2(pop_size=100) initialize_from_previous_results(nsga2, problem, results_folder) result = minimize(problem, nsga2, termination=('n_gen', 10), copy_algorithm=False, seed=42) assert abs(nsga2.evaluator.n_eval - 1100) < 10 # 200 from DoE + 9*100 from optimization plot(problem.pareto_front(), result.opt.get('F'), labels=['Known Pareto front', 'NSGA2 (10 gen)']) ``` ```text INFO 2025-12-01 16:24:26,393 sb_arch_opt.pymoo : Previous results loaded from pymoo results: 200 design points INFO 2025-12-01 16:24:26,393 sb_arch_opt.pymoo : Evaluation status: 200 of 200 (100.0%) are already evaluated ``` -------------------------------- ### Install Trieste via pip Source: https://sbarchopt.readthedocs.io/en/stable/algo/trieste Use this command to install the Trieste library as part of the sb-arch-opt package. ```bash pip install sb-arch-opt[trieste] ``` -------------------------------- ### Implement Jenatton Test Problem Implicitly Source: https://sbarchopt.readthedocs.io/en/stable/tutorial This example demonstrates how to implement a hierarchical architecture optimization problem by extending ArchOptProblemBase and defining custom correction functions for variable activeness. ```python import numpy as np from pymoo.core.variable import Real, Choice from sb_arch_opt.problem import ArchOptProblemBase # Define the evaluation function # You can clearly see the hierarchical structure def jenatton_evaluate(x): if x[0] == 0: if x[1] == 0: return x[3]**3 + .1 + x[7] else: return x[4]**3 + .1 + x[7] else: if x[2] == 0: return x[5]**3 + .1 + x[8] else: return x[6]**3 + .1 + x[8] class JenattonImplicit(ArchOptProblemBase): def __init__(self): # Define the design variables using pymoo variable classes des_vars = [ Choice(options=[0, 1]), Choice(options=[0, 1]), Choice(options=[0, 1]), # x1,2,3 Real(bounds=[0, 1]), Real(bounds=[0, 1]), Real(bounds=[0, 1]), # x4,5,6 Real(bounds=[0, 1]), Real(bounds=[0, 1]), Real(bounds=[0, 1]), # x7,8,9 ] super().__init__(des_vars=des_vars) def _arch_evaluate(self, 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 - 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" """ # Call the correction function to output which variables are inactive self._correct_x_impute(x, is_active_out) # Evaluate the design vectors for i, xi in enumerate(x): f_out[i, 0] = jenatton_evaluate(xi) def _correct_x(self, x: np.ndarray, is_active: np.ndarray): """Fill the activeness matrix and (if needed) impute any design variables that are partially inactive. Imputation of inactive design variables is always applied after this function.""" # Start from everything inactive except the first variable is_active[:, 1:] = False # First branch branch1_1 = x[:, 0] == 0 branch1_2 = x[:, 0] == 1 is_active[branch1_1, 1] = True # x2 and x8 are active in branch 1,1 is_active[branch1_1, 7] = True is_active[branch1_2, 2] = True # x3 and x9 are active in branch 1,2 is_active[branch1_2, 8] = True # x1 and x2 branch branch2_1 = branch1_1 & (x[:, 1] == 0) branch2_2 = branch1_1 & (x[:, 1] == 1) branch2_3 = branch1_2 & (x[:, 2] == 0) branch2_4 = branch1_2 & (x[:, 2] == 1) is_active[branch2_1, 3] = True is_active[branch2_2, 4] = True is_active[branch2_3, 5] = True is_active[branch2_4, 6] = True def _is_conditionally_active(self): """Return for each design variable whether it is conditionally active (i.e. might become inactive). Not needed if an explicit design space is provided.""" # Only the first variable never becomes inactive return [False if i == 0 else True for i in range(self.n_var)] def _get_n_active_cont_mean(self) -> int: """Get the mean number of active continuous dimensions, as seen over all discrete design vectors.""" # Each of the four discrete branches has 2 active continuous variables return 2 def _get_n_valid_discrete(self) -> int: """Return the number of valid discrete design points (ignoring continuous dimensions); enables calculation of the imputation ratio. Not needed if an explicit design space is provided.""" return 4 def __repr__(self): return f'{self.__class__.__name__}()' JenattonImplicit().print_stats() ``` -------------------------------- ### x property Source: https://sbarchopt.readthedocs.io/en/stable/api/egor Gets the design vectors. ```APIDOC ## x property ### Description Design vectors. ### Returns - **x** (np.ndarray) - The design vectors. ``` -------------------------------- ### get_trieste_optimizer(problem, n_init, n_infill, pof, seed) Source: https://sbarchopt.readthedocs.io/en/stable/api/trieste Gets the main interface to Trieste. Use the run_optimization method to run the DOE and infill loops. ```APIDOC ## get_trieste_optimizer(problem, n_init, n_infill, pof, seed) ### Description Gets the main interface to Trieste. Use the run_optimization method to run the DOE and infill loops. ### Parameters - **problem** (ArchOptProblemBase) - Required - The optimization problem. - **n_init** (int) - Required - Number of initial samples. - **n_infill** (int) - Required - Number of infill samples. - **pof** (float) - Optional - Probability of feasibility, default 0.5. - **seed** (int) - Optional - Random seed. ### Returns - The main interface to Trieste. ``` -------------------------------- ### f property Source: https://sbarchopt.readthedocs.io/en/stable/api/egor Gets the objective values. ```APIDOC ## f property ### Description Objective values. ### Returns - **f** (np.ndarray) - The objective values. ``` -------------------------------- ### Define JenattonExplicit Architecture Optimization Problem Source: https://sbarchopt.readthedocs.io/en/stable/tutorial This example demonstrates defining a hierarchical design space using ExplicitArchDesignSpace and implementing the _arch_evaluate method for evaluation. ```python from sb_arch_opt.design_space_explicit import * class JenattonExplicit(ArchOptProblemBase): def __init__(self): # We define the hierarchical structure using the explicit design space class # The design variables are defined by ds = ExplicitArchDesignSpace([ CategoricalParam('x1', [0, 1]), CategoricalParam('x2', [0, 1]), CategoricalParam('x3', [0, 1]), ContinuousParam('x4', 0, 1), ContinuousParam('x5', 0, 1), ContinuousParam('x6', 0, 1), ContinuousParam('x7', 0, 1), ContinuousParam('r8', 0, 1), ContinuousParam('r9', 0, 1), ]) # Define activation conditions ds.add_conditions([ # x2 and r8 are activated if x1 == 0 EqualsCondition(ds['x2'], ds['x1'], 0), EqualsCondition(ds['r8'], ds['x1'], 0), # x4 and x5 are additionally only activated if x2 == 0 or 1, respectively EqualsCondition(ds['x4'], ds['x2'], 0), EqualsCondition(ds['x5'], ds['x2'], 1), # x1 == 1 activates x3, r9 EqualsCondition(ds['x3'], ds['x1'], 1), EqualsCondition(ds['r9'], ds['x1'], 1), # x6 and x7 are additionally only activated if x3 == 0 or 1, respectively EqualsCondition(ds['x6'], ds['x3'], 0), EqualsCondition(ds['x7'], ds['x3'], 1), ]) super().__init__(ds) def _arch_evaluate(self, x: np.ndarray, is_active_out: np.ndarray, f_out: np.ndarray, g_out: np.ndarray, h_out: np.ndarray, *args, **kwargs): # No need to call the correction function, because the input is automatically # corrected according to the design space definition # Evaluate the design vectors for i, xi in enumerate(x): f_out[i, 0] = jenatton_evaluate(xi) def __repr__(self): return f'{self.__class__.__name__}()' # Note how the problem definition is exactly the same as the implicit definition JenattonExplicit().print_stats() ``` -------------------------------- ### get_smarty_optimizer(problem, n_init, n_infill) Source: https://sbarchopt.readthedocs.io/en/stable/api/smarty Gets the main interface to SMARTy. Use the optimize method to run the DOE and infill loops. ```APIDOC ## get_smarty_optimizer(problem: ArchOptProblemBase, n_init: int, n_infill: int) ### Description Gets the main interface to SMARTy. Use the `optimize` method to run the DOE and infill loops. ### Parameters - **problem** (ArchOptProblemBase) - Required - The optimization problem. - **n_init** (int) - Required - Number of initialization points. - **n_infill** (int) - Required - Number of infill points. ### Returns - **SMARTyArchOptInterface** - The SMARTy interface object. ``` -------------------------------- ### AxInterface.get_optimization_loop(n_init, n_infill, seed) Source: https://sbarchopt.readthedocs.io/en/stable/api/botorch Gets the optimization loop for the Ax optimization process. ```APIDOC ## AxInterface.get_optimization_loop(n_init, n_infill, seed) ### Description Gets the optimization loop for the Ax optimization process. ### Method Method ### Signature `get_optimization_loop(n_init: int, n_infill: int, seed: int = None) -> OptimizationLoop` ### Parameters - **n_init** (int) - Required - Number of initial points. - **n_infill** (int) - Required - Number of infill points. - **seed** (int) - Optional - Random seed. ### Returns - **OptimizationLoop** - The optimization loop. ``` -------------------------------- ### Use get_hebo_optimizer to run HEBO optimization Source: https://sbarchopt.readthedocs.io/en/stable/algo/hebo Shows how to create a HEBO optimizer interface for an ArchOptProblemBase subclass, run the optimization loop, and extract the results as a pymoo Population object. The example uses n_init=100 and n_infill=50 with a fixed seed. ```python from sb_arch_opt.algo.hebo_interface import get_hebo_optimizer problem = ... # Subclass of ArchOptProblemBase # Get the interface and optimization loop hebo = get_hebo_optimizer(problem, n_init=100, seed=42) # Run the optimization loop hebo.optimize(n_infill=50) # Extract data as a pymoo Population object pop = hebo.pop ``` -------------------------------- ### get_botorch_interface(problem) Source: https://sbarchopt.readthedocs.io/en/stable/api/botorch Gets the main interface to Ax and BoTorch for a given optimization problem. ```APIDOC ## get_botorch_interface(problem) ### Description Gets the main interface to Ax and BoTorch. ### Method Function ### Signature `sb_arch_opt.algo.botorch_interface.api.get_botorch_interface(problem: ArchOptProblemBase)` ### Parameters - **problem** (ArchOptProblemBase) - Required - The optimization problem to interface with. ``` -------------------------------- ### get_hebo_optimizer(problem, n_init, seed=None) Source: https://sbarchopt.readthedocs.io/en/stable/api/hebo Gets the main interface to HEBO. Use the optimize method to run the DOE and infill loops. ```APIDOC ## get_hebo_optimizer(problem, n_init, seed=None) ### Description Gets the main interface to HEBO. Use the optimize method to run the DOE and infill loops. ### Method Function ### Signature `sb_arch_opt.algo.hebo_interface.get_hebo_optimizer(problem: ArchOptProblemBase, n_init: int, seed: int = None)` ### Parameters - **problem** (ArchOptProblemBase) - Required - The optimization problem. - **n_init** (int) - Required - Number of initialization points. - **seed** (int) - Optional - Random seed. ### Returns - HEBOArchOptInterface - The HEBO interface object. ``` -------------------------------- ### AxInterface.get_population(opt_loop) Source: https://sbarchopt.readthedocs.io/en/stable/api/botorch Gets the population from the optimization loop. ```APIDOC ## AxInterface.get_population(opt_loop) ### Description Gets the population from the optimization loop. ### Method Method ### Signature `get_population(opt_loop: OptimizationLoop) -> Population` ### Parameters - **opt_loop** (OptimizationLoop) - Required - The optimization loop. ### Returns - **Population** - The population. ``` -------------------------------- ### Implement DemoExplicitArchOptProblem with ExplicitArchDesignSpace Source: https://sbarchopt.readthedocs.io/en/stable An example implementation of an architecture optimization problem using explicit design space definitions, including categorical, integer, and continuous parameters with conditional activation and value constraints. ```python import numpy as np from sb_arch_opt.design_space_explicit import * from sb_arch_opt.problem import ArchOptProblemBase class DemoExplicitArchOptProblem(ArchOptProblemBase): """ An example of an architecture problem implementation using an explicit design space definition. Using this, there is no need to implement _correct_x, _get_n_valid_discrete, and _gen_all_discrete_x. """ def __init__(self): # Specify a design space with a categorical, an integer, and a continuous variable ds = ExplicitArchDesignSpace([ CategoricalParam('cat', ['A', 'B', 'C']), IntegerParam('int', 0, 3), ContinuousParam('cont', 0, 1), ]) # Activate int and cont conditionally ds.add_conditions([ InCondition(ds['int'], ds['cat'], ['A', 'B']), # Activate int if cat == A or cat == B EqualsCondition(ds['cont'], ds['cat'], 'A'), # Activate cont if cat == A ]) # Explicitly forbid int from being 3 if cat == B # You can also specify the values as a list to constrain more than one value at a time ds.add_value_constraint(ds['int'], 3, ds['cat'], 'B') super().__init__(ds, n_obj=1) def _arch_evaluate(self, 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: - f (objectives): written as a minimization - g (inequality constraints): written as "<= 0" - h (equality constraints): written as "= 0" For the explicit design space definition, x and is_active_out are already imputed. If anything is wrong, then you should change the design space definition rather than trying to fix it here. """ # Example of how to set objective values f_out[:, 0] = np.sum(x ** 2, axis=1) def __repr__(self): """repr() of the class, should be unique for unique Pareto fronts""" return f'{self.__class__.__name__}()' ``` -------------------------------- ### egor property Source: https://sbarchopt.readthedocs.io/en/stable/api/egor Gets the native Egor optimizer object. ```APIDOC ## egor property ### Description Get the native Egor optimizer object. See help(egobox.Egor) for more information. ### Returns - **egor** - The native Egor optimizer object. ``` -------------------------------- ### Initialize temporary directory for SBO Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Sets up a temporary directory to store SBO results. ```python td_sbo = tempfile.TemporaryDirectory() results_folder = td_sbo.name ``` -------------------------------- ### ArchOptNSGA2(pop_size=100, sampling=HierarchicalSampling(), repair=ArchOptRepair(), mating=MixedDiscreteMating(repair=ArchOptRepair(), eliminate_duplicates=LargeDuplicateElimination()), eliminate_duplicates=LargeDuplicateElimination(), survival=RankAndCrowdingSurvival(), output=EHVMultiObjectiveOutput(), results_folder=None, **kwargs) Source: https://sbarchopt.readthedocs.io/en/stable/api/pymoo NSGA2 preconfigured with mixed-variable operators and other architecture optimization measures. ```APIDOC ## ArchOptNSGA2(pop_size=100, sampling=HierarchicalSampling(), repair=ArchOptRepair(), mating=MixedDiscreteMating(repair=ArchOptRepair(), eliminate_duplicates=LargeDuplicateElimination()), eliminate_duplicates=LargeDuplicateElimination(), survival=RankAndCrowdingSurvival(), output=EHVMultiObjectiveOutput(), results_folder=None, **kwargs) ### Description NSGA2 preconfigured with mixed-variable operators and other architecture optimization measures. ### Parameters - **pop_size** (int) - Optional - Population size (default 100). - **sampling** - Optional - Sampling strategy (default HierarchicalSampling()). - **repair** - Optional - Repair operator (default ArchOptRepair()). - **mating** - Optional - Mating strategy (default MixedDiscreteMating with repair and duplicate elimination). - **eliminate_duplicates** - Optional - Duplicate elimination strategy (default LargeDuplicateElimination()). - **survival** - Optional - Survival strategy (default RankAndCrowdingSurvival()). - **output** - Optional - Output strategy (default EHVMultiObjectiveOutput()). - **results_folder** - Optional - Folder to store results. - **kwargs** - Additional keyword arguments. ### Returns - ArchOptNSGA2 instance. ``` -------------------------------- ### Initialize Algorithm with Results Folder Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Creates an NSGA2 algorithm instance with a specified results folder and runs it for a set number of generations. ```python import tempfile # We create a temporary folder for demonstration purposes td = tempfile.TemporaryDirectory() results_folder = td.name # Create the algorithm with the results folder nsga2 = get_nsga2(pop_size=100, results_folder=results_folder) # Run for a few generations result5 = minimize(problem, nsga2, termination=('n_gen', 5), copy_algorithm=False, seed=42) assert abs(nsga2.evaluator.n_eval - 500) < 10 # 5*100 plot(problem.pareto_front(), result5.opt.get('F'), labels=['Known Pareto front', 'NSGA2 (5 gen)']) ``` -------------------------------- ### g property Source: https://sbarchopt.readthedocs.io/en/stable/api/egor Gets the inequality constraints. ```APIDOC ## g property ### Description Inequality constraints. ### Returns - **g** (np.ndarray) - The inequality constraints. ``` -------------------------------- ### Continue optimization from previous DoE results Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Initializes an NSGA2 algorithm from previous DoE results and continues the optimization process. ```python # Continue with an optimization from previous DoE results nsga2 = get_nsga2(pop_size=100) initialize_from_previous_results(nsga2, problem, results_folder) result = minimize(problem, nsga2, termination=('n_gen', 10), copy_algorithm=False, seed=42) assert abs(nsga2.evaluator.n_eval - 1100) < 10 # 200 from DoE + 9*100 from optimization plot(problem.pareto_front(), result.opt.get('F'), labels=['Known Pareto front', 'NSGA2 (10 gen)']) ``` -------------------------------- ### pop property Source: https://sbarchopt.readthedocs.io/en/stable/api/egor Gets the population of all evaluated points. ```APIDOC ## pop property ### Description Population of all evaluated points. ### Returns - **pop** (Population) - The population of all evaluated points. ``` -------------------------------- ### Run Optimization with Preconfigured NSGA2 Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Instantiate the NSGA2 algorithm using get_nsga2 and execute the optimization process via the pymoo minimize function. ```python from pymoo.optimize import minimize from sb_arch_opt.algo.pymoo_interface import get_nsga2 # Create the pre-configured NSGA2 algorithm nsga2 = get_nsga2(pop_size=100) # Run the optimization result = minimize(problem, nsga2, termination=('n_gen', 20), seed=42) # Compare results plot(problem.pareto_front(), result.opt.get('F'), labels=['Known Pareto front', 'NSGA2']) ``` -------------------------------- ### AxInterface.get_search_space() Source: https://sbarchopt.readthedocs.io/en/stable/api/botorch Gets the search space as defined by the underlying problem. ```APIDOC ## AxInterface.get_search_space() ### Description Gets the search space as defined by the underlying problem. ### Method Method ### Signature `get_search_space() -> SearchSpace` ### Returns - **SearchSpace** - The search space. ``` -------------------------------- ### Use ArchSBO with pymoo minimize Source: https://sbarchopt.readthedocs.io/en/stable/algo/arch_sbo Shows how to set up and run the ArchSBO algorithm (Kriging or RBF) with pymoo's minimize function. It includes initializing from previous results and setting the termination criterion. The seed is set to 42 for reproducibility but should be removed in production. ```python from pymoo.optimize import minimize from sb_arch_opt.algo.arch_sbo import get_arch_sbo_gp, get_arch_sbo_rbf problem = ... # Subclass of ArchOptProblemBase # Get Kriging or RBF algorithm n_init = 100 results_folder_path = 'path/to/results/folder' gp_arch_sbo_algo = get_arch_sbo_gp(problem, init_size=n_init, results_folder=results_folder_path) # Start from previous results (skipped if no previous results are available) gp_arch_sbo_algo.initialize_from_previous_results(problem, results_folder_path) n_infill = 10 result = minimize(problem, gp_arch_sbo_algo, termination=('n_eval', n_init + n_infill), seed=42) # Remove seed in production ``` -------------------------------- ### ArchDesignSpace.get_categorical_values Source: https://sbarchopt.readthedocs.io/en/stable/api/problem Gets the associated categorical variable values for some design variable. ```APIDOC ## get_categorical_values(x: np.ndarray, i_dv) -> np.ndarray ### Description Gets the associated categorical variable values for some design variable. ### Method get_categorical_values ### Parameters - **x** (np.ndarray) - Required - Design vectors. - **i_dv** - Required - Index of the design variable. ### Returns - **np.ndarray** - Categorical values for the specified design variable. ``` -------------------------------- ### initialize_from_previous_results(algorithm, problem, result_folder, **kwargs) -> bool Source: https://sbarchopt.readthedocs.io/en/stable/api/pymoo Initialize an Algorithm from previously stored results. ```APIDOC ## initialize_from_previous_results(algorithm: Algorithm, problem: ArchOptProblemBase, result_folder: str, **kwargs) -> bool ### Description Initialize an Algorithm from previously stored results. ### Parameters - **algorithm** (Algorithm) - Required - The algorithm to initialize. - **problem** (ArchOptProblemBase) - Required - The optimization problem. - **result_folder** (str) - Required - Folder containing previous results. - **kwargs** - Additional keyword arguments. ### Returns - bool - Whether initialization was successful. ``` -------------------------------- ### Initialize and run the Trieste optimizer Source: https://sbarchopt.readthedocs.io/en/stable/algo/trieste This snippet demonstrates how to obtain the Trieste optimizer interface, initialize it from existing results, and execute the optimization loop. ```python from sb_arch_opt.algo.trieste_interface import get_trieste_optimizer problem = ... # Subclass of ArchOptProblemBase # Get the interface and optimization loop optimizer = get_trieste_optimizer(problem, n_init=100, n_infill=50, seed=42) # Start from previous results (skipped if no previous results are available) results_folder_path = 'path/to/results/folder' optimizer.initialize_from_previous(results_folder_path) # Run the optimization loop (the results folder is optional) result = optimizer.run_optimization(results_folder=results_folder_path) # Extract data as a pymoo Population object pop = optimizer.to_population(result.datasets) ``` -------------------------------- ### Provisioning a pymoo GA algorithm Source: https://sbarchopt.readthedocs.io/en/stable/algo/pymoo Demonstrates how to provision a standard pymoo Genetic Algorithm with architecture optimization repair operators. ```python from pymoo.optimize import minimize from pymoo.algorithms.soo.nonconvex.ga import GA from sb_arch_opt.algo.pymoo_interface import provision_pymoo problem = ... # Subclass of ArchOptProblemBase ga_algorithm = GA(pop_size=100) provision_pymoo(ga_algorithm) # See intermediate results storage below result = minimize(problem, ga_algorithm, termination=('n_gen', 10), seed=42) # Remove seed when using in production! ``` -------------------------------- ### design_space property Source: https://sbarchopt.readthedocs.io/en/stable/api/egor Gets the design space as a native Egor input specification. ```APIDOC ## design_space property ### Description Get the design space a native Egor input specification. ### Returns - **design_space** (list[egx.XSpec]) - The design space specification. ``` -------------------------------- ### ArchOptBayesianOptimizer(problem, n_init, n_infill, pof, rule, seed) Source: https://sbarchopt.readthedocs.io/en/stable/api/trieste Bayesian optimization loop controller with some extra helper functions. Use the run_optimization function to run the DOE and infill loops. Use initialize_from_previous to initialize the optimization state from previously saved results. ```APIDOC ## ArchOptBayesianOptimizer(problem, n_init, n_infill, pof, rule, seed) ### Description Bayesian optimization loop controller with some extra helper functions. Use the run_optimization function to run the DOE and infill loops. Use initialize_from_previous to initialize the optimization state from previously saved results. ### Parameters - **problem** (ArchOptProblemBase) - Required - The optimization problem. - **n_init** (int) - Required - Number of initial samples. - **n_infill** (int) - Required - Number of infill samples. - **pof** (float) - Optional - Probability of feasibility, default 0.5. - **rule** (AcquisitionRule) - Optional - Acquisition rule. - **seed** (int) - Optional - Random seed. ### Methods #### initialize_from_previous(results_folder) - **results_folder** (str) - Required - Folder containing previously saved results. #### run_optimization(results_folder=None) -> Record - **results_folder** (str) - Optional - Folder to save results. - Returns a Record object. #### to_population(datasets) -> Population - **datasets** (Dict[Hashable, Dataset]) - Required - Datasets to convert. - Returns a Population object. ``` -------------------------------- ### SEGOMOEInterface.initialize_from_previous Source: https://sbarchopt.readthedocs.io/en/stable/api/segomoe Method to initialize the optimization from a previous run. ```APIDOC ## SEGOMOEInterface.initialize_from_previous ### Description Initializes the optimization from a previous run, optionally using a different results folder. ### Method `initialize_from_previous(results_folder: str = None)` ### Parameters - **results_folder** (str) - Optional - Path to the results folder of the previous run. If None, uses the current results folder. ``` -------------------------------- ### initialize_from_previous(results_folder=None) Source: https://sbarchopt.readthedocs.io/en/stable/api/egor Initializes the algorithm from previously stored results. ```APIDOC ## initialize_from_previous(results_folder=None) ### Description Initialize the algorithm from previously stored results. Note: Previous results might be generated on a previous run when the results_folder is specified in EgorArchOptInterface constructor. ### Parameters - **results_folder** (str) - Optional - Folder containing previous results. ``` -------------------------------- ### InfillAlgorithm - initialize_from_previous_results Source: https://sbarchopt.readthedocs.io/en/stable/api/arch_sbo Initializes the SBO algorithm from previously stored intermediate results, enabling resumption of an optimization run. ```APIDOC ## InfillAlgorithm.initialize_from_previous_results ### Description Initialize the SBO algorithm from previously stored results, allowing continuation from an earlier optimization run. ### Method Method call ### Parameters - **problem** (ArchOptProblemInfo) - The optimization problem instance. - **result_folder** (str) - Path to the folder containing previous intermediate results. ### Return Value Returns `True` if the initialization succeeds; otherwise `False`. ``` -------------------------------- ### Instantiate and Analyze HierZDT1Small Problem Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Instantiates the HierZDT1Small problem class and prints its statistical properties, including hierarchy and diversity metrics. ```python from sb_arch_opt.problems.hierarchical import HierZDT1Small # Instantiate the problem class and print some statistics problem = HierZDT1Small() problem.print_stats() ``` -------------------------------- ### Restart Optimization from Previous Results Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Initializes an algorithm from previously generated results and continues the optimization process. ```python from sb_arch_opt.algo.pymoo_interface import initialize_from_previous_results # Now create the algorithm again and initialize it from previously-generated results nsga2 = get_nsga2(pop_size=100) initialize_from_previous_results(nsga2, problem, results_folder) # NOTE: normally you'd of course also pass the results folder here, # but we omit it to prevent updating previous results in the notebook # nsga2 = get_nsga2(pop_size=100, results_folder=results_folder) # Previously-generated results count towards the evaluation budget, # however not to the iteration ("generations") budget result10 = minimize(problem, nsga2, termination=('n_gen', 6), copy_algorithm=False, seed=42) assert abs(nsga2.evaluator.n_eval - 1000) < 10 # 500 from previous + 5*100 continued optimization plot(problem.pareto_front(), result5.opt.get('F'), result10.opt.get('F'), labels=['Known Pareto front', 'NSGA2 (5 gen)', 'NSGA2 (10 gen)']) ``` ```text INFO 2025-12-01 16:24:22,186 sb_arch_opt.pymoo : Previous results loaded from pymoo results: 500 design points INFO 2025-12-01 16:24:22,186 sb_arch_opt.pymoo : Evaluation status: 500 of 500 (100.0%) are already evaluated ``` -------------------------------- ### Solve HierZDT1Small with ArchSBO Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Runs the ArchSBO surrogate-based optimization algorithm on HierZDT1Small with 4 parallel workers, an initial database of 60 points, and 100 infill evaluations (160 total). Plots NSGA2 and SBO results for comparison. Requires the arch_sbo dependencies and a seed for reproducibility. ```python from sb_arch_opt.algo.pymoo_interface import plot from pymoo.optimize import minimize from sb_arch_opt.problems.hierarchical import HierZDT1Small from sb_arch_opt.algo.arch_sbo.api import get_arch_sbo_gp # Create the problem problem = HierZDT1Small() # Create the algorithm (with an initial database size of 10*n_var = 10*6 = 60) n_init = problem.n_var*10 sbo = get_arch_sbo_gp(problem, n_parallel=4, init_size=n_init) # Run the optimization: 100 infill points (60 + 100 = 160 evaluations) # NOTE: remove "seed" argument when using in production! n_infill = 100 result_sbo = minimize(problem, sbo, termination=('n_eval', n_init+n_infill), seed=42) # Plot results plot(result_nsga2.opt.get('F'), result_sbo.opt.get('F'), labels=['NSGA2 (2000 evaluations)', 'SBO (160 evaluations)']) ``` -------------------------------- ### SEGOMOEInterface.__init__ Source: https://sbarchopt.readthedocs.io/en/stable/api/segomoe Constructor for the SEGOMOEInterface class. Initializes the interface with the given problem, results folder, and optimization settings. ```APIDOC ## SEGOMOEInterface.__init__ ### Description Initializes a new instance of the SEGOMOEInterface class. ### Method Constructor ### Signature `SEGOMOEInterface(problem: ArchOptProblemBase, results_folder: str, n_init: int, n_infill: int, use_moe=True, sego_options=None, model_options=None, verbose=True)` ### Parameters - **problem** (ArchOptProblemBase) - Required - The optimization problem to solve. - **results_folder** (str) - Required - Folder where results will be stored. - **n_init** (int) - Required - Number of initial samples. - **n_infill** (int) - Required - Number of infill samples. - **use_moe** (bool) - Optional - Whether to use multi-objective optimization (default: True). - **sego_options** (dict) - Optional - Additional options for SEGOMOE. - **model_options** (dict) - Optional - Additional options for the surrogate model. - **verbose** (bool) - Optional - Whether to print progress information (default: True). ``` -------------------------------- ### DOEAlgorithm(*args, **kwargs) Source: https://sbarchopt.readthedocs.io/en/stable/api/pymoo Algorithm that stops after initialization. ```APIDOC ## DOEAlgorithm(*args, **kwargs) ### Description Algorithm that stops after initialization. ### Parameters - **args** - Positional arguments. - **kwargs** - Keyword arguments. ### Methods #### set_doe_size(problem, doe_size: int, **kwargs) -> bool Set the DOE size, also if the algo is already initialized with a prior population. Returns whether the DOE size was increased. ##### Parameters - **problem** - Required - The optimization problem. - **doe_size** (int) - Required - The DOE size. - **kwargs** - Additional keyword arguments. ##### Returns - bool - Whether the DOE size was increased. ``` -------------------------------- ### Use get_egor_optimizer to run Egor optimization Source: https://sbarchopt.readthedocs.io/en/stable/algo/egor Shows how to create an Egor optimizer interface, optionally initialize from previous results, run the optimization loop, and extract results as numpy arrays or a pymoo Population object. ```python from sb_arch_opt.algo.egor_interface import get_egor_optimizer problem = ... # Subclass of ArchOptProblemBase # Get the interface and optimization loop egor = get_egor_optimizer(problem, n_init=100, seed=42) # Start from previous results (optional) results_folder_path = 'path/to/results/folder' egor.initialize_from_previous(results_folder_path) # Run the optimization loop (the results folder to store results is optional) result = egor.minimize(results_folder=results_folder_path) # Extract result as numpy arrays print(f"Minimum {result.y_opt} at {result.x_opt}") print(f"History {result.x_hist} {result.y_hist}") # Extract data as a pymoo Population object pop = egor.pop ``` -------------------------------- ### Execute optimization and compare results Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Runs the minimize function with JenattonExplicit and NSGA2, then prints the comparison between explicit and implicit results. ```python result_expl = minimize(JenattonExplicit(), get_nsga2(pop_size=50), termination=('n_gen', 20), seed=42) print(f'Optimum: {result_expl.opt.get("F")}; implicit: {result_impl.opt.get("F")}; difference = {result_expl.opt.get("F")-result_impl.opt.get("F")}') print(f'At X = {result_expl.opt.get("X")}') ``` -------------------------------- ### Configure and run SEGOMOEInterface optimization loop Source: https://sbarchopt.readthedocs.io/en/stable/algo/segomoe Use the SEGOMOEInterface to run a Bayesian optimization with Mixture of Experts. Requires a results folder for storage and a problem subclass of ArchOptProblemBase. Set use_moe=True to automatically identify clusters with different surrogates, which increases accuracy but also cost. ```python from sb_arch_opt.algo.segomoe_interface import SEGOMOEInterface problem = ... # Subclass of ArchOptProblemBase # Define folder to store results in results_folder = ... # Use Mixture of Experts: automatically identifies clusters in the design space # with different best surrogates ("experts"). Can be more accurate, however # also greatly increases the cost of finding new infill points. use_moe = True # Options passed to the Sego class and to model generation, respectively sego_options = {} model_options = {} # Get the interface (will be initialized if the results folder has results) interface = SEGOMOEInterface(problem, results_folder, n_init=100, n_infill=50, use_moe=use_moe, sego_options=sego_options, model_options=model_options) # Initialize from other results if you want interface.initialize_from_previous('path/to/other/results_folder') # Run the optimization loop incl DOE interface.run_optimization() x = interface.x # (n, nx) x_failed = interface.x_failed # (n_failed, nx) f = interface.f # (n, nf) g = interface.g # (n, ng) pop = interface.pop # Population containing all design points opt = interface.opt # Population containing optimal point(s) ``` -------------------------------- ### Use get_botorch_interface to run Bayesian optimization Source: https://sbarchopt.readthedocs.io/en/stable/algo/botorch Create an interface for a problem, run an optimization loop with 100 initial and 50 infill points, and extract results as a pymoo Population. ```python from sb_arch_opt.algo.botorch_interface import get_botorch_interface problem = ... # Subclass of ArchOptProblemBase # Get the interface and optimization loop interface = get_botorch_interface(problem) opt_loop = interface.get_optimization_loop(n_init=100, n_infill=50, seed=42) # Run the optimization loop until completion opt_loop.full_run() # Extract data as a pymoo Population object pop = interface.get_population(opt_loop) ``` -------------------------------- ### provision_pymoo(algorithm, set_init=True, results_folder=None) Source: https://sbarchopt.readthedocs.io/en/stable/api/pymoo Provisions a pymoo Algorithm to work correctly for architecture optimization: sets initializer, repair operator, optionally stores results, and replaces NaN outputs with Inf. ```APIDOC ## provision_pymoo(algorithm: Algorithm, set_init=True, results_folder=None) ### Description Provisions a pymoo Algorithm to work correctly for architecture optimization: - Sets initializer using a repaired sampler (if set_init = True) - Sets a repair operator - Optionally stores intermediate and final results in some results folder - Replace NaN outputs with Inf ### Parameters - **algorithm** (Algorithm) - Required - The algorithm to provision. - **set_init** (bool) - Optional - Whether to set the initializer. - **results_folder** (optional) - Folder to store results. ### Returns - None ``` -------------------------------- ### Create Conda Environment Source: https://sbarchopt.readthedocs.io/en/stable Initialize a new Conda environment named 'opt' with Python 3.12. ```bash conda create --name opt python=3.12 conda activate opt ``` -------------------------------- ### Run DoE algorithm and plot results Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Creates a temporary directory for results, runs the DoE algorithm, and plots the sampled population against the known Pareto front. ```python from sb_arch_opt.algo.pymoo_interface import get_doe_algo # Create a new results folder td.cleanup() td = tempfile.TemporaryDirectory() results_folder = td.name # Create and run the DoE algorithm doe_algo = get_doe_algo(doe_size=200, results_folder=results_folder) result = minimize(problem, doe_algo, seed=42) plot(problem.pareto_front(), result.pop.get('F'), labels=['Known Pareto front', 'Sampled population']) ``` -------------------------------- ### Run optimization with get_smarty_optimizer Source: https://sbarchopt.readthedocs.io/en/stable/algo/smarty Use the get_smarty_optimizer function to initialize the optimization interface with a problem instance and run the optimization loop. The resulting data can be extracted as a pymoo Population object. ```python from sb_arch_opt.algo.smarty_interface import get_smarty_optimizer problem = ... # Subclass of ArchOptProblemBase # Get the interface and optimization loop smarty = get_smarty_optimizer(problem, n_init=100, n_infill=50) # Run the optimization loop smarty.optimize() # Extract data as a pymoo Population object pop = smarty.pop ``` -------------------------------- ### Optimize JenattonImplicit Problem Source: https://sbarchopt.readthedocs.io/en/stable/tutorial Runs the optimization using the NSGA2 algorithm and prints the resulting optimum and design vector. ```python result_impl = minimize(JenattonImplicit(), get_nsga2(pop_size=50), termination=('n_gen', 20), seed=42) print(f'Optimum: {result_impl.opt.get("F")}') print(f'At X = {result_impl.opt.get("X")}') ``` -------------------------------- ### Increasing DOE size after a stored run Source: https://sbarchopt.readthedocs.io/en/stable/algo/pymoo Shows how to initialize a DOE algorithm from previous results and update the DOE size. ```python from sb_arch_opt.algo.pymoo_interface import get_doe_algo, \ initialize_from_previous_results problem = ... # Subclass of ArchOptProblemBase results_folder_path = 'path/to/results/folder' doe_algo = get_doe_algo(doe_size=200, results_folder=results_folder_path) # Initializing from previous results ignores the previously-set DOE size initialize_from_previous_results(doe_algo, problem, results_folder_path) doe_algo.set_doe_size(problem, doe_size=200) doe_algo.setup(problem, seed=42) # Remove seed argument when using in production! doe_algo.run() # Evaluate the sampled points pop = doe_algo.pop ``` -------------------------------- ### AxInterface(problem) Source: https://sbarchopt.readthedocs.io/en/stable/api/botorch Class handling interfacing between ArchOptProblemBase and the Ax optimization loop. ```APIDOC ## AxInterface(problem) ### Description Class handling interfacing between ArchOptProblemBase and the Ax optimization loop, based on: https://ax.dev/tutorials/gpei_hartmann_developer.html ### Method Class ### Signature `sb_arch_opt.algo.botorch_interface.algo.AxInterface(problem: ArchOptProblemBase)` ### Parameters - **problem** (ArchOptProblemBase) - Required - The optimization problem to interface with. ``` -------------------------------- ### SEGOMOEInterface.run_optimization Source: https://sbarchopt.readthedocs.io/en/stable/api/segomoe Method to run the optimization process. ```APIDOC ## SEGOMOEInterface.run_optimization ### Description Runs the optimization process. ### Method `run_optimization()` ```