Skip to content

Commit 7161d8c

Browse files
0.27.8
pareto
1 parent 3f6c1a8 commit 7161d8c

3 files changed

Lines changed: 73 additions & 1 deletion

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
77

88
[project]
99
name = "spotpython"
10-
version = "0.27.7"
10+
version = "0.27.8"
1111
authors = [
1212
{ name="T. Bartz-Beielstein", email="tbb@bartzundbartz.de" }
1313
]

src/spotpython/mo/pareto.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import numpy as np
2+
3+
4+
def is_pareto_efficient(costs: np.ndarray, minimize: bool = True) -> np.ndarray:
5+
"""
6+
Find the Pareto-efficient points from a set of points.
7+
8+
A point is Pareto-efficient if no other point exists that is better in all objectives.
9+
This function assumes that lower values are preferred for each objective when `minimize=True`,
10+
and higher values are preferred when `minimize=False`.
11+
12+
Args:
13+
costs (np.ndarray):
14+
An (N,M) array-like object of points, where N is the number of points and M is the number of objectives.
15+
minimize (bool, optional):
16+
If True, the function finds Pareto-efficient points assuming
17+
lower values are better. If False, it assumes higher values are better.
18+
Defaults to True.
19+
20+
Returns:
21+
np.ndarray:
22+
A boolean mask of length N, where True indicates that the corresponding point is Pareto-efficient.
23+
24+
Examples:
25+
>>> from spotpython.mo.pareto import is_pareto_efficient
26+
>>> import numpy as np
27+
>>> costs = np.array([[1, 2], [2, 1], [3, 3], [1.5, 1.5]])
28+
>>> is_efficient = is_pareto_efficient(costs)
29+
>>> print(is_efficient)
30+
[ True True False True]
31+
"""
32+
is_efficient = np.ones(costs.shape[0], dtype=bool)
33+
for i, cost in enumerate(costs):
34+
if is_efficient[i]:
35+
if minimize:
36+
is_efficient[is_efficient] = np.any(costs[is_efficient] < cost, axis=1)
37+
else:
38+
is_efficient[is_efficient] = np.any(costs[is_efficient] > cost, axis=1)
39+
is_efficient[i] = True
40+
return is_efficient

test/test_pareto.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import numpy as np
2+
from spotpython.mo.pareto import is_pareto_efficient
3+
4+
def test_is_pareto_efficient_minimize():
5+
costs = np.array([[1, 2], [2, 1], [3, 3], [1.5, 1.5]])
6+
expected = np.array([True, True, False, True])
7+
result = is_pareto_efficient(costs, minimize=True)
8+
assert np.array_equal(result, expected), f"Expected {expected}, but got {result}"
9+
10+
def test_is_pareto_efficient_maximize():
11+
costs = np.array([[1, 2], [2, 1], [3, 3], [1.5, 1.5]])
12+
expected = np.array([False, False, True, False])
13+
result = is_pareto_efficient(costs, minimize=False)
14+
assert np.array_equal(result, expected), f"Expected {expected}, but got {result}"
15+
16+
def test_is_pareto_efficient_single_point():
17+
costs = np.array([[1, 2]])
18+
expected = np.array([True])
19+
result = is_pareto_efficient(costs, minimize=True)
20+
assert np.array_equal(result, expected), f"Expected {expected}, but got {result}"
21+
22+
def test_is_pareto_efficient_identical_points():
23+
costs = np.array([[1, 2], [1, 2], [1, 2]])
24+
expected = np.array([True, False, False])
25+
result = is_pareto_efficient(costs, minimize=True)
26+
assert np.array_equal(result, expected), f"Expected {expected}, but got {result}"
27+
28+
def test_is_pareto_efficient_empty_input():
29+
costs = np.array([])
30+
expected = np.array([])
31+
result = is_pareto_efficient(costs, minimize=True)
32+
assert np.array_equal(result, expected), f"Expected {expected}, but got {result}"

0 commit comments

Comments
 (0)