Python-based Optimization¶
This notebook demonstrates how to execute a System Architecture Optimization (SAO) problem once the design space has been modeled and the evaluation code has been implemented and connected to.
To run optimization locally, make sure you have installed the optimization dependencies:
pip install adore-<version>.whl[opt]
The example that we will be using here is the Guidance, Navigation & Control (GNC) problem. Refer to the Evaluation Interfaces introduction for more details about this problem.
# Load the example model: the GNC problem
import adore as ad
from gnc import GNCCalculator
from gnc_evaluation_api import GNCEvaluator
def get_gnc_evaluator():
return GNCEvaluator.from_file(
'../assets/gnc.adore', save_to_project=True)
evaluator = get_gnc_evaluator()
with ad.pretty_printing_context(evaluator.project):
print(evaluator.design_problem)
DesignProblem "Design Problem #1" (id=160)
encoder: complete
design_vars [n=33]:
- DiscreteDesignVar (id=161)
decision_id: Decision(DecisionType.OPTION; id=57)
options: ['1 time', '2 times', '3 times']
- DiscreteDesignVar (id=162)
decision_id: Decision(DecisionType.OPTION; id=40)
options: ['1 time', '2 times', '3 times']
- DiscreteDesignVar (id=163)
decision_id: Decision(DecisionType.OPTION; id=26)
options: ['1 time', '2 times', '3 times']
- DiscreteDesignVar (id=164) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=58)
options: ['0', '1']
- DiscreteDesignVar (id=165) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=58)
options: ['0', '1']
- DiscreteDesignVar (id=166) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=58)
options: ['0', '1']
- DiscreteDesignVar (id=167) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=58)
options: ['0', '1']
- DiscreteDesignVar (id=168) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=47)
options: ['0', '1']
- DiscreteDesignVar (id=169) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=47)
options: ['0', '1']
- DiscreteDesignVar (id=170) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=47)
options: ['0', '1']
- DiscreteDesignVar (id=171) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=47)
options: ['0', '1']
- DiscreteDesignVar (id=172) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=39)
options: ['0', '1']
- DiscreteDesignVar (id=173) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=39)
options: ['0', '1']
- DiscreteDesignVar (id=174) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=39)
options: ['0', '1']
- DiscreteDesignVar (id=175) @ comp 0
decision_id: Decision(DecisionType.PERMUTATION; id=39)
options: ['0', '1']
- DiscreteDesignVar (id=176)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=177)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=178)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=179)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=180)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=181)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=182)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=183)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=184)
decision_id: Decision(DecisionType.PERMUTATION; id=65)
options: ['0', '1']
- DiscreteDesignVar (id=185)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
- DiscreteDesignVar (id=186)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
- DiscreteDesignVar (id=187)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
- DiscreteDesignVar (id=188)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
- DiscreteDesignVar (id=189)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
- DiscreteDesignVar (id=190)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
- DiscreteDesignVar (id=191)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
- DiscreteDesignVar (id=192)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
- DiscreteDesignVar (id=193)
decision_id: Decision(DecisionType.PERMUTATION; id=66)
options: ['0', '1']
objectives:
- Objective (id=194)
qoi_id: Qoi(Failure Rate; id=49)
maximize: False
- Objective (id=195)
qoi_id: Qoi(Mass; id=48)
maximize: False
from pymoo.optimize import minimize
from sb_arch_opt.algo.pymoo_interface import get_nsga2
# Load the evaluator
evaluator = get_gnc_evaluator()
# Get the SBArchOpt problem definition
problem = evaluator.get_arch_opt_problem()
# Get and configure the NSGA-II algorithm
algorithm = get_nsga2(pop_size=50)
# Run the optimization: 10 generations (10 x 50 = 500 evaluations)
result = minimize(problem, algorithm, termination=('n_gen', 10), verbose=True)
# Plot the results
GNCCalculator.plot_results(evaluator.get_results(), 'NSGA-II')
from IPython.display import display
# display(evaluator.get_results()) # Render pandas DataFrame
# # Outside a notebook, it is more convenient to use something like:
# evaluator.to_file('results.adore')
# evaluator.save_results_csv('results.csv')
==========================================================================================================================
n_gen | n_eval | n_nds | eps | indicator | hv_est | not_failed | feasible | optimal
==========================================================================================================================
1 | 50 | 7 | - | - | 0.3873979679 | 50 (100.0%) | 50 (100.0%) | 7 (14.0%)
2 | 100 | 10 | 0.0484462571 | ideal | 0.4417961128 | 50 (100.0%) | 50 (100.0%) | 10 (20.0%)
3 | 150 | 12 | 0.0213435131 | f | 0.4515782013 | 50 (100.0%) | 50 (100.0%) | 12 (24.0%)
4 | 200 | 11 | 0.0084794928 | ideal | 0.4539274309 | 50 (100.0%) | 50 (100.0%) | 11 (22.0%)
5 | 250 | 14 | 0.0114989200 | f | 0.4645516638 | 50 (100.0%) | 50 (100.0%) | 14 (28.0%)
6 | 300 | 13 | 0.0184963305 | ideal | 0.4746165561 | 50 (100.0%) | 50 (100.0%) | 13 (26.0%)
7 | 350 | 14 | 0.0500000000 | ideal | 0.4780658648 | 50 (100.0%) | 50 (100.0%) | 14 (28.0%)
8 | 400 | 14 | 0.0040735748 | f | 0.4845463148 | 50 (100.0%) | 50 (100.0%) | 14 (28.0%)
9 | 450 | 18 | 0.0243902439 | nadir | 0.4845471383 | 50 (100.0%) | 50 (100.0%) | 18 (36.0%)
10 | 500 | 19 | 0.0033324468 | f | 0.4855027399 | 50 (100.0%) | 50 (100.0%) | 19 (38.0%)
ArchSBO¶
Below code shows how to execute the optimization problem using the Surrogate-Based Optimization (SBO) algorithm, which uses machine learning to reduce the number of function evaluations.
You can observe that it achieves practically the same results as NSGA-II, however with only 10% of the evaluations.
from pymoo.optimize import minimize
from sb_arch_opt.algo.arch_sbo import get_arch_sbo_gp
# Load the evaluator
evaluator = get_gnc_evaluator()
# Get the SBArchOpt problem definition
problem = evaluator.get_arch_opt_problem()
# Get and configure the ArchSBO algorithm
n_init = 20
n_infill = 30
algorithm = get_arch_sbo_gp(problem, init_size=n_init, n_parallel=4, kpls_n_dim=10)
# Run the optimization: 20 init + 30 infill = 50 evaluations
result = minimize(problem, algorithm, termination=('n_eval', n_init+n_infill),
verbose=True)
# Plot the results
GNCCalculator.plot_results(evaluator.get_results(), 'ArchSBO')
from IPython.display import display
display(evaluator.get_results()) # Render pandas DataFrame
# # Outside a notebook, it is more convenient to use something like:
# evaluator.to_file('results.adore')
# evaluator.save_results_csv('results.csv')
==========================================================================================================================
n_gen | n_eval | n_nds | eps | indicator | hv_est | not_failed | feasible | optimal
==========================================================================================================================
1 | 20 | 6 | - | - | 0.4626955684 | 20 (100.0%) | 20 (100.0%) | 6 (30.0%)
fmin_cobyla failed but the best value is retained
fmin_cobyla failed but the best value is retained
INFO 2026-01-27 13:04:51,794 sb_arch_opt.sbo : Surrogate infill gen 10 @ 1000 points evaluated (20 real unique, 20 eval) INFO 2026-01-27 13:04:54,824 sb_arch_opt.sbo : Surrogate infill gen 20 @ 2000 points evaluated (20 real unique, 20 eval) INFO 2026-01-27 13:04:55,831 sb_arch_opt.sbo : Infill: 4 new (eval 20 real unique, 20 eval)
2 | 24 | 6 | 0.4112689716 | ideal | 1.0635294828 | 24 (100.0%) | 24 (100.0%) | 6 (25.0%) fmin_cobyla failed but the best value is retained fmin_cobyla failed but the best value is retained
INFO 2026-01-27 13:04:59,201 sb_arch_opt.sbo : Surrogate infill gen 10 @ 1000 points evaluated (24 real unique, 24 eval) INFO 2026-01-27 13:05:02,219 sb_arch_opt.sbo : Surrogate infill gen 20 @ 2000 points evaluated (24 real unique, 24 eval) INFO 2026-01-27 13:05:05,165 sb_arch_opt.sbo : Surrogate infill gen 30 @ 3000 points evaluated (24 real unique, 24 eval) INFO 2026-01-27 13:05:05,911 sb_arch_opt.sbo : Infill: 4 new (eval 24 real unique, 24 eval)
3 | 28 | 7 | 0.0098279612 | ideal | 1.0635294828 | 28 (100.0%) | 28 (100.0%) | 7 (25.0%) fmin_cobyla failed but the best value is retained fmin_cobyla failed but the best value is retained
INFO 2026-01-27 13:05:09,772 sb_arch_opt.sbo : Surrogate infill gen 10 @ 1000 points evaluated (28 real unique, 28 eval) INFO 2026-01-27 13:05:12,283 sb_arch_opt.sbo : Infill: 4 new (eval 28 real unique, 28 eval)
4 | 32 | 7 | 0.0528999751 | ideal | 1.0996169111 | 32 (100.0%) | 32 (100.0%) | 7 (21.9%) fmin_cobyla failed but the best value is retained fmin_cobyla failed but the best value is retained
INFO 2026-01-27 13:05:15,685 sb_arch_opt.sbo : Surrogate infill gen 10 @ 1000 points evaluated (32 real unique, 32 eval) INFO 2026-01-27 13:05:18,449 sb_arch_opt.sbo : Surrogate infill gen 20 @ 2000 points evaluated (32 real unique, 32 eval) INFO 2026-01-27 13:05:22,089 sb_arch_opt.sbo : Surrogate infill gen 30 @ 3000 points evaluated (32 real unique, 32 eval) INFO 2026-01-27 13:05:24,133 sb_arch_opt.sbo : Infill: 4 new (eval 32 real unique, 32 eval)
5 | 36 | 9 | 0.0051622904 | ideal | 1.1827652404 | 36 (100.0%) | 36 (100.0%) | 9 (25.0%) fmin_cobyla failed but the best value is retained fmin_cobyla failed but the best value is retained
INFO 2026-01-27 13:05:27,863 sb_arch_opt.sbo : Surrogate infill gen 10 @ 1000 points evaluated (36 real unique, 36 eval) INFO 2026-01-27 13:05:31,279 sb_arch_opt.sbo : Surrogate infill gen 20 @ 2000 points evaluated (36 real unique, 36 eval) INFO 2026-01-27 13:05:34,733 sb_arch_opt.sbo : Surrogate infill gen 30 @ 3000 points evaluated (36 real unique, 36 eval) INFO 2026-01-27 13:05:35,165 sb_arch_opt.sbo : Infill: 4 new (eval 36 real unique, 36 eval)
6 | 40 | 10 | 0.1276595745 | ideal | 1.1827652404 | 40 (100.0%) | 40 (100.0%) | 10 (25.0%) fmin_cobyla failed but the best value is retained fmin_cobyla failed but the best value is retained
INFO 2026-01-27 13:05:38,765 sb_arch_opt.sbo : Surrogate infill gen 10 @ 1000 points evaluated (40 real unique, 40 eval) INFO 2026-01-27 13:05:42,207 sb_arch_opt.sbo : Surrogate infill gen 20 @ 2000 points evaluated (40 real unique, 40 eval) INFO 2026-01-27 13:05:45,413 sb_arch_opt.sbo : Infill: 4 new (eval 40 real unique, 40 eval)
7 | 44 | 11 | 0.0129994340 | ideal | 1.3404455684 | 44 (100.0%) | 44 (100.0%) | 11 (25.0%) fmin_cobyla failed but the best value is retained fmin_cobyla failed but the best value is retained
INFO 2026-01-27 13:05:49,130 sb_arch_opt.sbo : Surrogate infill gen 10 @ 1000 points evaluated (44 real unique, 44 eval) INFO 2026-01-27 13:05:52,543 sb_arch_opt.sbo : Surrogate infill gen 20 @ 2000 points evaluated (44 real unique, 44 eval) INFO 2026-01-27 13:05:53,712 sb_arch_opt.sbo : Infill: 4 new (eval 44 real unique, 44 eval)
8 | 48 | 11 | 0.000000E+00 | f | 1.3404455684 | 48 (100.0%) | 48 (100.0%) | 11 (22.9%) fmin_cobyla failed but the best value is retained fmin_cobyla failed but the best value is retained
INFO 2026-01-27 13:05:57,471 sb_arch_opt.sbo : Surrogate infill gen 10 @ 1000 points evaluated (48 real unique, 48 eval) INFO 2026-01-27 13:06:00,849 sb_arch_opt.sbo : Surrogate infill gen 20 @ 2000 points evaluated (48 real unique, 48 eval) INFO 2026-01-27 13:06:01,986 sb_arch_opt.sbo : Infill: 4 new (eval 48 real unique, 48 eval)
9 | 52 | 11 | 0.0024741806 | f | 1.3525803241 | 52 (100.0%) | 52 (100.0%) | 11 (21.2%)
| id | name | evaluated | perfFeasible | inParetoFront | DV_161_Instantiate Component Actuator | DV_161_Instantiate Component Actuator_active | DV_162_Instantiate Component Computer | DV_162_Instantiate Component Computer_active | DV_163_Instantiate Component Sensor | ... | PORT_61_Command | ATTR_27_Type_0 | ATTR_27_Type_1 | ATTR_27_Type_2 | ATTR_41_Type_0 | ATTR_41_Type_1 | ATTR_41_Type_2 | ATTR_53_Type_0 | ATTR_53_Type_1 | ATTR_53_Type_2 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 196 | Architecture #2 | True | True | False | 1 | True | 0 | True | 1 | ... | 1 | A | C | 0 | C | 0 | 0 | B | B | 0 |
| 2 | 262 | Architecture #3 | True | True | False | 1 | True | 2 | True | 0 | ... | 1 | C | 0 | 0 | A | A | A | B | B | 0 |
| 3 | 333 | Architecture #4 | True | True | False | 2 | True | 1 | True | 1 | ... | 1 | B | B | 0 | B | B | 0 | A | A | A |
| 4 | 406 | Architecture #5 | True | True | False | 0 | True | 2 | True | 1 | ... | 1 | A | B | 0 | A | C | C | C | 0 | 0 |
| 5 | 477 | Architecture #6 | True | True | False | 0 | True | 0 | True | 1 | ... | 1 | B | B | 0 | B | 0 | 0 | B | 0 | 0 |
| 6 | 540 | Architecture #7 | True | True | False | 2 | True | 1 | True | 1 | ... | 1 | A | A | 0 | A | C | 0 | A | A | C |
| 7 | 613 | Architecture #8 | True | True | True | 0 | True | 0 | True | 2 | ... | 1 | A | A | A | B | 0 | 0 | A | 0 | 0 |
| 8 | 679 | Architecture #9 | True | True | False | 2 | True | 1 | True | 2 | ... | 1 | A | A | A | A | A | 0 | C | C | C |
| 9 | 755 | Architecture #10 | True | True | False | 1 | True | 1 | True | 1 | ... | 1 | A | A | 0 | C | C | 0 | C | C | 0 |
| 10 | 825 | Architecture #11 | True | True | False | 2 | True | 1 | True | 0 | ... | 1 | A | 0 | 0 | B | B | 0 | A | B | C |
| 11 | 895 | Architecture #12 | True | True | False | 0 | True | 2 | True | 0 | ... | 1 | B | 0 | 0 | A | C | C | C | 0 | 0 |
| 12 | 963 | Architecture #13 | True | True | False | 1 | True | 0 | True | 2 | ... | 1 | A | A | B | A | 0 | 0 | A | A | 0 |
| 13 | 1032 | Architecture #14 | True | True | False | 2 | True | 0 | True | 2 | ... | 1 | B | B | C | B | 0 | 0 | A | A | B |
| 14 | 1104 | Architecture #15 | True | True | False | 1 | True | 1 | True | 2 | ... | 1 | A | A | C | B | C | 0 | C | C | 0 |
| 15 | 1177 | Architecture #16 | True | True | False | 1 | True | 1 | True | 2 | ... | 1 | B | B | B | A | A | 0 | B | C | 0 |
| 16 | 1250 | Architecture #17 | True | True | False | 0 | True | 0 | True | 0 | ... | 1 | C | 0 | 0 | B | 0 | 0 | A | 0 | 0 |
| 17 | 1310 | Architecture #18 | True | True | False | 1 | True | 2 | True | 1 | ... | 1 | A | B | 0 | A | A | B | B | B | 0 |
| 18 | 1384 | Architecture #19 | True | True | False | 2 | True | 2 | True | 1 | ... | 1 | A | C | 0 | A | B | C | A | A | B |
| 19 | 1461 | Architecture #20 | True | True | False | 1 | True | 0 | True | 0 | ... | 1 | B | 0 | 0 | B | 0 | 0 | A | A | 0 |
| 20 | 1524 | Architecture #21 | True | True | False | 0 | True | 2 | True | 0 | ... | 1 | A | 0 | 0 | A | A | A | C | 0 | 0 |
| 21 | 1592 | Architecture #22 | True | True | True | 0 | True | 1 | True | 2 | ... | 1 | A | A | A | A | A | 0 | A | 0 | 0 |
| 22 | 1662 | Architecture #23 | True | True | True | 1 | True | 1 | True | 1 | ... | 1 | A | A | 0 | A | A | 0 | A | A | 0 |
| 23 | 1732 | Architecture #24 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | A | A | A | A | A | C |
| 24 | 1812 | Architecture #25 | True | True | False | 0 | True | 2 | True | 2 | ... | 1 | A | B | B | A | A | A | A | 0 | 0 |
| 25 | 1886 | Architecture #26 | True | True | False | 2 | True | 2 | True | 0 | ... | 1 | B | 0 | 0 | A | A | C | A | A | C |
| 26 | 1960 | Architecture #27 | True | True | False | 2 | True | 2 | True | 1 | ... | 1 | A | A | 0 | A | A | C | A | A | C |
| 27 | 2037 | Architecture #28 | True | True | False | 1 | True | 2 | True | 2 | ... | 1 | B | C | C | A | C | C | A | A | 0 |
| 28 | 2114 | Architecture #29 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | C | B | B | B | B | B | B |
| 29 | 2194 | Architecture #30 | True | True | False | 1 | True | 1 | True | 1 | ... | 1 | A | A | 0 | A | A | 0 | B | C | 0 |
| 30 | 2264 | Architecture #31 | True | True | False | 1 | True | 1 | True | 2 | ... | 1 | A | A | A | A | A | 0 | B | C | 0 |
| 31 | 2337 | Architecture #32 | True | True | True | 2 | True | 2 | True | 2 | ... | 1 | A | B | B | B | B | C | A | A | B |
| 32 | 2417 | Architecture #33 | True | True | True | 2 | True | 2 | True | 2 | ... | 1 | A | B | B | A | A | A | A | A | A |
| 33 | 2497 | Architecture #34 | True | True | False | 1 | True | 2 | True | 2 | ... | 1 | A | B | C | A | A | A | A | A | 0 |
| 34 | 2574 | Architecture #35 | True | True | True | 1 | True | 2 | True | 2 | ... | 1 | A | A | A | A | A | A | A | A | 0 |
| 35 | 2651 | Architecture #36 | True | True | True | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | B | B | B | A | C | C |
| 36 | 2731 | Architecture #37 | True | True | True | 2 | True | 2 | True | 2 | ... | 1 | B | B | C | A | A | A | C | C | C |
| 37 | 2811 | Architecture #38 | True | True | True | 0 | True | 0 | True | 0 | ... | 1 | A | 0 | 0 | B | 0 | 0 | A | 0 | 0 |
| 38 | 2871 | Architecture #39 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | B | B | C | A | A | A |
| 39 | 2951 | Architecture #40 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | B | B | B | B | B | B | B |
| 40 | 3031 | Architecture #41 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | A | C | C | B | B | B |
| 41 | 3111 | Architecture #42 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | A | A | A | A | A | A |
| 42 | 3191 | Architecture #43 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | A | A | A | A | A | A |
| 43 | 3271 | Architecture #44 | True | True | False | 1 | True | 2 | True | 2 | ... | 1 | B | C | C | A | A | C | B | B | 0 |
| 44 | 3348 | Architecture #45 | True | True | True | 2 | True | 2 | True | 2 | ... | 1 | A | C | C | B | C | C | A | C | C |
| 45 | 3428 | Architecture #46 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | B | B | B | B | B | B | C |
| 46 | 3508 | Architecture #47 | True | True | False | 1 | True | 2 | True | 2 | ... | 1 | A | A | C | B | C | C | A | A | 0 |
| 47 | 3585 | Architecture #48 | True | True | False | 2 | True | 2 | True | 1 | ... | 1 | B | B | 0 | A | A | B | B | C | C |
| 48 | 3662 | Architecture #49 | True | True | False | 2 | True | 2 | True | 1 | ... | 1 | B | B | 0 | A | C | C | A | A | A |
| 49 | 3739 | Architecture #50 | True | True | True | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | A | A | A | A | A | A |
| 50 | 3819 | Architecture #51 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | A | A | A | B | B | C |
| 51 | 3899 | Architecture #52 | True | True | False | 2 | True | 2 | True | 2 | ... | 1 | A | A | A | A | A | A | B | B | C |
| 52 | 3979 | Architecture #53 | True | True | False | 2 | True | 2 | True | 1 | ... | 1 | B | B | 0 | B | B | B | C | C | C |
52 rows × 92 columns
Parallel Execution¶
The Problem class "translates" the ADORE design problem as provided by the evaluator to a format the SBArchOpt and pymoo understand.
The translation is done automatically and there's only one option: n_parallel.
This option can be used to support running evaluations in parallel when evaluation is executed locally in Python code.
Parallelization is achieved using a multiprocessing Pool.
Parallelization works best with algorithms that generate batches of designs to be evaluated, such as a Design of Experiments (DoE), NSGA-II or ArchSBO running with batch execution (use n_parallel when creating the ArchSBO algorithm).
from pymoo.optimize import minimize
from sb_arch_opt.algo.pymoo_interface import get_nsga2
evaluator = get_gnc_evaluator()
# Get the SBArchOpt problem definition
problem = evaluator.get_arch_opt_problem(n_parallel=8)
# Run the optimization
algorithm = get_nsga2(pop_size=20)
result = minimize(problem, algorithm, termination=('n_gen', 5), verbose=True)
GNCCalculator.plot_results(evaluator.get_results(), 'NSGA-II (parallel eval)')
==========================================================================================================================
n_gen | n_eval | n_nds | eps | indicator | hv_est | not_failed | feasible | optimal
==========================================================================================================================
1 | 20 | 4 | - | - | 0.3206449138 | 20 (100.0%) | 20 (100.0%) | 4 (20.0%)
2 | 40 | 6 | 0.6086956522 | nadir | 0.3543284460 | 20 (100.0%) | 20 (100.0%) | 6 (30.0%)
3 | 60 | 10 | 0.2004414580 | ideal | 0.3756766444 | 20 (100.0%) | 20 (100.0%) | 10 (50.0%)
4 | 80 | 10 | 0.0224432972 | f | 0.3798719559 | 20 (100.0%) | 20 (100.0%) | 10 (50.0%)
5 | 100 | 10 | 0.2203423093 | ideal | 0.3798719559 | 20 (100.0%) | 20 (100.0%) | 10 (50.0%)
Restart Capability¶
SBArchOpt supports restart by storing intermediate evaluation results.
from pymoo.optimize import minimize
from sb_arch_opt.algo.pymoo_interface import get_nsga2, get_doe_algo, \
load_from_previous_results, initialize_from_previous_results
# Create a temp dir to store results for this demonstration
import tempfile
with tempfile.TemporaryDirectory() as results_folder:
# Get the problem definition
evaluator = get_gnc_evaluator()
problem = evaluator.get_arch_opt_problem()
# First run a DoE of 100 points
doe = get_doe_algo(doe_size=100, results_folder=results_folder)
doe.setup(problem)
doe.run()
# Load intermediary results
pop = load_from_previous_results(problem, results_folder)
print('Population size (DoE):', len(pop))
# Run NSGA-II initialized from DoE results
nsga2 = get_nsga2(pop_size=20, results_folder=results_folder)
initialize_from_previous_results(nsga2, problem, results_folder)
result = minimize(problem, nsga2, termination=('n_gen', 5), verbose=True)
print('Population size (NSGA-II):', len(result.pop))
print('Number of unique architectures:', len(evaluator.get_results()))
GNCCalculator.plot_results(evaluator.get_results(), 'NSGA-II (restarted)')
INFO 2026-01-27 17:10:51,276 sb_arch_opt.pymoo : Merged additional design points from pymoo results: 100 design points INFO 2026-01-27 17:10:51,276 sb_arch_opt.pymoo : Evaluation status: 100 of 100 (100.0%) are already evaluated
Population size (DoE): 100
INFO 2026-01-27 17:10:51,491 sb_arch_opt.pymoo : Merged additional design points from pymoo results: 100 design points INFO 2026-01-27 17:10:51,491 sb_arch_opt.pymoo : Evaluation status: 100 of 100 (100.0%) are already evaluated
==========================================================================================================================
n_gen | n_eval | n_nds | eps | indicator | hv_est | not_failed | feasible | optimal
==========================================================================================================================
1 | 100 | 6 | - | - | 0.3623298505 | 100 (100.0%) | 100 (100.0%) | 6 (6.0%)
2 | 120 | 6 | 0.0088645490 | f | 0.3659289185 | 20 (100.0%) | 20 (100.0%) | 6 (30.0%)
3 | 140 | 7 | 0.0346989446 | ideal | 0.4045651886 | 20 (100.0%) | 20 (100.0%) | 7 (35.0%)
4 | 160 | 7 | 0.1250000000 | ideal | 0.4826300421 | 20 (100.0%) | 20 (100.0%) | 7 (35.0%)
5 | 180 | 7 | 0.0236236497 | ideal | 0.4844897340 | 20 (100.0%) | 20 (100.0%) | 7 (35.0%)
Population size (NSGA-II): 20
Number of unique architectures: 179
Inspecting Results in the GUI¶
After an optimization has finished, you can store the project as an ADORE file again. This time it will also contain all evaluated architectures, so you can inspect them in the GUI.
# Truncate architectures to reduce file size
evaluator.project.architectures = evaluator.project.architectures[:10]
# Save the ADORE file
evaluator.to_file('gnc_results.adore')
# Show the project in the Jupyter notebook
evaluator.show_project(
show_architecture_id=evaluator.project.architectures[-1].id,
externalize_js=True, # Set to False when viewing within an interactive notebook
)