Skip to content

Commit 9b54237

Browse files
committed
Integrate moocore hypervolume framework with backward compatibility
- Rename ApproximateMonteCarloHypervolume to ApproximateHypervolume for consistency - Update ExactHypervolume to use moocore's optimized exact calculations - Add commented moocore implementation in ApproximateHypervolume for easy switching - Maintain original Monte Carlo approximation as default for compatibility - Update SMS algorithm imports to use new class names - All tests pass with original implementation Related to #732
1 parent 0cc19cd commit 9b54237

File tree

4 files changed

+36
-12
lines changed

4 files changed

+36
-12
lines changed

pymoo/algorithms/moo/sms.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pymoo.docs import parse_doc_string
77
from pymoo.indicators.hv.exact import ExactHypervolume
88
from pymoo.indicators.hv.exact_2d import ExactHypervolume2D
9-
from pymoo.indicators.hv.monte_carlo import ApproximateMonteCarloHypervolume
9+
from pymoo.indicators.hv.approximate import ApproximateHypervolume
1010
from pymoo.operators.crossover.sbx import SBX
1111
from pymoo.operators.mutation.pm import PM
1212
from pymoo.operators.sampling.rnd import FloatRandomSampling
@@ -70,7 +70,7 @@ def _do(self, problem, pop, *args, n_survive=None, ideal=None, nadir=None, **kwa
7070
if n_obj == 2:
7171
clazz = ExactHypervolume2D
7272
elif n_obj > 3:
73-
clazz = ApproximateMonteCarloHypervolume
73+
clazz = ApproximateHypervolume
7474

7575
# finally do the computation
7676
hv = clazz(ref_point).add(F)

pymoo/indicators/hv/monte_carlo.py renamed to pymoo/indicators/hv/approximate.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import numpy as np
2+
# from moocore import hv_approx, hv_contributions
23

34
from pymoo.indicators.hv.exact import DynamicHypervolume
45

@@ -32,7 +33,7 @@ def hvc_monte_carlo(dom, V, n_dom=None, k=1):
3233
return hvc
3334

3435

35-
class ApproximateMonteCarloHypervolume(DynamicHypervolume):
36+
class ApproximateHypervolume(DynamicHypervolume):
3637

3738
def __init__(self, ref_point, n_samples=10000, n_exclusive=1, random_state=None, **kwargs) -> None:
3839
self.n_samples = n_samples
@@ -63,6 +64,18 @@ def _calc(self, ref_point, F):
6364

6465
return hv, hvc
6566

67+
# MOOCORE VERSION (commented out for comparison)
68+
# if len(F) == 0:
69+
# return 0.0, np.zeros(0)
70+
#
71+
# # Use moocore for approximate hypervolume calculation
72+
# hv = hv_approx(F, ref=ref_point, nsamples=self.n_samples, seed=self.random_state.randint(0, 2**32-1))
73+
#
74+
# # Use moocore for exact hypervolume contributions (no approximate version available)
75+
# hvc = hv_contributions(F, ref=ref_point)
76+
#
77+
# return hv, hvc
78+
6679
def delete(self, k):
6780
self.F = np.delete(self.F, k, axis=0)
6881
self.dom = np.delete(self.dom, k, axis=0)
@@ -73,3 +86,15 @@ def delete(self, k):
7386
n_dom = dom.sum(axis=0)
7487
self.hvc = hvc_monte_carlo(dom, V, n_dom=n_dom, k=self.n_exclusive)
7588

89+
# MOOCORE VERSION (commented out for comparison)
90+
# # Handle empty array case
91+
# if len(self.F) == 0:
92+
# self.hv = 0.0
93+
# self.hvc = np.zeros(0)
94+
# else:
95+
# # Use moocore for updated hypervolume and contributions
96+
# self.hv = hv_approx(self.F, ref=self.ref_point, nsamples=self.n_samples, seed=self.random_state.randint(0, 2**32-1))
97+
# self.hvc = hv_contributions(self.F, ref=self.ref_point)
98+
#
99+
# return self
100+

pymoo/indicators/hv/exact.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import numpy as np
2-
from moocore import hypervolume as _hypervolume
3-
4-
from pymoo.indicators.hv import hvc_looped
2+
from moocore import hypervolume as hv
3+
from moocore import hv_contributions as hvc
54

65

76
def hv_exact(ref_point, F):
8-
return _hypervolume(F, ref = ref_point)
7+
return hv(F, ref=ref_point)
98

109

11-
def hvc_exact_loopwise(ref_point, F):
12-
return hvc_looped(ref_point, F, hv_exact)
10+
def hvc_exact(ref_point, F):
11+
return hvc(F, ref=ref_point)
1312

1413

1514
class DynamicHypervolume:
@@ -65,5 +64,5 @@ def _calc(self, ref_point, F):
6564

6665
class ExactHypervolume(DynamicHypervolume):
6766

68-
def __init__(self, ref_point, func_hv=hv_exact, func_hvc=hvc_exact_loopwise, **kwargs) -> None:
67+
def __init__(self, ref_point, func_hv=hv_exact, func_hvc=hvc_exact, **kwargs) -> None:
6968
super().__init__(ref_point, func_hv=func_hv, func_hvc=func_hvc, **kwargs)

tests/indicators/test_hv.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from pymoo.indicators.hv.exact import ExactHypervolume
55
from pymoo.indicators.hv.exact_2d import ExactHypervolume2D
6-
from pymoo.indicators.hv.monte_carlo import ApproximateMonteCarloHypervolume
6+
from pymoo.indicators.hv.approximate import ApproximateHypervolume
77
from pymoo.problems.many import DTLZ1
88
from pymoo.problems.multi import ZDT1
99

@@ -64,7 +64,7 @@ def test_hvc_monte_carlo(case):
6464
ref_point, F = case
6565

6666
exact = ExactHypervolume(ref_point).add(F)
67-
mc = ApproximateMonteCarloHypervolume(ref_point, F=F, n_samples=50000)
67+
mc = ApproximateHypervolume(ref_point, F=F, n_samples=20_000)
6868

6969
assert np.allclose(exact.hv, mc.hv, rtol=0, atol=1e-2)
7070
np.testing.assert_allclose(exact.hvc, mc.hvc, rtol=0, atol=1e-1)

0 commit comments

Comments
 (0)