def test_rel_entr(self) -> None: """Test domain for rel_entr. """ b = Variable() dom = cp.rel_entr(self.a, b).domain Problem(Minimize(self.a + b), dom).solve() self.assertAlmostEqual(self.a.value, 0) self.assertAlmostEqual(b.value, 0)
def test_rel_entr(self) -> None: """Test domain for rel_entr. """ b = Variable() expr = cp.rel_entr(self.a, b) self.a.value = 2 b.value = 4 self.assertAlmostEqual(expr.grad[self.a], np.log(2 / 4) + 1) self.assertAlmostEqual(expr.grad[b], -(2 / 4)) self.a.value = 3 b.value = 0 self.assertAlmostEqual(expr.grad[self.a], None) self.assertAlmostEqual(expr.grad[b], None) self.a.value = -1 b.value = 2 self.assertAlmostEqual(expr.grad[self.a], None) self.assertAlmostEqual(expr.grad[b], None) y = Variable(2) expr = cp.rel_entr(self.x, y) self.x.value = [3, 4] y.value = [5, 8] val = np.zeros((2, 2)) + np.diag(np.log([3, 4]) - np.log([5, 8]) + 1) self.assertItemsAlmostEqual(expr.grad[self.x].toarray(), val) val = np.zeros((2, 2)) + np.diag([-3 / 5, -4 / 8]) self.assertItemsAlmostEqual(expr.grad[y].toarray(), val) expr = cp.rel_entr(self.x, y) self.x.value = [-1e-9, 4] y.value = [1, 2] self.assertAlmostEqual(expr.grad[self.x], None) self.assertAlmostEqual(expr.grad[y], None) expr = cp.rel_entr(self.A, self.B) self.A.value = [[1, 2], [3, 4]] self.B.value = [[5, 1], [3.5, 2.3]] div = (self.A.value / self.B.value).ravel(order='F') val = np.zeros((4, 4)) + np.diag(np.log(div) + 1) self.assertItemsAlmostEqual(expr.grad[self.A].toarray(), val) val = np.zeros((4, 4)) + np.diag(-div) self.assertItemsAlmostEqual(expr.grad[self.B].toarray(), val)
def test_difference_kl_div_rel_entr(self) -> None: """A test showing the difference between kl_div and rel_entr """ x = cvx.Variable() y = cvx.Variable() kl_div_prob = cvx.Problem(cvx.Minimize(cvx.kl_div(x, y)), constraints=[x + y <= 1]) kl_div_prob.solve(solver=cvx.ECOS) self.assertItemsAlmostEqual(x.value, y.value) self.assertItemsAlmostEqual(kl_div_prob.value, 0) rel_entr_prob = cvx.Problem(cvx.Minimize(cvx.rel_entr(x, y)), constraints=[x + y <= 1]) rel_entr_prob.solve(solver=cvx.ECOS) """ Reference solution computed by passing the following command to Wolfram Alpha: minimize x*log(x/y) subject to {x + y <= 1, 0 <= x, 0 <= y} """ self.assertItemsAlmostEqual(x.value, 0.2178117, places=4) self.assertItemsAlmostEqual(y.value, 0.7821882, places=4) self.assertItemsAlmostEqual(rel_entr_prob.value, -0.278464)
def test_rel_entr(self) -> None: """Test a problem with rel_entr. """ kK = 50 kSeed = 10 prng = np.random.RandomState(kSeed) # Generate a random reference distribution npSPriors = prng.uniform(0.0, 1.0, kK) npSPriors = npSPriors / sum(npSPriors) # Reference distribution p_refProb = cvx.Parameter(kK, nonneg=True) # Distribution to be estimated v_prob = cvx.Variable(kK) obj_rel_entr = cvx.sum(cvx.rel_entr(v_prob, p_refProb)) constrs = [cvx.sum(v_prob) == 1] rel_entr_prob = cvx.Problem(cvx.Minimize(obj_rel_entr), constrs) p_refProb.value = npSPriors rel_entr_prob.solve(solver=cvx.SCS, verbose=True) self.assertItemsAlmostEqual(v_prob.value, npSPriors, places=3) rel_entr_prob.solve(solver=cvx.ECOS, verbose=True) self.assertItemsAlmostEqual(v_prob.value, npSPriors)