Skip to content

Commit

Permalink
epsilon covering problem solved
Browse files Browse the repository at this point in the history
  • Loading branch information
cahity committed Nov 1, 2024
1 parent 8977712 commit 561db5a
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 117 deletions.
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
[tool.pytest.ini_options]
filterwarnings = [
"ignore::UserWarning",
]

[tool.black]
line-length = 100

Expand Down
6 changes: 0 additions & 6 deletions test/algorithms/test_decoupled.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ def setUp(self):
cost_budget=self.cost_budget,
)

def test_pareto_updating(self):
"""Test the pareto_updating method."""

def test_evaluating(self):
"""Test the evaluating method."""
sample_test = self.algorithm.sample_count
Expand Down Expand Up @@ -68,13 +65,10 @@ def test_run_one_step(self):
alg_done = False
for i in range(num_rounds): # Run for 10 rounds, it should be enough.
if not alg_done and i <= 3: # Save the state at round 3 at the latest.
P_test = self.algorithm.P
cost_test = self.algorithm.total_cost
alg_done = self.algorithm.run_one_step()

P = self.algorithm.P
cost = self.algorithm.total_cost

self.assertTrue(num_rounds >= self.algorithm.round)
self.assertTrue(len(P) >= len(P_test))
self.assertTrue(cost_test < cost)
12 changes: 0 additions & 12 deletions test/algorithms/test_paveba.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,6 @@ def setUp(self):
conf_contraction=self.conf_contraction,
)

def test_modeling(self):
"""Test the modeling method."""

def test_discarding(self):
"""Test the discarding method."""

def test_pareto_updating(self):
"""Test the pareto_updating method."""

def test_useful_updating(self):
"""Test the useful_updating method."""

def test_evaluating(self):
"""Test the evaluating method."""
sample_test = self.algo.sample_count
Expand Down
34 changes: 14 additions & 20 deletions test/algorithms/test_paveba_gp.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,11 @@ def setUp(self):
conf_contraction=self.conf_contraction,
)

def test_modeling(self):
"""Test the modeling method."""

def test_discarding(self):
"""Test the discarding method."""

def test_pareto_updating(self):
"""Test the pareto_updating method."""

def test_useful_updating(self):
"""Test the useful_updating method."""

def test_evaluating(self):
"""Test the evaluating method."""
sample_test = self.algo.sample_count
self.algo.evaluating()
self.assertTrue(self.algo.sample_count > sample_test)

def test_whole_class(self):
while True:
Expand All @@ -66,17 +57,20 @@ def test_whole_class(self):

def test_run_one_step(self):
"""Test the run_one_step method."""
for i in range(42):
self.algo.run_one_step()
if i == 3:
S3 = self.algo.S
P3 = self.algo.P
num_rounds = 10
alg_done = False
for i in range(num_rounds): # Run for 10 rounds, it should be enough.
if not alg_done and i <= 3: # Save the state at round 3 at the latest.
S_test = self.algo.S
P_test = self.algo.P
alg_done = self.algo.run_one_step()

self.assertTrue(42 >= self.algo.round)
S = self.algo.S
P = self.algo.P
self.assertTrue(len(S3) >= len(S))
self.assertTrue(len(P) >= len(P3))

self.assertTrue(num_rounds >= self.algo.round)
self.assertTrue(len(S_test) >= len(S))
self.assertTrue(len(P) >= len(P_test))

def test_compute_alpha(self):
"""Test the compute_alpha method."""
Expand Down
12 changes: 0 additions & 12 deletions test/algorithms/test_paveba_partial_gp.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@ def setUp(self):
cost_budget=self.cost_budget,
)

def test_modeling(self):
"""Test the modeling method."""

def test_discarding(self):
"""Test the discarding method."""

def test_pareto_updating(self):
"""Test the pareto_updating method."""

def test_useful_updating(self):
"""Test the useful_updating method."""

def test_evaluating(self):
"""Test the evaluating method."""
sample_test = self.algo.sample_count
Expand Down
18 changes: 10 additions & 8 deletions test/utils/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,22 +190,24 @@ def test_get_delta(self):
np.testing.assert_allclose(delta_true, delta_expected)


class TestIsCovered(TestCase):
"""Test coverage of points w.r.t. the ordering."""
class TestEpsilonCover(TestCase):
"""Test epsilon coverage of Pareto points w.r.t. the ordering."""

def setUp(self):
self.epsilon = 0.1

def test_is_covered(self):
"""Test the is_covered function."""
def test_is_covered_specific_data(self):
"""
Test the is_covered function with a specific case that fails with CLARABEL.
Details: https://github.com/cvxpy/cvxpy/issues/2610
"""

