diff --git a/benches/test_bm_example1.py b/benches/test_bm_example1.py index 271a1f7..d858fee 100644 --- a/benches/test_bm_example1.py +++ b/benches/test_bm_example1.py @@ -3,13 +3,14 @@ import numpy as np -from ellalgo.cutting_plane import cutting_plane_optim +from ellalgo.cutting_plane import Options, cutting_plane_optim from ellalgo.ell import Ell from ellalgo.ell_typing import OracleFeas, OracleOptim class MyOracleFeas(OracleFeas): idx = 0 + gamma = 0.0 # constraint 1: x + y <= 3 def fn1(self, x, y): @@ -19,15 +20,21 @@ def fn1(self, x, y): def fn2(self, x, y): return -x + y + 1 + def fn0(self, x, y): + return self.gamma - (x + y) + def grad1(self): return np.array([1.0, 1.0]) def grad2(self): return np.array([-1.0, 1.0]) + def grad0(self): + return np.array([-1.0, -1.0]) + def __init__(self): - self.fns = (self.fn1, self.fn2) - self.grads = (self.grad1, self.grad2) + self.fns = (self.fn1, self.fn2, self.fn0) + self.grads = (self.grad1, self.grad2, self.grad0) def assess_feas(self, z): """[summary] @@ -40,9 +47,9 @@ def assess_feas(self, z): """ x, y = z - for _ in [0, 1]: + for _ in range(3): self.idx += 1 - if self.idx == 2: + if self.idx == 3: self.idx = 0 # round robin if (fj := self.fns[self.idx](x, y)) > 0: return self.grads[self.idx](), fj @@ -62,20 +69,16 @@ def assess_optim(self, z, gamma: float): Returns: [type]: [description] """ + self.helper.gamma = gamma if cut := self.helper.assess_feas(z): return cut, None x, y = z # objective: maximize x + y - f0 = x + y - if (fj := gamma - f0) > 0.0: - return (-1.0 * np.array([1.0, 1.0]), fj), None - - gamma = f0 - return (-1.0 * np.array([1.0, 1.0]), 0.0), gamma + return (np.array([-1.0, -1.0]), 0.0), x + y class MyOracleFeas2(OracleFeas): - idx = 0 + gamma = 0.0 # constraint 1: x + y <= 3 def fn1(self, x, y): @@ -85,15 +88,21 @@ def fn1(self, x, y): def fn2(self, x, y): return -x + y + 1 + def fn0(self, x, y): + return self.gamma - (x + y) + def grad1(self): return np.array([1.0, 1.0]) def grad2(self): return np.array([-1.0, 1.0]) + def grad0(self): + return np.array([-1.0, -1.0]) + def __init__(self): - self.fns = (self.fn1, self.fn2) - self.grads = (self.grad1, self.grad2) + self.fns = (self.fn1, self.fn2, self.fn0) + self.grads = (self.grad1, self.grad2, self.grad0) def assess_feas(self, z): """[summary] @@ -105,13 +114,9 @@ def assess_feas(self, z): [type]: [description] """ x, y = z - - for _ in [0, 1]: - self.idx += 1 - if self.idx == 2: - self.idx = 0 # round robin - if (fj := self.fns[self.idx](x, y)) > 0: - return self.grads[self.idx](), fj + for idx in range(3): + if (fj := self.fns[idx](x, y)) > 0: + return self.grads[idx](), fj return None @@ -128,31 +133,29 @@ def assess_optim(self, z, gamma: float): Returns: [type]: [description] """ + self.helper.gamma = gamma if cut := self.helper.assess_feas(z): return cut, None x, y = z # objective: maximize x + y - f0 = x + y - if (fj := gamma - f0) > 0.0: - return (-1.0 * np.array([1.0, 1.0]), fj), None - - gamma = f0 - return (-1.0 * np.array([1.0, 1.0]), 0.0), gamma + return (np.array([-1.0, -1.0]), 0.0), x + y def run_example1(omega): xinit = np.array([0.0, 0.0]) # initial xinit ellip = Ell(10.0, xinit) - xbest, _, num_iters = cutting_plane_optim(omega(), ellip, float("-inf")) + options = Options() + options.tolerance = 1e-10 + xbest, _, num_iters = cutting_plane_optim(omega(), ellip, float("-inf"), options) assert xbest is not None return num_iters def test_bm_with_round_robin(benchmark): num_iters = benchmark(run_example1, MyOracle) - assert num_iters == 31 + assert num_iters == 25 def test_bm_without_round_robin(benchmark): num_iters = benchmark(run_example1, MyOracle2) - assert num_iters == 31 + assert num_iters == 25