def test(self): x = cp.Variable(10) x.value = np.zeros(10) expr = cp.sum_squares(x) with self.assertRaises(AssertionError): sccf.minimum(-expr, 1.0) min_expr = sccf.minimum(expr, 1.0) self.assertEqual(min_expr.value, 0.0) x.value = np.ones(10) self.assertEqual(min_expr.value, 1.0)
def test(self): x = cp.Variable(1) x.value = 2 * np.ones(1) expr1 = sccf.minimum(cp.sum(cp.huber(x)), 1.0) expr2 = sccf.minimum(cp.sum(cp.huber(x - 1.0)), 1.0) obj = expr1 + expr2 starting = obj.value prob = sccf.Problem(obj) ending = prob.solve() self.assertLessEqual(ending["final_objective_value"], starting)
def test(self): x = cp.Variable(10) x.value = np.zeros(10) expr1 = sccf.minimum(cp.sum_squares(x), 1.0) expr2 = sccf.minimum(cp.sum_squares(x - 1), 1.0) sum_exprs = expr1 + expr2 self.assertEqual(len(sum_exprs.min_exprs), 2) self.assertEqual(sum_exprs.value, 1.0) sum_exprs += 1.0 self.assertEqual(sum_exprs.value, 2.0) sum_exprs += cp.sum_squares(x - 1) self.assertEqual(sum_exprs.value, 12.0)
import cvxpy as cp import sccf import numpy as np np.random.seed(3) # fishy? a = np.random.randint(-50, 50, size=5) idx = np.random.choice(np.arange(5), size=3, replace=False) a = np.append( a, -int(np.sum(a[idx])) ) n = a.size print("a =", a) x = cp.Variable(n) objective = 0.0 for i in range(n): objective += sccf.minimum(cp.square(x[i]), 0.25) objective += sccf.minimum(cp.square(x[i] - 1.0), 0.25) objective += cp.square(a*x) - n/4 constraints = [cp.sum(x) >= 1.0] prob = sccf.Problem(objective, constraints) print("Alternating minimization:") result = prob.solve(maxiter=50, verbose=True, warm_start_lam=np.random.uniform(0.0, 1.0, size=2*n+2), solver=cp.MOSEK) print("objective value = %.3f" % result["final_objective_value"]) print("x =", np.around(x.value))
def main(show): # generate data np.random.seed(243) m, n = 5, 1 n_outliers = 1 eta = 0.1 alpha = 0.5 A = np.random.randn(m, n) x_true = np.random.randn(n) b = A @ x_true + 1e-1 * np.random.randn(m) b[np.random.choice(np.arange(m), replace=False, size=n_outliers)] *= -1. # alternating x_alternating = cp.Variable(n) objective = 0.0 for i in range(m): objective += sccf.minimum(cp.square(A[i]@x_alternating-b[i]), alpha) objective += eta * cp.sum_squares(x_alternating) prob = sccf.Problem(objective) prob.solve() # solve relaxed problem x_relaxed = cp.Variable(n) z = [cp.Variable(n) for _ in range(m)] s = cp.Variable(m) objective = 0.0 constraints = [0 <= s, s <= 1] for i in range(m): objective += cp.quad_over_lin(A[i, :] @ z[i] - b[i] * s[i], s[i]) + (1.0 - s[i]) * alpha + \ eta / m * (cp.quad_over_lin(x_relaxed - z[i], 1.0 - s[i]) + eta / m * cp.quad_over_lin(z[i], s[i])) prob = cp.Problem(cp.Minimize(objective), constraints) result = prob.solve(solver=cp.MOSEK) # alternating w/ relaxed initialization x_alternating_perspective = cp.Variable(n) x_alternating_perspective.value = x_relaxed.value objective = 0.0 for i in range(m): objective += sccf.minimum(cp.square(A[i]@x_alternating_perspective-b[i]), alpha) objective += eta * cp.sum_squares(x_alternating_perspective) prob = sccf.Problem(objective) prob.solve(warm_start=True) # brute force evaluate function and perspective xs = np.linspace(-5, 5, 100) f = np.sum(np.minimum(np.square(A * xs - b[:, None]), alpha), axis=0) + eta*xs**2 f_persp = [] for x in xs: z = [cp.Variable(n) for _ in range(m)] s = cp.Variable(m) objective = 0.0 constraints = [0 <= s, s <= 1] for i in range(m): objective += cp.quad_over_lin(A[i, :] @ z[i] - b[i] * s[i], s[i]) + (1.0 - s[i]) * alpha + \ eta / m * (cp.quad_over_lin(x - z[i], 1.0 - s[i]) + eta / m * cp.quad_over_lin(z[i], s[i])) prob = cp.Problem(cp.Minimize(objective), constraints) result = prob.solve(solver=cp.MOSEK) f_persp.append(result) def find_nearest(array, value): array = np.asarray(array) idx = (np.abs(array - value)).argmin() return idx # plot latexify(fig_width=6, fig_height=4) plt.plot(xs, f, '-', label="$L(x)$", c='k') plt.plot(xs, f_persp, '--', label="perspective", c='k') plt.plot(x_alternating.value[0], ) plt.scatter(x_alternating.value[0], f[find_nearest(xs, x_alternating.value[0])], marker='o', label="sccf (no init)", c='k') plt.scatter(x_alternating_perspective.value[0], f[find_nearest(xs, x_alternating_perspective.value[0])], marker='*', label="sccf (persp init)", c='k') plt.legend() plt.xlabel("$x$") plt.savefig("figs/perspective.pdf") if show: plt.show()
def main(show=False): margin = .05 # margin for drawing box initial_pos = 1 final_pos = 1 n = 100 all_pos = np.linspace(0, 1, n) # Complicated lane example box_size = .18 box_pos = [.2, .5, .8] box_orientation = [-1, 1, -1] x = cp.Variable(n) cons = [x[0] == initial_pos, -2 <= x, x <= 2, x[-1] == -1] obj = 0.0 for i, pos in enumerate(all_pos): obj += sccf.minimum(cp.square(x[i] + 1), 1) obj += sccf.minimum(cp.square(x[i] - 1), 1) for b_pos, b_or in zip(box_pos, box_orientation): if b_pos <= pos and pos <= b_pos + box_size: cons.append(x[i] >= 0 if b_or > 0 else x[i] <= 0) for idx, weight in enumerate([10, 1, .1]): obj += weight * cp.sum_squares(cp.diff(x, k=idx + 1)) prob = sccf.Problem(obj, cons) tic = time.time() result = prob.solve() toc = time.time() print("lane change 2:", obj.value) print("time:", toc - tic) print("iters:", result["iters"]) latexify(fig_width=7, fig_height=2) plt.plot(all_pos * 100, x.value, c='black') plt.ylim(-2, 2) for pos, orientation in zip(box_pos, box_orientation): plt.gca().add_patch( Rectangle((pos * 100, .25 if orientation < 0 else -1.75), (box_size - margin) * 100, 1.5, facecolor='none', edgecolor='k')) plt.axhline(0, ls='--', c='k') plt.savefig("figs/lane_changing.pdf") if show: plt.show() # Lower bound obj = 0 z_top = [cp.Variable(n) for _ in range(n)] z_bottom = [cp.Variable(n) for _ in range(n)] x = cp.Variable(n) cons = [x[0] == initial_pos, -2 <= x, x <= 2, x[-1] == -1] lam_top = cp.Variable(n) lam_bottom = cp.Variable(n) cons.append(0 <= lam_top) cons.append(0 <= lam_bottom) cons.append(lam_top <= 1) cons.append(lam_bottom <= 1) for z, lam in zip(z_top + z_bottom, lam_top + lam_bottom): cons.append(z[0] == initial_pos * lam) cons.append(-2 * lam <= z) cons.append(z <= 2 * lam) cons.append(z[-1] == -1 * lam) for i, pos in enumerate(all_pos): obj += cp.quad_over_lin(z_top[i][i] + lam_top[i], lam_top[i]) + (1 - lam_top[i]) obj += cp.quad_over_lin(z_bottom[i][i] - lam_bottom[i], lam_bottom[i]) + (1 - lam_bottom[i]) for b_pos, b_or in zip(box_pos, box_orientation): if b_pos <= pos and pos <= b_pos + box_size: for z in z_top + z_bottom + [x]: cons.append(z[i] >= 0 if b_or > 0 else z[i] <= 0) for idx, weight in enumerate([10, 1, .1]): for z, lam in zip(z_top + z_bottom, lam_top + lam_bottom): obj += weight * cp.quad_over_lin(cp.diff(z, k=idx + 1), lam) / (2 * n) obj += weight * cp.quad_over_lin(cp.diff(x - z, k=idx + 1), 1 - lam) / (2 * n) prob = cp.Problem(cp.Minimize(obj), cons) obj_value = prob.solve(solver=cp.MOSEK) print("lane change lower bound:", obj_value) # MICP obj = 0 z_top = [cp.Variable(n) for _ in range(n)] z_bottom = [cp.Variable(n) for _ in range(n)] x = cp.Variable(n) cons = [x[0] == initial_pos, -2 <= x, x <= 2, x[-1] == -1] lam_top = cp.Variable(n, boolean=True) lam_bottom = cp.Variable(n, boolean=True) for z, lam in zip(z_top + z_bottom, lam_top + lam_bottom): cons.append(z[0] == initial_pos * lam) cons.append(-2 * lam <= z) cons.append(z <= 2 * lam) cons.append(z[-1] == -1 * lam) for i, pos in enumerate(all_pos): obj += cp.quad_over_lin(z_top[i][i] + lam_top[i], lam_top[i]) + (1 - lam_top[i]) obj += cp.quad_over_lin(z_bottom[i][i] - lam_bottom[i], lam_bottom[i]) + (1 - lam_bottom[i]) for b_pos, b_or in zip(box_pos, box_orientation): if b_pos <= pos and pos <= b_pos + box_size: for z in z_top + z_bottom + [x]: cons.append(z[i] >= 0 if b_or > 0 else z[i] <= 0) for idx, weight in enumerate([10, 1, .1]): for z, lam in zip(z_top + z_bottom, lam_top + lam_bottom): obj += weight * cp.quad_over_lin(cp.diff(z, k=idx + 1), lam) / (2 * n) obj += weight * cp.quad_over_lin(cp.diff(x - z, k=idx + 1), 1 - lam) / (2 * n) prob = cp.Problem(cp.Minimize(obj), cons) import sys while True: answer = input( "Are you sure you would like to solve the MICP (y/n) ").lower() if answer == "y": break elif answer == "n": return else: print("Invalid answer.") continue obj_value = prob.solve(solver=cp.MOSEK, verbose=True) print("global optimum:", obj_value)