NSGA-II c-factor optimiser

NSGA-II multi-objective Pareto optimisation of per-element c-factors.

Replaces the exhaustive ND grid scan (HiFiWorkflow.scan_cfactor_grid) as the default multi-element c-optimisation path. The grid scan remains practical for N_el ≤ 2.

Public API

HiFiCFactorProblem — batch pymoo Problem evaluating scan-axis vectors optimize_c_factors_nsga2 — run NSGA-II, return result + history + HV trace fidelity_envelope — maximum fidelity at each subset size extract_pareto_front — post-process result into DataFrame + auto-pick point plot_nsga2_results — produce NSGA-II diagnostic plots

class atom_hifi.training.optimizer.HiFiCFactorProblem(*args, **kwargs)[source]

Bases: Problem

Batch pymoo Problem wrapping _fit_cfactor_worker with joblib parallelism.

Evaluates each generation’s points that miss the cross-generation cache (count-kind backends also skip in-batch duplicates) serially (n_jobs == 1) or in one joblib.Parallel call; workers get a symbols-only library when n_jobs > 1. Descriptors and PCA embeddings come from SharedMemory when optimize_c_factors_nsga2 runs with its own n_jobs > 1 (the pattern of HiFiWorkflow._scan_cfactor).

Objectives (both minimised):

F[0] = -L_min (maximise likeness) F[1] = R (minimise redundancy)

Parameters:
  • species_order (List[str])

  • xl (Sequence[float])

  • xu (Sequence[float])

  • evaluator_kwargs (dict)

  • n_jobs (int)

canonical_key(x)[source]

Canonical cache key for a scan-axis vector x.

Count-kind: the realized k-vector (round(f·k_micro) per element, same conversion the worker performs internally) — many f-vectors map to one backend configuration. Distance-kind: round-to-4dp f-vector (legacy).

atom_hifi.training.optimizer.optimize_c_factors_nsga2(problem, n_gen=50, pop_size=40, seed=42, c_star_1d=None, c_vec_2d_best=None, n_jobs=1)[source]

Run NSGA-II on problem and return results.

Parameters:
  • problem (HiFiCFactorProblem)

  • n_gen (NSGA-II budget parameters.) – Rule of thumb: pop_size ≥ 10 × N_focus_elements (min 40). Watch pareto_convergence.png — increase n_gen if HV hasn’t plateaued.

  • pop_size (NSGA-II budget parameters.) – Rule of thumb: pop_size ≥ 10 × N_focus_elements (min 40). Watch pareto_convergence.png — increase n_gen if HV hasn’t plateaued.

  • seed (NSGA-II budget parameters.) – Rule of thumb: pop_size ≥ 10 × N_focus_elements (min 40). Watch pareto_convergence.png — increase n_gen if HV hasn’t plateaued.

  • c_star_1d (float or None) – Common 1-D c* from the 1-D scan; seeds the initial population.

  • c_vec_2d_best (array-like or None) – Best c-vector from a prior 2-D grid scan (if available).

  • n_jobs (int) – When > 1, descriptors and their PCA embeddings are copied to SharedMemory once for the whole run and the problem’s direct descriptor references are dropped before minimisation. Evaluation parallelism is problem.n_jobs. On every path the direct descriptor references are dropped after minimisation completes.

Returns:

res — pymoo Result object (.X, .F on the Pareto front) history — the problem’s list of result dicts, one per worker call that returned a row (cross-generation cache hits and count-kind in-batch duplicates are not re-evaluated; failed workers add none) hv_history — list of hypervolume values per generation

Return type:

(res, history, hv_history)

atom_hifi.training.optimizer.fidelity_envelope(df_pareto, x_col='n_structs_S')[source]

Upper envelope of fidelity F over x_col (default: |S|).

Groups by x_col, keeps max-F row per group, returns sorted ascending. Rows with non-finite F are dropped; returns empty DataFrame if none remain.

Parameters:
  • df_pareto (DataFrame)

  • x_col (str)

Return type:

DataFrame

atom_hifi.training.optimizer.extract_pareto_front(res, history, species_order, eps_noise_per_el, l_tol=0.9, save_dir=None, pareto_filename='pareto_front.csv', history_filename='pareto_history.csv', *, key_fn=None, granularity_kind='distance')[source]

Build Pareto front DataFrame and auto-pick operating point.

Returns:

df_pareto — NSGA-II front points (non-dominated in objective space

(-L_min, R)), sorted by R ascending.

best_c_per_el — {el: c_factor} dict for the auto-picked point;

pass directly to HiFiWorkflow.plot_final_fit(delta_pick=…)

Return type:

(df_pareto, best_c_per_el)

Parameters:
  • history (list)

  • species_order (List[str])

  • eps_noise_per_el (dict)

  • l_tol (float)

  • pareto_filename (str)

  • history_filename (str)

  • granularity_kind (str)

atom_hifi.training.optimizer.plot_nsga2_results(df_pareto, history, hv_history, species_order, best_c_per_el, l_tol=0.9, save_dir=None)[source]

Produce NSGA-II diagnostic plots and save to save_dir.

Parameters: