openswmm_gymnasium.scoring#

openswmm_gymnasium.scoring#

Multi-objective optimisation scoring utilities. Plan §5.3.

All functions operate on numpy arrays of shape (n_points, n_objectives) in B{minimisation} convention (smaller is better). The env’s reward composer is responsible for the sign-flipping bookkeeping at the boundary (plan §0 #5); functions here always treat the input as costs.

author:

Caleb Buahin

copyright:

Copyright (c) 2026 Caleb Buahin

license:

MIT

openswmm_gymnasium.scoring.epsilon_indicator(front_a, front_b)[source]#

Additive ε-indicator I_ε+(A, B).

Smallest ε such that for every B{b ∈ B} there exists B{a ∈ A} with a_d - ε <= b_d for every dimension d. Equivalently ε = max_b min_a max_d (a_d - b_d).

Parameters:
  • front_a (array_like) – 2-D array (n, d) — typically the approximation.

  • front_b (array_like) – 2-D array (m, d) — typically the reference front.

Returns:

The ε value, or inf if either input is empty.

Return type:

float

openswmm_gymnasium.scoring.hypervolume(points, reference, *, method='auto', mc_samples=100000, rng=None)[source]#

Hypervolume dominated by points w.r.t. reference.

For d <= 2 an exact closed-form is used (sweep). For d >= 3 Monte-Carlo is used. Setting method="mc" forces Monte-Carlo even in low dimensions (useful for cross-checking).

Parameters:
  • points (array_like) – 2-D array of shape (n, d) in minimisation convention.

  • reference (array_like) – 1-D array of length d giving the worst-case (nadir) reference point. Points not strictly dominating reference contribute nothing.

  • method (str) – "auto", "exact" (only valid for d <= 2), or "mc".

  • mc_samples (int) – Number of Monte-Carlo samples when method is "mc" or auto-dispatched for d >= 3.

  • rng (numpy.random.Generator or None) – Optional pre-seeded generator for reproducible MC.

Returns:

Hypervolume value, 0.0 for empty / fully dominated inputs.

Return type:

float

Raises:

ValueError – If method is unknown or "exact" is requested for d > 2.

openswmm_gymnasium.scoring.igd(approximation, reference_front)[source]#

Inverted Generational Distance.

For each point in reference_front, compute the Euclidean distance to the closest point in approximation; IGD is the mean of those distances. Lower is better.

Parameters:
  • approximation (array_like) – 2-D array, shape (n, d).

  • reference_front (array_like) – 2-D array, shape (m, d).

Returns:

Mean nearest-neighbour distance, or inf if either input is empty.

Return type:

float

openswmm_gymnasium.scoring.igd_plus(approximation, reference_front)[source]#

IGD+ — distance is computed only along dominated dimensions.

For minimisation, the IGD+ distance from reference point r to approximation point a replaces (a - r) with max(0, a - r) before computing the Euclidean norm. The result is zero whenever a weakly dominates r, which makes IGD+ Pareto-compliant in a way standard IGD is not.

Return type:

float

Parameters:
  • approximation (ArrayLike)

  • reference_front (ArrayLike)

openswmm_gymnasium.scoring.is_dominated(point, others)[source]#

Return whether point is dominated by at least one row of others.

For minimisation: row j dominates point iff j[d] <= point[d] for every dimension d and j[d] < point[d] for at least one d.

Parameters:
  • point (array_like) – 1-D array of length d.

  • others (array_like) – 2-D array of shape (n, d).

Returns:

True if some row of others strictly dominates point.

Return type:

bool

openswmm_gymnasium.scoring.normalize(points, ideal, reference)[source]#

Return (points - ideal) / (reference - ideal).

Parameters:
  • points (array_like) – Array of shape (d,) or (n, d).

  • ideal (array_like) – 1-D array of length d giving the per-dimension best-possible value (lower in minimisation).

  • reference (array_like) – 1-D array of length d giving the per-dimension worst-case (nadir) value used as the hypervolume reference.

Returns:

Same shape as points, values typically in [0, 1] but B{not clipped} — callers do their own clipping if required.

Return type:

numpy.ndarray

Raises:

ValueError – If reference[d] <= ideal[d] for any d.

openswmm_gymnasium.scoring.normalized_hypervolume(points, ideal, reference, *, method='auto', mc_samples=100000, rng=None)[source]#

Hypervolume in normalised [0, 1]^d space.

Normalises points via normalize so the reference becomes (1, ..., 1) and the ideal becomes (0, ..., 0); the returned value is therefore in [0, 1] regardless of the original objective scales.

Return type:

float

Parameters:
  • points (ArrayLike)

  • ideal (ArrayLike)

  • reference (ArrayLike)

  • method (str)

  • mc_samples (int)

  • rng (Generator | None)

openswmm_gymnasium.scoring.pareto_front(points)[source]#

Return the non-dominated subset of points (minimisation).

Parameters:

points (array_like) – 2-D array of shape (n, d).

Returns:

Subset of rows of points that are non-dominated, in the original ordering.

Return type:

numpy.ndarray

openswmm_gymnasium.scoring.r2_indicator(front, weights, reference)[source]#

R2 indicator over a set of weight vectors.

For each weight vector w, compute the minimum over the front of the weighted-Tchebycheff utility max_d w_d * |p_d - reference_d|; the R2 indicator is the mean of those minima over all weight vectors. Lower is better.

Parameters:
  • front (array_like) – 2-D array (n, d).

  • weights (array_like) – 2-D array (k, d) of weight vectors.

  • reference (array_like) – 1-D array (d,) of the utopia / ideal point.

Returns:

Mean weighted-Tchebycheff utility.

Return type:

float

openswmm_gymnasium.scoring.spread(front)[source]#

Standard deviation of nearest-neighbour Euclidean distances.

For a front with fewer than two points, returns 0.0.

Parameters:

front (array_like) – 2-D array (n, d).

Returns:

Stddev of per-point nearest-neighbour distances. Lower means more uniform spacing.

Return type:

float