Modules and Architecture (Key Parts)
This page gives a curated overview of Optienv internals to help you extend and maintain the codebase.
High‑level architecture
+------------------------------+
| CLI (Typer) |
| search | front | hv | ver |
+------------------------------+
|
v
+------------------------------+ +----------------------------+
| Algorithms (ask / tell) |<------>| utils.pareto |
| NSGA2 | NSGA3 | | - nondominated_mask |
+------------------------------+ | - epsilon_archive |
| +----------------------------+
v
+------------------------------+
| Evaluation Pipeline |
| - CSV adapter |
| - Lean workers (subprocs) |
+------------------------------+
Core packages
optienv.cli.app (CLI entry points)
Implements the commands documented in Command Line Interface.
Spawns a pool of workers (processes or threads) to evaluate candidates.
Writes the single‑file per‑seed history and optional CSVs.
Manages checkpoint save/load and resume semantics.
For analysis: -
frontcomputes the global non‑dominated set (optionally ε‑thinned). -hypervolumecomputes normalized HV (wide format).
optienv.core.adapters.csv_wrapper (CSV model adapter)
Wrapper contract
Optienv writes
variable_values.csvin a working copy of your model.Your wrapper must define:
def search_and_apply_variables(model_folder: str) -> None: ...
Your wrapper must write
objective_values.csvwith two columns:Name,Value.The adapter flips sign for objectives declared as maximize to ensure a pure minimization view inside the algorithms.
Working copies & cleanup
Each evaluation runs in a fresh working copy, then the directory is deleted (unless
--keep-work-on-error).The adapter uses robust deletion with retries (Windows‑friendly).
optienv.algos.nsga2 (NSGA‑II)
NSGA2(population_size, seed=None)exposesinitialize(n_var, bounds)and the GA loop viaask(pop, fit, bounds)→tell(pop, fit, children, fit_children).Survival: - Combine parents and offspring → fast non‑dominated sort - Fill full fronts; on the splitting front, keep the largest crowding distance points
Variation: SBX crossover (+ polynomial mutation)
Recommended when M ≤ 3 or as a strong baseline for most problems.
Implementation notes:
Ensure the splitting front is truncated (never exceed
population_size).Keep an invariant check during development:
assert survivors.shape[0] == population_size
optienv.algos.nsga3 (NSGA‑III)
Many‑objective extension of NSGA‑II, replacing crowding with reference‑direction niching.
Reference directions - Generated via Das–Dennis (
--ref-parts) or loaded from CSV (--ref-dirs-csv)Survival - Combine parents & offspring → non‑dominated sort - Truncate the splitting front with niching:
fill under‑represented directions first, choose the smallest perpendicular distance
Works well when M ≥ 4.
Implementation notes:
The niching selector must return at most
kindices when truncating.Normalize objective values before association (min‑max normalization suffices in practice for robustness).
optienv.utils.pareto
nondominated_mask(F): boolean mask of non‑dominated rows for a minimization arrayepsilon_archive(F, eps): ε‑box thinning (useful for density control in fronts/HV)Used by both CLI analysis commands and, optionally, in algorithm prototypes.
Checkpoints & resume
Checkpoints are single‑file
.npzwith: population, fitness, RNG state, variable/objective names, bounds, history path, model_dir, and last generation index.On resume, RNG state and arrays are restored and evaluation continues seamlessly from the saved generation.