From b73be1c443114a54f57076ef6430efcd91466068 Mon Sep 17 00:00:00 2001 From: Jasper Bussemaker Date: Wed, 18 Feb 2026 06:43:07 +0100 Subject: [PATCH] Do not calculate HV for single-dimension problems --- sb_arch_opt/algo/pymoo_interface/metrics.py | 8 +++++++- sb_arch_opt/tests/algo/test_pymoo.py | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/sb_arch_opt/algo/pymoo_interface/metrics.py b/sb_arch_opt/algo/pymoo_interface/metrics.py index 85ead32..d161075 100644 --- a/sb_arch_opt/algo/pymoo_interface/metrics.py +++ b/sb_arch_opt/algo/pymoo_interface/metrics.py @@ -123,7 +123,7 @@ def do(self, f, *args, **kwargs): if f.ndim == 1: f = f[None, :] - if len(f) <= 1: + if f.shape[1] == 0: return 0. if self.ref_point is None: @@ -138,6 +138,12 @@ def do(self, f, *args, **kwargs): self.normalization = ZeroToOneNormalization(ideal, nadir) self.ref_point = self.normalization.forward(nadir) + if f.shape[1] == 1: + # Calculate HV here due to bug in moocore: https://github.com/multi-objective/moocore/issues/58 + f = self.normalization.forward(f) + hv = self.ref_point[0] - np.min(f) + return hv if hv >= 0. else 0. + return super().do(f, *args, **kwargs) diff --git a/sb_arch_opt/tests/algo/test_pymoo.py b/sb_arch_opt/tests/algo/test_pymoo.py index 2802c57..9c8e825 100644 --- a/sb_arch_opt/tests/algo/test_pymoo.py +++ b/sb_arch_opt/tests/algo/test_pymoo.py @@ -7,6 +7,7 @@ from typing import Optional from sb_arch_opt.problem import * from sb_arch_opt.sampling import * +from sb_arch_opt.problems.discrete import MDBranin from sb_arch_opt.algo.pymoo_interface import * from sb_arch_opt.algo.pymoo_interface.random_search import RandomSearchAlgorithm @@ -33,6 +34,16 @@ def test_nsga2(problem: ArchOptProblemBase): assert np.all(pop.get('X') == x_imp) +def test_nsga2_so(): + problem = MDBranin() + nsga2 = get_nsga2(pop_size=100) + result = minimize(problem, nsga2, termination=('n_gen', 10), verbose=True, progress=True) + pop = result.pop + + x_imp, _ = problem.correct_x(pop.get('X')) + assert np.all(pop.get('X') == x_imp) + + def test_termination(problem: ArchOptProblemBase): nsga2 = get_nsga2(pop_size=100) assert minimize(problem, nsga2, get_default_termination(problem, tol=1e-4), verbose=True, progress=True)