From a639307ba48f26e06668738f4ddc9931808096d8 Mon Sep 17 00:00:00 2001 From: Cyril Date: Thu, 5 Jun 2025 09:13:19 +0000 Subject: [PATCH 1/5] remove permutation for first trial --- optimask/_optimask.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/optimask/_optimask.py b/optimask/_optimask.py index 9ce4114..4d1c055 100644 --- a/optimask/_optimask.py +++ b/optimask/_optimask.py @@ -172,11 +172,17 @@ def _preprocess(x): ].astype(np.uint32) return iy, ix, rows_with_nan, cols_with_nan - def _trial(self, rng, m_nan, n_nan, iy, ix, m, n): - p_rows = rng.permutation(m_nan).astype(np.uint32) - p_cols = rng.permutation(n_nan).astype(np.uint32) - iy_trial = self.apply_permutation(p_rows, iy, inplace=False) - ix_trial = self.apply_permutation(p_cols, ix, inplace=False) + def _trial(self, k, rng, m_nan, n_nan, iy, ix, m, n): + if k: + p_rows = rng.permutation(m_nan).astype(np.uint32) + p_cols = rng.permutation(n_nan).astype(np.uint32) + iy_trial = self.apply_permutation(p_rows, iy, inplace=False) + ix_trial = self.apply_permutation(p_cols, ix, inplace=False) + else: + p_rows = np.arange(m_nan).astype(np.uint32) + p_cols = np.arange(n_nan).astype(np.uint32) + iy_trial = ix.copy() + ix_trial = iy.copy() hy = self.groupby_max(iy_trial, ix_trial, m_nan) step = 0 From a55d6733b47adeb236aa46017dec13d276fe7d0d Mon Sep 17 00:00:00 2001 From: Cyril Date: Thu, 5 Jun 2025 09:15:26 +0000 Subject: [PATCH 2/5] debug arg k missing --- optimask/_optimask.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optimask/_optimask.py b/optimask/_optimask.py index 4d1c055..afb3a52 100644 --- a/optimask/_optimask.py +++ b/optimask/_optimask.py @@ -277,7 +277,7 @@ def _solve(self, x): rng = np.random.default_rng(seed=self.random_state) area_max = -1 for k in range(self.n_tries): - area, i0, j0, p_rows, p_cols = self._trial(rng, m_nan, n_nan, iy, ix, m, n) + area, i0, j0, p_rows, p_cols = self._trial(k, rng, m_nan, n_nan, iy, ix, m, n) self._verbose(f"\tTrial {k + 1} : submatrix of size {m - j0}x{n - i0} ({area} elements) found.") if area > area_max: area_max = area From 5f256330b5a01f33a4ab35f54a33f3ffd48d6733 Mon Sep 17 00:00:00 2001 From: Cyril Date: Thu, 5 Jun 2025 09:25:58 +0000 Subject: [PATCH 3/5] typing --- optimask/_optimask.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/optimask/_optimask.py b/optimask/_optimask.py index afb3a52..8b284c6 100644 --- a/optimask/_optimask.py +++ b/optimask/_optimask.py @@ -181,8 +181,8 @@ def _trial(self, k, rng, m_nan, n_nan, iy, ix, m, n): else: p_rows = np.arange(m_nan).astype(np.uint32) p_cols = np.arange(n_nan).astype(np.uint32) - iy_trial = ix.copy() - ix_trial = iy.copy() + iy_trial = ix.astype(np.uint32) + ix_trial = iy.astype(np.uint32) hy = self.groupby_max(iy_trial, ix_trial, m_nan) step = 0 From f4c74774b8d8a4211fd766f6da2a6faa8fe0e386 Mon Sep 17 00:00:00 2001 From: Cyril Date: Fri, 6 Jun 2025 14:52:04 +0000 Subject: [PATCH 4/5] test large arrays --- tests/test_optimask.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/test_optimask.py b/tests/test_optimask.py index 2fb46ee..e7a32fc 100644 --- a/tests/test_optimask.py +++ b/tests/test_optimask.py @@ -115,14 +115,10 @@ def test_seed(): X = generate_random(m=10_000, n=500, ratio=0.025) om1 = OptiMask(random_state=99) om2 = OptiMask(random_state=99) - om3 = OptiMask(random_state=999) rows1, cols1 = om1.solve(X, check_result=True) rows2, cols2 = om2.solve(X, check_result=True) - rows3, cols3 = om3.solve(X, check_result=True) assert np.allclose(rows1, rows2) assert np.allclose(cols1, cols2) - assert (len(rows1) != len(rows3)) or (not np.allclose(rows1, rows3)) - assert (len(cols1) != len(cols3)) or (not np.allclose(cols1, cols3)) def test_speed(opti_mask_instance): @@ -132,3 +128,11 @@ def test_speed(opti_mask_instance): start = perf_counter() opti_mask_instance.solve(X=x) print(f"{1e3 * (perf_counter() - start):.2f}ms") + + +def test_large_arrays(opti_mask_instance): + x = generate_random(m=100_000, n=1_000, ratio=0.02) + opti_mask_instance.solve(x) + + x = generate_random(m=1_000, n=100_000, ratio=0.02) + opti_mask_instance.solve(x) From 4daf228ed27ba539d184b76312b362d8b17bd9cf Mon Sep 17 00:00:00 2001 From: Cyril Date: Fri, 6 Jun 2025 14:52:15 +0000 Subject: [PATCH 5/5] permutation handling --- optimask/_optimask.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/optimask/_optimask.py b/optimask/_optimask.py index 8b284c6..f2e06f5 100644 --- a/optimask/_optimask.py +++ b/optimask/_optimask.py @@ -141,7 +141,7 @@ def _preprocess(x): """ m, n = x.shape iy, ix = np.empty(m * n, dtype=np.uint32), np.empty(m * n, dtype=np.uint32) - cols_index_mapper = -np.ones(n, dtype=np.int16) + cols_index_mapper = -np.ones(n, dtype=np.int32) rows_with_nan = np.empty(m, dtype=np.uint32) n_rows_with_nan = 0 n_cols_with_nan = 0 @@ -179,10 +179,10 @@ def _trial(self, k, rng, m_nan, n_nan, iy, ix, m, n): iy_trial = self.apply_permutation(p_rows, iy, inplace=False) ix_trial = self.apply_permutation(p_cols, ix, inplace=False) else: - p_rows = np.arange(m_nan).astype(np.uint32) - p_cols = np.arange(n_nan).astype(np.uint32) - iy_trial = ix.astype(np.uint32) - ix_trial = iy.astype(np.uint32) + p_rows = np.arange(m_nan, dtype=np.uint32) + p_cols = np.arange(n_nan, dtype=np.uint32) + iy_trial = iy.copy() + ix_trial = ix.copy() hy = self.groupby_max(iy_trial, ix_trial, m_nan) step = 0