def test_dual_problem(self): tests = [] atom, q, prox_center, L = self.atom, self.q, self.prox_center, self.L loss = self.loss dproblem = rr.dual_problem.fromprimal(loss, atom) dcoef = dproblem.solve(coef_stop=self.coef_stop, tol=1.0e-14) tests.append(( atom.proximal(q), dcoef, 'solving prox with dual_problem.fromprimal with monotonicity \n %s ' % str(self))) dproblem2 = rr.dual_problem(loss.conjugate, rr.identity(loss.shape), atom.conjugate) dcoef2 = dproblem2.solve(coef_stop=self.coef_stop, tol=1.e-14) tests.append( (atom.proximal(q), dcoef2, 'solving prox with dual_problem with monotonicity %s \n' % str(self))) if not self.interactive: for test in tests: yield (all_close, ) + test + (self, ) else: for test in tests: yield all_close(*((test + (self, ))))
def test_dual_problem(self): tests = [] atom, q, prox_center, L = self.atom, self.q, self.prox_center, self.L loss = self.loss dproblem = rr.dual_problem.fromprimal(loss, atom) dcoef = dproblem.solve(coef_stop=self.coef_stop, tol=1.0e-14) tests.append((atom.proximal(q), dcoef, 'solving prox with dual_problem.fromprimal with monotonicity \n %s ' % str(self))) dproblem2 = rr.dual_problem(loss.conjugate, rr.identity(loss.shape), atom.conjugate) dcoef2 = dproblem2.solve(coef_stop=self.coef_stop, tol=1.e-14) tests.append((atom.proximal(q), dcoef2, 'solving prox with dual_problem with monotonicity %s \n' % str(self))) if not self.interactive: for test in tests: yield (all_close,) + test + (self,) else: for test in tests: yield all_close(*((test + (self,))))
def solveit(atom, Z, W, U, linq, L, FISTA, coef_stop): p2 = copy(atom) p2.quadratic = rr.identity_quadratic(L, Z, 0, 0) d = atom.conjugate q = rr.identity_quadratic(1, Z, 0, 0) yield ac, Z - atom.proximal(q), d.proximal( q), 'testing duality of projections starting from atom %s ' % atom q = rr.identity_quadratic(L, Z, 0, 0) # use simple_problem.nonsmooth p2 = copy(atom) p2.quadratic = atom.quadratic + q problem = rr.simple_problem.nonsmooth(p2) solver = rr.FISTA(problem) solver.fit(tol=1.0e-14, FISTA=FISTA, coef_stop=coef_stop) yield ac, atom.proximal( q ), solver.composite.coefs, 'solving prox with simple_problem.nonsmooth with monotonicity %s ' % atom # use the solve method p2.coefs *= 0 p2.quadratic = atom.quadratic + q soln = p2.solve() yield ac, atom.proximal( q), soln, 'solving prox with solve method %s ' % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.simple_problem(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, FISTA=FISTA, coef_stop=coef_stop) yield ac, atom.proximal( q ), solver.composite.coefs, 'solving prox with simple_problem with monotonicity %s ' % atom dproblem2 = rr.dual_problem(loss.conjugate, rr.identity(loss.shape), atom.conjugate) dcoef2 = dproblem2.solve(coef_stop=coef_stop, tol=1.e-14) yield ac, atom.proximal( q ), dcoef2, 'solving prox with dual_problem with monotonicity %s ' % atom dproblem = rr.dual_problem.fromprimal(loss, atom) dcoef = dproblem.solve(coef_stop=coef_stop, tol=1.0e-14) yield ac, atom.proximal( q ), dcoef, 'solving prox with dual_problem.fromprimal with monotonicity %s ' % atom # write the loss in terms of a quadratic for the smooth loss and a smooth function... lossq = rr.quadratic.shift(-Z, coef=0.6 * L) lossq.quadratic = rr.identity_quadratic(0.4 * L, Z, 0, 0) problem = rr.simple_problem(lossq, atom) yield ac, atom.proximal(q), problem.solve( coef_stop=coef_stop, FISTA=FISTA, tol=1.0e-12 ), 'solving prox with simple_problem with monotonicity but loss has identity_quadratic %s ' % atom problem = rr.simple_problem.nonsmooth(p2) solver = rr.FISTA(problem) solver.fit(tol=1.0e-14, monotonicity_restart=False, coef_stop=coef_stop, FISTA=FISTA) yield ac, atom.proximal( q ), solver.composite.coefs, 'solving prox with simple_problem.nonsmooth with no monotonocity %s ' % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.simple_problem(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, monotonicity_restart=False, coef_stop=coef_stop, FISTA=FISTA) yield ac, atom.proximal( q ), solver.composite.coefs, 'solving prox with simple_problem %s no monotonicity_restart' % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.separable_problem.singleton(atom, loss) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, coef_stop=coef_stop, FISTA=FISTA) yield ac, atom.proximal( q ), solver.composite.coefs, 'solving atom prox with separable_atom.singleton %s ' % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.container(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, coef_stop=coef_stop, FISTA=FISTA) yield ac, atom.proximal( q ), solver.composite.coefs, 'solving atom prox with container %s ' % atom # write the loss in terms of a quadratic for the smooth loss and a smooth function... lossq = rr.quadratic.shift(-Z, coef=0.6 * L) lossq.quadratic = rr.identity_quadratic(0.4 * L, Z, 0, 0) problem = rr.container(lossq, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, FISTA=FISTA, coef_stop=coef_stop) yield ( ac, atom.proximal(q), problem.solve(tol=1.e-12, FISTA=FISTA, coef_stop=coef_stop), 'solving prox with container with monotonicity but loss has identity_quadratic %s ' % atom) loss = rr.quadratic.shift(-Z, coef=L) problem = rr.simple_problem(loss, d) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, monotonicity_restart=False, coef_stop=coef_stop, FISTA=FISTA) # ac(d.proximal(q), solver.composite.coefs, 'solving dual prox with simple_problem no monotonocity %s ' % atom) yield (ac, d.proximal(q), problem.solve(tol=1.e-12, FISTA=FISTA, coef_stop=coef_stop, monotonicity_restart=False), 'solving dual prox with simple_problem no monotonocity %s ' % atom) problem = rr.container(d, loss) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, coef_stop=coef_stop, FISTA=FISTA) yield ac, d.proximal( q ), solver.composite.coefs, 'solving dual prox with container %s ' % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.separable_problem.singleton(d, loss) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, coef_stop=coef_stop, FISTA=FISTA) yield ac, d.proximal( q ), solver.composite.coefs, 'solving atom prox with separable_atom.singleton %s ' % atom
def test_quadratic_for_smooth(): ''' this test is a check to ensure that the quadratic part of the smooth functions are being used in the proximal step ''' L = 0.45 W = np.random.standard_normal(40) Z = np.random.standard_normal(40) U = np.random.standard_normal(40) atomq = rr.identity_quadratic(0.4, U, W, 0) atom = rr.l1norm(40, quadratic=atomq, lagrange=0.12) # specifying in this way should be the same as if we put 0.5*L below loss = rr.quadratic.shift(Z, coef=0.6 * L) lq = rr.identity_quadratic(0.4 * L, Z, 0, 0) loss.quadratic = lq ww = np.random.standard_normal(40) # specifying in this way should be the same as if we put 0.5*L below loss2 = rr.quadratic.shift(Z, coef=L) yield all_close, loss2.objective(ww), loss.objective( ww), 'checking objective', None yield all_close, lq.objective(ww, 'func'), loss.nonsmooth_objective( ww), 'checking nonsmooth objective', None yield all_close, loss2.smooth_objective( ww, 'func'), 0.5 / 0.3 * loss.smooth_objective( ww, 'func'), 'checking smooth objective func', None yield all_close, loss2.smooth_objective( ww, 'grad'), 0.5 / 0.3 * loss.smooth_objective( ww, 'grad'), 'checking smooth objective grad', None problem = rr.container(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12) problem3 = rr.simple_problem(loss, atom) solver3 = rr.FISTA(problem3) solver3.fit(tol=1.0e-12, coef_stop=True) loss4 = rr.quadratic.shift(Z, coef=0.6 * L) problem4 = rr.simple_problem(loss4, atom) problem4.quadratic = lq solver4 = rr.FISTA(problem4) solver4.fit(tol=1.0e-12) gg_soln = rr.gengrad(problem, L) loss6 = rr.quadratic.shift(Z, coef=0.6 * L) loss6.quadratic = lq + atom.quadratic atomcp = copy(atom) atomcp.quadratic = rr.identity_quadratic(0, 0, 0, 0) problem6 = rr.dual_problem(loss6.conjugate, rr.identity(loss6.shape), atomcp.conjugate) problem6.lipschitz = L + atom.quadratic.coef dsoln2 = problem6.solve(coef_stop=True, tol=1.e-10, max_its=100) problem2 = rr.container(loss2, atom) solver2 = rr.FISTA(problem2) solver2.fit(tol=1.0e-12, coef_stop=True) q = rr.identity_quadratic(L, Z, 0, 0) yield all_close, problem.objective( ww), atom.nonsmooth_objective(ww) + q.objective(ww, 'func'), '', None atom = rr.l1norm(40, quadratic=atomq, lagrange=0.12) aq = atom.solve(q) for p, msg in zip([ solver3.composite.coefs, gg_soln, solver2.composite.coefs, dsoln2, solver.composite.coefs, solver4.composite.coefs ], [ 'simple_problem with loss having no quadratic', 'gen grad', 'container with loss having no quadratic', 'dual problem with loss having a quadratic', 'container with loss having a quadratic', 'simple_problem having a quadratic' ]): yield all_close, aq, p, msg, None
def test_quadratic_for_smooth(): ''' this test is a check to ensure that the quadratic part of the smooth functions are being used in the proximal step ''' L = 0.45 W = np.random.standard_normal(40) Z = np.random.standard_normal(40) U = np.random.standard_normal(40) atomq = rr.identity_quadratic(0.4, U, W, 0) atom = rr.l1norm(40, quadratic=atomq, lagrange=0.12) # specifying in this way should be the same as if we put 0.5*L below loss = rr.quadratic_loss.shift(Z, coef=0.6*L) lq = rr.identity_quadratic(0.4*L, Z, 0, 0) loss.quadratic = lq ww = np.random.standard_normal(40) # specifying in this way should be the same as if we put 0.5*L below loss2 = rr.quadratic_loss.shift(Z, coef=L) yield all_close, loss2.objective(ww), loss.objective(ww), 'checking objective', None yield all_close, lq.objective(ww, 'func'), loss.nonsmooth_objective(ww), 'checking nonsmooth objective', None yield all_close, loss2.smooth_objective(ww, 'func'), 0.5 / 0.3 * loss.smooth_objective(ww, 'func'), 'checking smooth objective func', None yield all_close, loss2.smooth_objective(ww, 'grad'), 0.5 / 0.3 * loss.smooth_objective(ww, 'grad'), 'checking smooth objective grad', None problem = rr.container(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12) problem3 = rr.simple_problem(loss, atom) solver3 = rr.FISTA(problem3) solver3.fit(tol=1.0e-12, coef_stop=True) loss4 = rr.quadratic_loss.shift(Z, coef=0.6*L) problem4 = rr.simple_problem(loss4, atom) problem4.quadratic = lq solver4 = rr.FISTA(problem4) solver4.fit(tol=1.0e-12) gg_soln = rr.gengrad(problem, L) loss6 = rr.quadratic_loss.shift(Z, coef=0.6*L) loss6.quadratic = lq + atom.quadratic atomcp = copy(atom) atomcp.quadratic = rr.identity_quadratic(0,0,0,0) problem6 = rr.dual_problem(loss6.conjugate, rr.identity(loss6.shape), atomcp.conjugate) problem6.lipschitz = L + atom.quadratic.coef dsoln2 = problem6.solve(coef_stop=True, tol=1.e-10, max_its=100) problem2 = rr.container(loss2, atom) solver2 = rr.FISTA(problem2) solver2.fit(tol=1.0e-12, coef_stop=True) q = rr.identity_quadratic(L, Z, 0, 0) yield all_close, problem.objective(ww), atom.nonsmooth_objective(ww) + q.objective(ww,'func'), '', None atom = rr.l1norm(40, quadratic=atomq, lagrange=0.12) aq = atom.solve(q) for p, msg in zip([solver3.composite.coefs, gg_soln, solver2.composite.coefs, dsoln2, solver.composite.coefs, solver4.composite.coefs], ['simple_problem with loss having no quadratic', 'gen grad', 'container with loss having no quadratic', 'dual problem with loss having a quadratic', 'container with loss having a quadratic', 'simple_problem having a quadratic']): yield all_close, aq, p, msg, None
def test_quadratic_for_smooth2(): """ this test is a check to ensure that the quadratic part of the smooth functions are being used in the proximal step """ L = 2 W = np.arange(5) Z = 0.5 * np.arange(5)[::-1] U = 1.5 * np.arange(5) atomq = rr.identity_quadratic(0.4, U, W, 0) atom = rr.l1norm(5, quadratic=atomq, lagrange=0.1) # specifying in this way should be the same as if we put 0.5*L below loss = rr.quadratic.shift(-Z, coef=0.6 * L) lq = rr.identity_quadratic(0.4 * L, Z, 0, 0) loss.quadratic = lq ww = np.ones(5) # specifying in this way should be the same as if we put 0.5*L below loss2 = rr.quadratic.shift(-Z, coef=L) np.testing.assert_allclose(loss2.objective(ww), loss.objective(ww)) np.testing.assert_allclose(lq.objective(ww, "func"), loss.nonsmooth_objective(ww)) np.testing.assert_allclose(loss2.smooth_objective(ww, "func"), 0.5 / 0.3 * loss.smooth_objective(ww, "func")) np.testing.assert_allclose(loss2.smooth_objective(ww, "grad"), 0.5 / 0.3 * loss.smooth_objective(ww, "grad")) problem = rr.container(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12) problem3 = rr.simple_problem(loss, atom) solver3 = rr.FISTA(problem3) solver3.fit(tol=1.0e-12, coef_stop=True) loss4 = rr.quadratic.shift(-Z, coef=0.6 * L) problem4 = rr.simple_problem(loss4, atom) problem4.quadratic = lq solver4 = rr.FISTA(problem4) solver4.fit(tol=1.0e-12) gg_soln = rr.gengrad(problem4, L) loss6 = rr.quadratic.shift(-Z, coef=0.6 * L) loss6.quadratic = lq + atom.quadratic atomcp = copy(atom) atomcp.quadratic = rr.identity_quadratic(0, 0, 0, 0) problem6 = rr.dual_problem(loss6.conjugate, rr.identity(loss6.primal_shape), atomcp.conjugate) problem6.lipschitz = L + atom.quadratic.coef dsoln2 = problem6.solve(coef_stop=True, tol=1.0e-10, max_its=100) problem2 = rr.container(loss2, atom) solver2 = rr.FISTA(problem2) solver2.fit(tol=1.0e-12, coef_stop=True) q = rr.identity_quadratic(L, Z, 0, 0) ac(problem.objective(ww), atom.nonsmooth_objective(ww) + q.objective(ww, "func")) aq = atom.solve(q) for p, msg in zip( [ solver3.composite.coefs, gg_soln, solver2.composite.coefs, solver4.composite.coefs, dsoln2, solver.composite.coefs, ], [ "simple_problem with loss having no quadratic", "gen grad", "container with loss having no quadratic", "simple_problem container with quadratic", "dual problem with loss having a quadratic", "container with loss having a quadratic", ], ): yield ac, aq, p, msg
def solveit(atom, Z, W, U, linq, L, FISTA, coef_stop): p2 = copy(atom) p2.quadratic = rr.identity_quadratic(L, Z, 0, 0) d = atom.conjugate q = rr.identity_quadratic(1, Z, 0, 0) yield ac, Z - atom.proximal(q), d.proximal(q), "testing duality of projections starting from atom %s " % atom q = rr.identity_quadratic(L, Z, 0, 0) # use simple_problem.nonsmooth p2 = copy(atom) p2.quadratic = atom.quadratic + q problem = rr.simple_problem.nonsmooth(p2) solver = rr.FISTA(problem) solver.fit(tol=1.0e-14, FISTA=FISTA, coef_stop=coef_stop) yield ac, atom.proximal( q ), solver.composite.coefs, "solving prox with simple_problem.nonsmooth with monotonicity %s " % atom # use the solve method p2.coefs *= 0 p2.quadratic = atom.quadratic + q soln = p2.solve() yield ac, atom.proximal(q), soln, "solving prox with solve method %s " % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.simple_problem(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, FISTA=FISTA, coef_stop=coef_stop) yield ac, atom.proximal(q), solver.composite.coefs, "solving prox with simple_problem with monotonicity %s " % atom dproblem2 = rr.dual_problem(loss.conjugate, rr.identity(loss.primal_shape), atom.conjugate) dcoef2 = dproblem2.solve(coef_stop=coef_stop, tol=1.0e-14) yield ac, atom.proximal(q), dcoef2, "solving prox with dual_problem with monotonicity %s " % atom dproblem = rr.dual_problem.fromprimal(loss, atom) dcoef = dproblem.solve(coef_stop=coef_stop, tol=1.0e-14) yield ac, atom.proximal(q), dcoef, "solving prox with dual_problem.fromprimal with monotonicity %s " % atom # write the loss in terms of a quadratic for the smooth loss and a smooth function... lossq = rr.quadratic.shift(-Z, coef=0.6 * L) lossq.quadratic = rr.identity_quadratic(0.4 * L, Z, 0, 0) problem = rr.simple_problem(lossq, atom) yield ac, atom.proximal(q), problem.solve( coef_stop=coef_stop, FISTA=FISTA, tol=1.0e-12 ), "solving prox with simple_problem with monotonicity but loss has identity_quadratic %s " % atom problem = rr.simple_problem.nonsmooth(p2) solver = rr.FISTA(problem) solver.fit(tol=1.0e-14, monotonicity_restart=False, coef_stop=coef_stop, FISTA=FISTA) yield ac, atom.proximal( q ), solver.composite.coefs, "solving prox with simple_problem.nonsmooth with no monotonocity %s " % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.simple_problem(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, monotonicity_restart=False, coef_stop=coef_stop, FISTA=FISTA) yield ac, atom.proximal( q ), solver.composite.coefs, "solving prox with simple_problem %s no monotonicity_restart" % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.separable_problem.singleton(atom, loss) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, coef_stop=coef_stop, FISTA=FISTA) yield ac, atom.proximal(q), solver.composite.coefs, "solving atom prox with separable_atom.singleton %s " % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.container(loss, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, coef_stop=coef_stop, FISTA=FISTA) yield ac, atom.proximal(q), solver.composite.coefs, "solving atom prox with container %s " % atom # write the loss in terms of a quadratic for the smooth loss and a smooth function... lossq = rr.quadratic.shift(-Z, coef=0.6 * L) lossq.quadratic = rr.identity_quadratic(0.4 * L, Z, 0, 0) problem = rr.container(lossq, atom) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, FISTA=FISTA, coef_stop=coef_stop) yield ( ac, atom.proximal(q), problem.solve(tol=1.0e-12, FISTA=FISTA, coef_stop=coef_stop), "solving prox with container with monotonicity but loss has identity_quadratic %s " % atom, ) loss = rr.quadratic.shift(-Z, coef=L) problem = rr.simple_problem(loss, d) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, monotonicity_restart=False, coef_stop=coef_stop, FISTA=FISTA) # ac(d.proximal(q), solver.composite.coefs, 'solving dual prox with simple_problem no monotonocity %s ' % atom) yield ( ac, d.proximal(q), problem.solve(tol=1.0e-12, FISTA=FISTA, coef_stop=coef_stop, monotonicity_restart=False), "solving dual prox with simple_problem no monotonocity %s " % atom, ) problem = rr.container(d, loss) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, coef_stop=coef_stop, FISTA=FISTA) yield ac, d.proximal(q), solver.composite.coefs, "solving dual prox with container %s " % atom loss = rr.quadratic.shift(-Z, coef=L) problem = rr.separable_problem.singleton(d, loss) solver = rr.FISTA(problem) solver.fit(tol=1.0e-12, coef_stop=coef_stop, FISTA=FISTA) yield ac, d.proximal(q), solver.composite.coefs, "solving atom prox with separable_atom.singleton %s " % atom