dataset = get_dataset_instance("Test")
vi = dataset.out_data[18].reshape(-1, 1)
vj = dataset.out_data[30].reshape(-1, 1)
vi = dataset.out_data[30]
vj = dataset.out_data[18]
W = np.eye(2)

is_covered(vi, vj, self.epsilon, W)
self.assertIsNone(None)
self.assertFalse(is_covered(vi, vj, self.epsilon, W))


class TestHyperrectangleCheckIntersection(TestCase):
Expand Down
2 changes: 0 additions & 2 deletions vectoptal/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
get_delta,
get_uncovered_set,
get_uncovered_size,
is_covered_SOCP,
is_covered,
hyperrectangle_check_intersection,
hyperrectangle_get_vertices,
Expand All @@ -32,7 +31,6 @@
"get_delta",
"get_uncovered_set",
"get_uncovered_size",
"is_covered_SOCP",
"is_covered",
"hyperrectangle_check_intersection",
"hyperrectangle_get_vertices",
Expand Down
68 changes: 11 additions & 57 deletions vectoptal/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def get_uncovered_set(p_opt_miss, p_opt_hat, mu, eps, W):

for i in p_opt_miss:
for j in p_opt_hat:
if is_covered(mu[i, :].reshape(-1, 1), mu[j, :].reshape(-1, 1), eps, W):
if is_covered(mu[i, :], mu[j, :], eps, W):
break
else:
uncovered_set.append(i)
Expand All @@ -249,82 +249,36 @@ def get_uncovered_size(p_opt_miss, p_opt_hat, eps, W) -> int:

for i, ip in enumerate(p_opt_miss):
for jp in p_opt_hat:
if is_covered(ip.reshape(-1, 1), jp.reshape(-1, 1), eps, W):
if is_covered(ip, jp, eps, W):
break
else:
count += 1

return count


def is_covered_SOCP(vi, vj, eps, W):
def is_covered(vi, vj, eps, W):
"""
Check if vi is eps covered by vj for cone matrix W.
:param vi, vj: (D,1) ndarrays
:param W: An (n_constraint,D) ndarray
:param eps: float
:return: Boolean.
"""
m = 2 * W.shape[0] + 1 # number of constraints
D = W.shape[1]
f = np.zeros(D)
A = []
b = []
c = []
d = []

for i in range(W.shape[0]):
A.append(np.zeros((1, D)))
b.append(np.zeros(1))
c.append(W[i, :])
d.append(np.zeros(1))

A.append(np.eye(D))
b.append((vi - vj).ravel())
c.append(np.zeros(D))
d.append(eps * np.ones(1))

for i in range(W.shape[0]):
A.append(np.zeros((1, D)))
b.append(np.zeros(1))
c.append(W[i, :])
d.append(np.dot(W[i, :], (vi - vj)))
x = cp.Variable(W.shape[1])

# Define and solve the CVXPY problem.
x = cp.Variable(D)
# We use cp.SOC(t, x) to create the SOC constraint ||x||_2 <= t.
soc_constraints = [cp.SOC(c[i].T @ x + d[i], A[i] @ x + b[i]) for i in range(m)]
prob = cp.Problem(cp.Minimize(f.T @ x), soc_constraints)
constraints = [
W @ x >= 0,
cp.norm(x + (vi - vj)) <= eps,
W @ (x + (vi - vj)) >= 0,
]

prob.solve(solver=cp.SCS)
prob = cp.Problem(cp.Minimize(0), constraints)
prob.solve()

"""
# Print result.
print("The optimal value is", prob.value)
print("A solution x is")
print(x.value)
print(x.value is not None)
for i in range(m):
print("SOC constraint %i dual variable solution" % i)
print(soc_constraints[i].dual_value)
"""
return x.value is not None


def is_covered(vi, vj, eps, W):
"""
Check if vi is eps covered by vj for cone matrix W.
:param vi, vj: (D,1) ndarrays
:param W: An (n_constraint,D) ndarray
:param eps: float
:return: Boolean.
"""
# TODO: Check if the commented out early stop condition is correct.
# if np.dot((vi-vj).T, vi-vj) <= eps**2:
# return True
return is_covered_SOCP(vi, vj, eps, W)


def hyperrectangle_check_intersection(
lower1: np.ndarray, upper1: np.ndarray, lower2: np.ndarray, upper2: np.ndarray
) -> bool:
Expand Down

0 comments on commit 561db5a

Please sign in to comment.