From 0c86e618a5c3ba929321aefc07ba6322817e67b6 Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 09:15:01 +0900 Subject: [PATCH 01/14] suppress warning with `np.errstate` in hssp.py --- optuna/_hypervolume/hssp.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/optuna/_hypervolume/hssp.py b/optuna/_hypervolume/hssp.py index 1b63552712..f7be2687cc 100644 --- a/optuna/_hypervolume/hssp.py +++ b/optuna/_hypervolume/hssp.py @@ -44,10 +44,12 @@ def _solve_hssp_on_unique_loss_vals( subset_size: int, reference_point: np.ndarray, ) -> np.ndarray: - assert not np.any(reference_point - rank_i_loss_vals <= 0) + with np.errstate(invalid='ignore'): + distance_from_reference_point = reference_point - rank_i_loss_vals + assert not np.any(distance_from_reference_point <= 0) assert subset_size <= rank_i_indices.size n_objectives = reference_point.size - contribs = np.prod(reference_point - rank_i_loss_vals, axis=-1) + contribs = np.prod(distance_from_reference_point, axis=-1) selected_indices = np.zeros(subset_size, dtype=int) selected_vecs = np.empty((subset_size, n_objectives)) indices = np.arange(rank_i_loss_vals.shape[0], dtype=int) From c8f0a5e22c195bd8558306a4065a89febcefaa7a Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 09:15:47 +0900 Subject: [PATCH 02/14] suppress warning with `np.errstate` in utils.py --- optuna/_hypervolume/utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/optuna/_hypervolume/utils.py b/optuna/_hypervolume/utils.py index 5439f30c94..ee057cd383 100644 --- a/optuna/_hypervolume/utils.py +++ b/optuna/_hypervolume/utils.py @@ -35,6 +35,7 @@ def _compute_2d(solution_set: np.ndarray, reference_point: np.ndarray) -> float: mask = sorted_solution_set[:, 1] <= reference_points_y_cummin used_solution = sorted_solution_set[mask] - edge_length_x = reference_point[0] - used_solution[:, 0] - edge_length_y = reference_points_y_cummin[mask] - used_solution[:, 1] + with np.errstate(invalid='ignore'): + edge_length_x = reference_point[0] - used_solution[:, 0] + edge_length_y = reference_points_y_cummin[mask] - used_solution[:, 1] return edge_length_x @ edge_length_y From c13d315bef5328b8b3c565daf6e9d689774e06bc Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 09:29:03 +0900 Subject: [PATCH 03/14] fix black --- optuna/_hypervolume/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna/_hypervolume/utils.py b/optuna/_hypervolume/utils.py index ee057cd383..9445a59ad4 100644 --- a/optuna/_hypervolume/utils.py +++ b/optuna/_hypervolume/utils.py @@ -35,7 +35,7 @@ def _compute_2d(solution_set: np.ndarray, reference_point: np.ndarray) -> float: mask = sorted_solution_set[:, 1] <= reference_points_y_cummin used_solution = sorted_solution_set[mask] - with np.errstate(invalid='ignore'): + with np.errstate(invalid="ignore"): edge_length_x = reference_point[0] - used_solution[:, 0] edge_length_y = reference_points_y_cummin[mask] - used_solution[:, 1] return edge_length_x @ edge_length_y From 4ee5c441471ad7e2d0e528f846669da6567a473d Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 09:29:27 +0900 Subject: [PATCH 04/14] fix black --- optuna/_hypervolume/hssp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna/_hypervolume/hssp.py b/optuna/_hypervolume/hssp.py index f7be2687cc..922e458f96 100644 --- a/optuna/_hypervolume/hssp.py +++ b/optuna/_hypervolume/hssp.py @@ -44,7 +44,7 @@ def _solve_hssp_on_unique_loss_vals( subset_size: int, reference_point: np.ndarray, ) -> np.ndarray: - with np.errstate(invalid='ignore'): + with np.errstate(invalid="ignore"): distance_from_reference_point = reference_point - rank_i_loss_vals assert not np.any(distance_from_reference_point <= 0) assert subset_size <= rank_i_indices.size From 407800f4584d44ef911c77dca1af4e431c6bf15b Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 10:55:52 +0900 Subject: [PATCH 05/14] remove an unneeded assertion and rename a var Co-authored-by: Shuhei Watanabe <47781922+nabenabe0928@users.noreply.github.com> --- optuna/_hypervolume/hssp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/optuna/_hypervolume/hssp.py b/optuna/_hypervolume/hssp.py index 922e458f96..bcb03dad85 100644 --- a/optuna/_hypervolume/hssp.py +++ b/optuna/_hypervolume/hssp.py @@ -45,8 +45,7 @@ def _solve_hssp_on_unique_loss_vals( reference_point: np.ndarray, ) -> np.ndarray: with np.errstate(invalid="ignore"): - distance_from_reference_point = reference_point - rank_i_loss_vals - assert not np.any(distance_from_reference_point <= 0) + diff_of_loss_vals_and_ref_point = reference_point - rank_i_loss_vals assert subset_size <= rank_i_indices.size n_objectives = reference_point.size contribs = np.prod(distance_from_reference_point, axis=-1) From 3a60ef00311b14e9742a9ecdbdd1e66053ed8252 Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 10:56:06 +0900 Subject: [PATCH 06/14] rename a var in optuna/_hypervolume/hssp.py Co-authored-by: Shuhei Watanabe <47781922+nabenabe0928@users.noreply.github.com> --- optuna/_hypervolume/hssp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna/_hypervolume/hssp.py b/optuna/_hypervolume/hssp.py index bcb03dad85..8519e8f994 100644 --- a/optuna/_hypervolume/hssp.py +++ b/optuna/_hypervolume/hssp.py @@ -48,7 +48,7 @@ def _solve_hssp_on_unique_loss_vals( diff_of_loss_vals_and_ref_point = reference_point - rank_i_loss_vals assert subset_size <= rank_i_indices.size n_objectives = reference_point.size - contribs = np.prod(distance_from_reference_point, axis=-1) + contribs = np.prod(diff_of_loss_vals_and_ref_point, axis=-1) selected_indices = np.zeros(subset_size, dtype=int) selected_vecs = np.empty((subset_size, n_objectives)) indices = np.arange(rank_i_loss_vals.shape[0], dtype=int) From b0231d2f6373473a7e7cd2289667187bf97279ea Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 11:31:43 +0900 Subject: [PATCH 07/14] Add a guard to wfg.py --- optuna/_hypervolume/wfg.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/optuna/_hypervolume/wfg.py b/optuna/_hypervolume/wfg.py index de7db1b553..75490dd65c 100644 --- a/optuna/_hypervolume/wfg.py +++ b/optuna/_hypervolume/wfg.py @@ -20,6 +20,8 @@ def __init__(self) -> None: self._reference_point: Optional[np.ndarray] = None def _compute(self, solution_set: np.ndarray, reference_point: np.ndarray) -> float: + if not np.isfinite(reference_point).all(): + return float("inf") self._reference_point = reference_point.astype(np.float64) return self._compute_rec(solution_set.astype(np.float64)) From c4b76648405cfe83c1aa8b20b76dc151f7230da2 Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 16:39:02 +0900 Subject: [PATCH 08/14] Update test_hssp.py --- tests/hypervolume_tests/test_hssp.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/tests/hypervolume_tests/test_hssp.py b/tests/hypervolume_tests/test_hssp.py index 454d4385e7..24005ddf2b 100644 --- a/tests/hypervolume_tests/test_hssp.py +++ b/tests/hypervolume_tests/test_hssp.py @@ -1,4 +1,5 @@ import itertools +import math from typing import Tuple import numpy as np @@ -11,11 +12,14 @@ def _compute_hssp_truth_and_approx(test_case: np.ndarray, subset_size: int) -> T r = 1.1 * np.max(test_case, axis=0) truth = 0.0 for subset in itertools.permutations(test_case, subset_size): - truth = max(truth, optuna._hypervolume.WFG().compute(np.asarray(subset), r)) + hv = optuna._hypervolume.WFG().compute(np.asarray(subset), r) + assert not math.isnan(hv) + truth = max(truth, hv) indices = optuna._hypervolume.hssp._solve_hssp( test_case, np.arange(len(test_case)), subset_size, r ) approx = optuna._hypervolume.WFG().compute(test_case[indices], r) + assert not math.isnan(approx) return truth, approx @@ -35,19 +39,13 @@ def test_solve_hssp_infinite_loss() -> None: rng = np.random.RandomState(128) subset_size = 4 - test_case = rng.rand(9, 2) - test_case[-1].fill(float("inf")) - truth, approx = _compute_hssp_truth_and_approx(test_case, subset_size) - assert np.isinf(truth) - assert np.isinf(approx) - - test_case = rng.rand(9, 3) - test_case[-1].fill(float("inf")) - truth, approx = _compute_hssp_truth_and_approx(test_case, subset_size) - assert truth == 0 - assert np.isnan(approx) - for dim in range(2, 4): + test_case = rng.rand(9, dim) + test_case[-1].fill(float("inf")) + truth, approx = _compute_hssp_truth_and_approx(test_case, subset_size) + assert np.isinf(truth) + assert np.isinf(approx) + test_case = rng.rand(9, dim) test_case[-1].fill(-float("inf")) truth, approx = _compute_hssp_truth_and_approx(test_case, subset_size) From 2d184acdf922da299f7923de874f3ab1db9b7e59 Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 16:40:37 +0900 Subject: [PATCH 09/14] Update hssp.py --- optuna/_hypervolume/hssp.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/optuna/_hypervolume/hssp.py b/optuna/_hypervolume/hssp.py index 8519e8f994..07a4116c22 100644 --- a/optuna/_hypervolume/hssp.py +++ b/optuna/_hypervolume/hssp.py @@ -44,6 +44,8 @@ def _solve_hssp_on_unique_loss_vals( subset_size: int, reference_point: np.ndarray, ) -> np.ndarray: + if not np.isfinite(reference_point).all(): + return rank_i_indices[list(range(subset_size))] with np.errstate(invalid="ignore"): diff_of_loss_vals_and_ref_point = reference_point - rank_i_loss_vals assert subset_size <= rank_i_indices.size From 6cfeff8150580af04f4f1d00f9c77032f40b1e1d Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Wed, 8 May 2024 16:41:19 +0900 Subject: [PATCH 10/14] Update utils.py --- optuna/_hypervolume/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/optuna/_hypervolume/utils.py b/optuna/_hypervolume/utils.py index 9445a59ad4..4de90f7335 100644 --- a/optuna/_hypervolume/utils.py +++ b/optuna/_hypervolume/utils.py @@ -27,6 +27,8 @@ def _compute_2d(solution_set: np.ndarray, reference_point: np.ndarray) -> float: The reference point to compute the hypervolume. """ assert solution_set.shape[1] == 2 and reference_point.shape[0] == 2 + if not np.isfinite(reference_point).all(): + return float("inf") # Ascending order in the 1st objective, and descending order in the 2nd objective. sorted_solution_set = solution_set[np.lexsort((-solution_set[:, 1], solution_set[:, 0]))] From 92d2251767ef5b31258ceb0a82309c716c92b2e7 Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Thu, 9 May 2024 03:40:55 +0900 Subject: [PATCH 11/14] remove an unneeded guard from hssp.py --- optuna/_hypervolume/hssp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/optuna/_hypervolume/hssp.py b/optuna/_hypervolume/hssp.py index 07a4116c22..2d80e69c45 100644 --- a/optuna/_hypervolume/hssp.py +++ b/optuna/_hypervolume/hssp.py @@ -46,8 +46,7 @@ def _solve_hssp_on_unique_loss_vals( ) -> np.ndarray: if not np.isfinite(reference_point).all(): return rank_i_indices[list(range(subset_size))] - with np.errstate(invalid="ignore"): - diff_of_loss_vals_and_ref_point = reference_point - rank_i_loss_vals + diff_of_loss_vals_and_ref_point = reference_point - rank_i_loss_vals assert subset_size <= rank_i_indices.size n_objectives = reference_point.size contribs = np.prod(diff_of_loss_vals_and_ref_point, axis=-1) From 0d543b2678dd066e013a43ab3e2681c4902ff86b Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Thu, 9 May 2024 03:41:40 +0900 Subject: [PATCH 12/14] remove an unneeded guard from utils.py --- optuna/_hypervolume/utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/optuna/_hypervolume/utils.py b/optuna/_hypervolume/utils.py index 4de90f7335..7c24879e2d 100644 --- a/optuna/_hypervolume/utils.py +++ b/optuna/_hypervolume/utils.py @@ -37,7 +37,6 @@ def _compute_2d(solution_set: np.ndarray, reference_point: np.ndarray) -> float: mask = sorted_solution_set[:, 1] <= reference_points_y_cummin used_solution = sorted_solution_set[mask] - with np.errstate(invalid="ignore"): - edge_length_x = reference_point[0] - used_solution[:, 0] - edge_length_y = reference_points_y_cummin[mask] - used_solution[:, 1] + edge_length_x = reference_point[0] - used_solution[:, 0] + edge_length_y = reference_points_y_cummin[mask] - used_solution[:, 1] return edge_length_x @ edge_length_y From 51f08cb9911e1d7dc7899e2f2ff04962b5d92638 Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Thu, 9 May 2024 07:26:06 +0900 Subject: [PATCH 13/14] Update optuna/_hypervolume/hssp.py Co-authored-by: Shuhei Watanabe <47781922+nabenabe0928@users.noreply.github.com> --- optuna/_hypervolume/hssp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optuna/_hypervolume/hssp.py b/optuna/_hypervolume/hssp.py index 2d80e69c45..00e417d95f 100644 --- a/optuna/_hypervolume/hssp.py +++ b/optuna/_hypervolume/hssp.py @@ -45,7 +45,7 @@ def _solve_hssp_on_unique_loss_vals( reference_point: np.ndarray, ) -> np.ndarray: if not np.isfinite(reference_point).all(): - return rank_i_indices[list(range(subset_size))] + return rank_i_indices[:subset_size] diff_of_loss_vals_and_ref_point = reference_point - rank_i_loss_vals assert subset_size <= rank_i_indices.size n_objectives = reference_point.size From 875fbc1db2889b40a76a18b53454d1bd3f13f3ac Mon Sep 17 00:00:00 2001 From: Hiroki Takizawa Date: Tue, 21 May 2024 12:10:53 +0900 Subject: [PATCH 14/14] remove unneeded `filterwarnings` in test_hssp.py --- tests/hypervolume_tests/test_hssp.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/hypervolume_tests/test_hssp.py b/tests/hypervolume_tests/test_hssp.py index 24005ddf2b..86be7b9f5f 100644 --- a/tests/hypervolume_tests/test_hssp.py +++ b/tests/hypervolume_tests/test_hssp.py @@ -34,7 +34,6 @@ def test_solve_hssp(dim: int) -> None: assert approx / truth > 0.6321 # 1 - 1/e -@pytest.mark.filterwarnings("ignore::RuntimeWarning") def test_solve_hssp_infinite_loss() -> None: rng = np.random.RandomState(128) @@ -53,7 +52,6 @@ def test_solve_hssp_infinite_loss() -> None: assert np.isinf(approx) -@pytest.mark.filterwarnings("ignore::RuntimeWarning") def test_solve_hssp_duplicated_infinite_loss() -> None: test_case = np.array([[np.inf, 0, 0], [np.inf, 0, 0], [0, np.inf, 0], [0, 0, np.inf]]) r = np.full(3, np.inf)