def test_problem_absorb(self): """Test problem object with absorption. """ X = Variable((4, 2)) B = np.reshape(np.arange(8, dtype=np.float32), (4, 2), order='F') # Absorbing lin ops. prox_fns = sum_squares(-2 * X, b=B) + norm1(5 * mul_elemwise(B, X)) prob = Problem(prox_fns) prob.set_absorb(True) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) cvx_X = cvx.Variable((4, 2)) cost = cvx.sum_squares(-2 * cvx_X - B) + cvx.norm( 5 * cvx.multiply(B, cvx_X), 1) cvx_prob = cvx.Problem(cvx.Minimize(cost)) cvx_prob.solve(solver=cvx.SCS) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2) prob.set_absorb(False) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2) # Constant offsets. prox_fns = sum_squares(-2 * X - B) + norm1(5 * mul_elemwise(B, X)) prob = Problem(prox_fns) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2)
def test_mul_elemwise(self): """Test mul_elemwise lin op. """ # Forward. var = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, var) x = W.copy() out = np.zeros(x.shape) fn.forward([x], [out]) self.assertItemsAlmostEqual(out, W * W) # Adjoint. x = W.copy() out = np.zeros(x.shape) fn.adjoint([x], [out]) self.assertItemsAlmostEqual(out, W * W) # Diagonal form. x = Variable(5) fn = mul_elemwise(np.arange(5) - 3, x) assert not fn.is_diag(freq=True) assert fn.is_diag(freq=False) self.assertItemsAlmostEqual( fn.get_diag(freq=False)[x], np.arange(5) - 3)
def test_mul_elemwise(self): """Test mul_elemwise lin op. """ # Forward. var = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, var) x = W.copy() out = np.zeros(x.shape) fn.forward([x], [out]) self.assertItemsAlmostEqual(out, W * W) # Adjoint. x = W.copy() out = np.zeros(x.shape) fn.adjoint([x], [out]) self.assertItemsAlmostEqual(out, W * W) # Diagonal form. x = Variable(5) fn = mul_elemwise(np.arange(5) - 3, x) assert not fn.is_diag(freq=True) assert fn.is_diag(freq=False) self.assertItemsAlmostEqual(fn.get_diag(freq=False)[x], np.arange(5) - 3)
def test_problem(self): """Test problem object. """ X = Variable((4, 2)) B = np.reshape(np.arange(8), (4, 2)) * 1. prox_fns = [norm1(X), sum_squares(X, b=B)] prob = Problem(prox_fns) # prob.partition(quad_funcs = [prox_fns[0], prox_fns[1]]) prob.set_automatic_frequency_split(False) prob.set_absorb(False) prob.set_implementation(Impl['halide']) prob.set_solver('admm') prob.solve() true_X = norm1(X).prox(2, B.copy()) self.assertItemsAlmostEqual(X.value, true_X, places=2) prob.solve(solver="pc") self.assertItemsAlmostEqual(X.value, true_X, places=2) prob.solve(solver="hqs", eps_rel=1e-6, rho_0=1.0, rho_scale=np.sqrt(2.0) * 2.0, rho_max=2**16, max_iters=20, max_inner_iters=500, verbose=False) self.assertItemsAlmostEqual(X.value, true_X, places=2) # CG prob = Problem(prox_fns) prob.set_lin_solver("cg") prob.solve(solver="admm") self.assertItemsAlmostEqual(X.value, true_X, places=2) prob.solve(solver="hqs", eps_rel=1e-6, rho_0=1.0, rho_scale=np.sqrt(2.0) * 2.0, rho_max=2**16, max_iters=20, max_inner_iters=500, verbose=False) self.assertItemsAlmostEqual(X.value, true_X, places=2) # Quad funcs. prob = Problem(prox_fns) prob.solve(solver="admm") self.assertItemsAlmostEqual(X.value, true_X, places=2) # Absorbing lin ops. prox_fns = [norm1(5 * mul_elemwise(B, X)), sum_squares(-2 * X, b=B)] prob = Problem(prox_fns) prob.set_absorb(True) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) cvx_X = cvx.Variable(4, 2) cost = cvx.sum_squares(-2 * cvx_X - B) + cvx.norm(5 * cvx.mul_elemwise(B, cvx_X), 1) cvx_prob = cvx.Problem(cvx.Minimize(cost)) cvx_prob.solve(solver=cvx.SCS) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2) prob.set_absorb(False) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2) # Constant offsets. prox_fns = [norm1(5 * mul_elemwise(B, X)), sum_squares(-2 * X - B)] prob = Problem(prox_fns) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2)
def absorb_params(self): """Returns an equivalent sum_squares with alpha = 1.0, gamma = 0, and c = 0. """ new_lin_op = mul_elemwise(self.weight, self.lin_op) new_b = mul_elemwise(self.weight, self.b).value return sum_squares(new_lin_op, alpha=self.alpha, beta=self.beta, b=new_b, c=self.c, gamma=self.gamma).absorb_params()
def test_sum(self): # Forward. x = Variable((2, 3)) y = Variable((2, 3)) fn = sum([x, y]) x_val = np.reshape(np.arange(6) * 1.0, x.shape) y_val = np.reshape(np.arange(6) * 1.0 - 5, x.shape) out = np.zeros(fn.shape) fn.forward([x_val, y_val], [out]) self.assertItemsAlmostEqual(out, 2 * np.arange(6) - 5) # Adjoint. x_val = np.reshape(np.arange(6) * 1.0, x.shape) out = [np.zeros(fn.shape), np.zeros(fn.shape)] fn.adjoint([x_val], out) for arr in out: self.assertItemsAlmostEqual(arr, x_val) # Constant args. x = Variable((2, 3)) y = Variable((2, 3)) x_val = np.reshape(np.arange(6) * 1.0, x.shape) y_val = np.reshape(np.arange(6) * 1.0 - 5, x.shape) fn = sum([x_val, y_val]) self.assertItemsAlmostEqual(fn.value, 2 * np.arange(6) - 5) # Diagonal form. x = Variable(5) term = mul_elemwise(np.arange(5) - 3, x) fn = sum([term, x]) assert not fn.is_diag(freq=True) assert fn.is_diag(freq=False) self.assertItemsAlmostEqual( fn.get_diag(freq=False)[x], np.arange(5) - 3 + np.ones(5))
def test_sum(self): # Forward. x = Variable((2, 3)) y = Variable((2, 3)) fn = sum([x, y]) x_val = np.reshape(np.arange(6) * 1.0, x.shape) y_val = np.reshape(np.arange(6) * 1.0 - 5, x.shape) out = np.zeros(fn.shape) fn.forward([x_val, y_val], [out]) self.assertItemsAlmostEqual(out, 2 * np.arange(6) - 5) # Adjoint. x_val = np.reshape(np.arange(6) * 1.0, x.shape) out = [np.zeros(fn.shape), np.zeros(fn.shape)] fn.adjoint([x_val], out) for arr in out: self.assertItemsAlmostEqual(arr, x_val) # Constant args. x = Variable((2, 3)) y = Variable((2, 3)) x_val = np.reshape(np.arange(6) * 1.0, x.shape) y_val = np.reshape(np.arange(6) * 1.0 - 5, x.shape) fn = sum([x_val, y_val]) self.assertItemsAlmostEqual(fn.value, 2 * np.arange(6) - 5) # Diagonal form. x = Variable(5) term = mul_elemwise(np.arange(5) - 3, x) fn = sum([term, x]) assert not fn.is_diag(freq=True) assert fn.is_diag(freq=False) self.assertItemsAlmostEqual(fn.get_diag(freq=False)[x], np.arange(5) - 3 + np.ones(5))
def test_problem(self): """Test problem object. """ X = Variable((4, 2)) B = np.reshape(np.arange(8), (4, 2)) * 1. prox_fns = [norm1(X), sum_squares(X, b=B)] prob = Problem(prox_fns) # prob.partition(quad_funcs = [prox_fns[0], prox_fns[1]]) prob.set_automatic_frequency_split(False) prob.set_absorb(False) prob.set_implementation(Impl['halide']) prob.set_solver('admm') prob.solve() true_X = norm1(X).prox(2, B.copy()) self.assertItemsAlmostEqual(X.value, true_X, places=2) prob.solve(solver="pc") self.assertItemsAlmostEqual(X.value, true_X, places=2) prob.solve(solver="hqs", eps_rel=1e-6, rho_0=1.0, rho_scale=np.sqrt(2.0) * 2.0, rho_max=2**16, max_iters=20, max_inner_iters=500, verbose=False) self.assertItemsAlmostEqual(X.value, true_X, places=2) # CG prob = Problem(prox_fns) prob.set_lin_solver("cg") prob.solve(solver="admm") self.assertItemsAlmostEqual(X.value, true_X, places=2) prob.solve(solver="hqs", eps_rel=1e-6, rho_0=1.0, rho_scale=np.sqrt(2.0) * 2.0, rho_max=2**16, max_iters=20, max_inner_iters=500, verbose=False) self.assertItemsAlmostEqual(X.value, true_X, places=2) # Quad funcs. prob = Problem(prox_fns) prob.solve(solver="admm") self.assertItemsAlmostEqual(X.value, true_X, places=2) # Absorbing lin ops. prox_fns = [norm1(5 * mul_elemwise(B, X)), sum_squares(-2 * X, b=B)] prob = Problem(prox_fns) prob.set_absorb(True) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) cvx_X = cvx.Variable(4, 2) cost = cvx.sum_squares(-2 * cvx_X - B) + cvx.norm( 5 * cvx.mul_elemwise(B, cvx_X), 1) cvx_prob = cvx.Problem(cvx.Minimize(cost)) cvx_prob.solve(solver=cvx.SCS) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2) prob.set_absorb(False) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2) # Constant offsets. prox_fns = [norm1(5 * mul_elemwise(B, X)), sum_squares(-2 * X - B)] prob = Problem(prox_fns) prob.solve(solver="admm", eps_rel=1e-6, eps_abs=1e-6) self.assertItemsAlmostEqual(X.value, cvx_X.value, places=2)
def test_op_overloading(self): """Test operator overloading. """ # Multiplying by a scalar. # Forward. var = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = -2 * mul_elemwise(W, var) fn = CompGraph(fn) x = W.copy() out = np.zeros(x.shape) fn.forward(x.flatten(), out) self.assertItemsAlmostEqual(out, -2 * W * W) # Adjoint. x = W.copy() out = np.zeros(x.shape).flatten() fn.adjoint(x, out) self.assertItemsAlmostEqual(out, -2 * W * W) # Forward. var = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, var) * 0.5 fn = CompGraph(fn) x = W.copy() out = np.zeros(x.shape) fn.forward(x.flatten(), out) self.assertItemsAlmostEqual(out, W * W / 2.) # Adjoint. x = W.copy() out = np.zeros(x.shape).flatten() fn.adjoint(x, out) self.assertItemsAlmostEqual(out, W * W / 2.) # Dividing by a scalar. # Forward. var = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, var) / 2 fn = CompGraph(fn) x = W.copy() out = np.zeros(x.shape) fn.forward(x, out) self.assertItemsAlmostEqual(out, W * W / 2.) # Adding lin ops. # Forward. x = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, x) fn = fn + x + x self.assertEqual(len(fn.input_nodes), 3) fn = CompGraph(fn) x = W.copy() out = np.zeros(fn.shape) fn.forward(x, out) self.assertItemsAlmostEqual(out, W * W + 2 * W) # Adjoint. x = W.copy() out = np.zeros(x.shape).flatten() fn.adjoint(x, out) self.assertItemsAlmostEqual(out, W * W + 2 * W) # Adding in a constant. # CompGraph should ignore the constant. x = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, x) fn = fn + x + W self.assertEqual(len(fn.input_nodes), 3) fn = CompGraph(fn) x = W.copy() out = np.zeros(fn.shape) fn.forward(x, out) self.assertItemsAlmostEqual(out, W * W + W) # Subtracting lin ops. # Forward. x = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = -mul_elemwise(W, x) fn = x + x - fn self.assertEqual(len(fn.input_nodes), 3) fn = CompGraph(fn) x = W.copy() out = np.zeros(fn.shape) fn.forward(x, out) self.assertItemsAlmostEqual(out, W * W + 2 * W) # Adjoint. x = W.copy() out = np.zeros(x.shape).flatten() fn.adjoint(x, out) self.assertItemsAlmostEqual(out, W * W + 2 * W)
def test_absorb_lin_op(self): """Test absorb lin op operator. """ # norm1. tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 fn = norm1(mul_elemwise(-v, tmp), alpha=5.) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) self.assertItemsAlmostEqual(x, np.sign(v) * np.maximum(np.abs(v) - 5. * np.abs(v) / rho, 0)) fn = norm1(mul_elemwise(-v, mul_elemwise(2 * v, tmp)), alpha=5.) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) self.assertItemsAlmostEqual(x, np.sign(v) * np.maximum(np.abs(v) - 5. * np.abs(v) / rho, 0)) new_prox = absorb_lin_op(new_prox)[0] x = new_prox.prox(rho, v.copy()) new_v = 2 * v * v self.assertItemsAlmostEqual(x, np.sign(new_v) * np.maximum(np.abs(new_v) - 5. * np.abs(new_v) / rho, 0)) # nonneg. tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 fn = nonneg(mul_elemwise(-v, tmp), alpha=5.) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) self.assertItemsAlmostEqual(x, fn.prox(rho, -np.abs(v))) # sum_squares. tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 alpha = 5. val = np.arange(10) fn = sum_squares(mul_elemwise(-v, tmp), alpha=alpha, c=val) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) cvx_x = cvx.Variable(10) prob = cvx.Problem(cvx.Minimize(cvx.sum_squares(cvx_x - v) * (rho / 2) + 5 * cvx.sum_squares(cvx.mul_elemwise(-v, cvx_x)) + (val * -v).T * cvx_x )) prob.solve() self.assertItemsAlmostEqual(x, cvx_x.value, places=3) # Test scale. tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 fn = norm1(10 * tmp) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) cvx_x = cvx.Variable(10) prob = cvx.Problem(cvx.Minimize(cvx.sum_squares(cvx_x - v) + cvx.norm(10 * cvx_x, 1))) prob.solve() self.assertItemsAlmostEqual(x, cvx_x.value, places=3) val = np.arange(10) fn = norm1(10 * tmp, c=val, b=val, gamma=0.01) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) cvx_x = cvx.Variable(10) prob = cvx.Problem(cvx.Minimize(cvx.sum_squares(cvx_x - v) + cvx.norm(10 * cvx_x - val, 1) + 10 * val.T * \ cvx_x + cvx.sum_squares(cvx_x) )) prob.solve() self.assertItemsAlmostEqual(x, cvx_x.value, places=2) # sum_entries tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 fn = sum_entries(sum([10 * tmp, mul_elemwise(v, tmp)])) funcs = absorb.absorb_all_lin_ops([fn]) c = __builtins__['sum']([func.c for func in funcs]) self.assertItemsAlmostEqual(c, v + 10, places=3)
def test_absorb_lin_op(self): """Test absorb lin op operator. """ # norm1. tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 fn = norm1(mul_elemwise(-v, tmp), alpha=5.) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) self.assertItemsAlmostEqual( x, np.sign(v) * np.maximum(np.abs(v) - 5. * np.abs(v) / rho, 0)) fn = norm1(mul_elemwise(-v, mul_elemwise(2 * v, tmp)), alpha=5.) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) self.assertItemsAlmostEqual( x, np.sign(v) * np.maximum(np.abs(v) - 5. * np.abs(v) / rho, 0)) new_prox = absorb_lin_op(new_prox)[0] x = new_prox.prox(rho, v.copy()) new_v = 2 * v * v self.assertItemsAlmostEqual( x, np.sign(new_v) * np.maximum(np.abs(new_v) - 5. * np.abs(new_v) / rho, 0)) # nonneg. tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 fn = nonneg(mul_elemwise(-v, tmp), alpha=5.) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) self.assertItemsAlmostEqual(x, fn.prox(rho, -np.abs(v))) # sum_squares. tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 alpha = 5. val = np.arange(10) fn = sum_squares(mul_elemwise(-v, tmp), alpha=alpha, c=val) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) cvx_x = cvx.Variable(10) prob = cvx.Problem( cvx.Minimize( cvx.sum_squares(cvx_x - v) * (rho / 2) + 5 * cvx.sum_squares(cvx.mul_elemwise(-v, cvx_x)) + (val * -v).T * cvx_x)) prob.solve() self.assertItemsAlmostEqual(x, cvx_x.value, places=3) # Test scale. tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 fn = norm1(10 * tmp) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) cvx_x = cvx.Variable(10) prob = cvx.Problem( cvx.Minimize(cvx.sum_squares(cvx_x - v) + cvx.norm(10 * cvx_x, 1))) prob.solve() self.assertItemsAlmostEqual(x, cvx_x.value, places=3) val = np.arange(10) fn = norm1(10 * tmp, c=val, b=val, gamma=0.01) rho = 2 new_prox = absorb_lin_op(fn)[0] x = new_prox.prox(rho, v.copy()) cvx_x = cvx.Variable(10) prob = cvx.Problem(cvx.Minimize(cvx.sum_squares(cvx_x - v) + cvx.norm(10 * cvx_x - val, 1) + 10 * val.T * \ cvx_x + cvx.sum_squares(cvx_x) )) prob.solve() self.assertItemsAlmostEqual(x, cvx_x.value, places=2) # sum_entries tmp = Variable(10) v = np.arange(10) * 1.0 - 5.0 fn = sum_entries(sum([10 * tmp, mul_elemwise(v, tmp)])) funcs = absorb.absorb_all_lin_ops([fn]) c = __builtins__['sum']([func.c for func in funcs]) self.assertItemsAlmostEqual(c, v + 10, places=3)
def test_op_overloading(self): """Test operator overloading. """ # Multiplying by a scalar. # Forward. var = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = -2 * mul_elemwise(W, var) fn = CompGraph(fn) x = W.copy() out = np.zeros(x.shape) fn.forward(x.flatten(), out) self.assertItemsAlmostEqual(out, -2 * W * W) # Adjoint. x = W.copy() out = np.zeros(x.shape).flatten() fn.adjoint(x, out) self.assertItemsAlmostEqual(out, -2 * W * W) # Forward. var = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, var) * 0.5 fn = CompGraph(fn) x = W.copy() out = np.zeros(x.shape) fn.forward(x.flatten(), out) self.assertItemsAlmostEqual(out, W * W / 2.) # Adjoint. x = W.copy() out = np.zeros(x.shape).flatten() fn.adjoint(x, out) self.assertItemsAlmostEqual(out, W * W / 2.) # Dividing by a scalar. # Forward. var = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, var) / 2 fn = CompGraph(fn) x = W.copy() out = np.zeros(x.shape) fn.forward(x, out) self.assertItemsAlmostEqual(out, W * W / 2.) # Adding lin ops. # Forward. x = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, x) fn = fn + x + x self.assertEquals(len(fn.input_nodes), 3) fn = CompGraph(fn) x = W.copy() out = np.zeros(fn.shape) fn.forward(x, out) self.assertItemsAlmostEqual(out, W * W + 2 * W) # Adjoint. x = W.copy() out = np.zeros(x.shape).flatten() fn.adjoint(x, out) self.assertItemsAlmostEqual(out, W * W + 2 * W) # Adding in a constant. # CompGraph should ignore the constant. x = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = mul_elemwise(W, x) fn = fn + x + W self.assertEquals(len(fn.input_nodes), 3) fn = CompGraph(fn) x = W.copy() out = np.zeros(fn.shape) fn.forward(x, out) self.assertItemsAlmostEqual(out, W * W + W) # Subtracting lin ops. # Forward. x = Variable((2, 5)) W = np.arange(10) W = np.reshape(W, (2, 5)) fn = -mul_elemwise(W, x) fn = x + x - fn self.assertEquals(len(fn.input_nodes), 3) fn = CompGraph(fn) x = W.copy() out = np.zeros(fn.shape) fn.forward(x, out) self.assertItemsAlmostEqual(out, W * W + 2 * W) # Adjoint. x = W.copy() out = np.zeros(x.shape).flatten() fn.adjoint(x, out) self.assertItemsAlmostEqual(out, W * W + 2 * W)