def test_non_psd(self): """Test error when P is symmetric but not definite. """ P = np.array([[1, 0], [0, -1]]) x = cvxpy.Variable(2,1) with self.assertRaises(Exception) as cm: cvxpy.quad_form(x,P) self.assertEqual(str(cm.exception), "P has both positive and negative eigenvalues.")
def test_non_symmetric(self): """Test error when P is constant and not symmetric. """ P = np.array([[1, 2], [3, 4]]) x = cvxpy.Variable(2,1) with self.assertRaises(Exception) as cm: cvxpy.quad_form(x,P) self.assertEqual(str(cm.exception), "P is not symmetric.")
def discretized_optimal_control(A, B, C, x0, y_d, r=0, tf=30.0, n=31): # tf is the duration of a trial, in seconds # n is number of time steps # can redefine n = tf/tr # # r is a scalar that weights against using large control inputs # probably set r to zero, or remove expR from problem # Q is a matrix that weights against error in state # reference may be assumed to be zero xdim = A.shape[0] udim = B.shape[1] # R=r.T .dot(r) Q = C.T.dot(C) t = np.linspace(0.0, tf, n) dt = t[1] - t[0] subn = 100 Aint = np.eye(xdim) Bint = np.zeros((xdim, udim)) for i in range(0, subn): Aint += (1.0 / subn) * dt * A.dot(Aint) Bint += (1.0 / subn) * dt * Aint.dot(B) A = cvx.Constant(A) Aint = cvx.Constant(Aint) B = cvx.Constant(B) Bint = cvx.Constant(Bint) Q = cvx.Constant(Q) # R=cvx.Constant(R) x0 = cvx.Constant(x0) x = cvx.Variable(xdim, n) u = cvx.Variable(udim, n) dt = cvx.Constant(dt) expQ = cvx.quad_form(x[:, 0], Q) # expR=cvx.quad_form(u[:,0],R) physical_constraints = [x[:, 0] == x0] # for i in range(1,n): # expQ+=cvx.quad_form(x[:,i],Q) # put x - x_desired here # constraint=x[:,i] == Aint*x[:,i-1]+Bint*u[:,i-1] # physical_constraints.append(constraint) for i in range(1, n): expQ += cvx.quad_form(x[:, i], Q) # put x - x_desired here # or make a matrix x_desired expQ += -2 * y_d[i] * C * x[:, i] + y_d[i] * y_d[i] # could try with x_desired # expR+=cvx.quad_form(u[:,i],R) # can remove this if r=0 constraint = x[:, i] == Aint * x[:, i - 1] + Bint * u[:, i - 1] # constraint=x[:,i] == x[:,i-1]+dt*(A*x[:,i-1]+B*u[:,i-1]) physical_constraints.append(constraint) obj = cvx.Minimize(expQ) # obj=cvx.Minimize(expQ+expR) physical_constraints.append(u >= MIN_FORCE) # we added this physical_constraints.append(u <= MAX_FORCE) # set this prob = cvx.Problem(obj, physical_constraints) return prob.solve(), t, x, u # u.values is what I want
def linear_mpc_control(xref, xbar, x0, dref): """ linear mpc control xref: reference point xbar: operational point x0: initial state dref: reference steer angle """ x = cvxpy.Variable((NX, T + 1)) u = cvxpy.Variable((NU, T)) cost = 0.0 constraints = [] for t in range(T): cost += cvxpy.quad_form(u[:, t], R) if t != 0: cost += cvxpy.quad_form(xref[:, t] - x[:, t], Q) A, B, C = get_linear_model_matrix( xbar[2, t], xbar[3, t], dref[0, t]) constraints += [x[:, t + 1] == A * x[:, t] + B * u[:, t] + C] if t < (T - 1): cost += cvxpy.quad_form(u[:, t + 1] - u[:, t], Rd) constraints += [cvxpy.abs(u[1, t + 1] - u[1, t]) <= MAX_DSTEER * DT] cost += cvxpy.quad_form(xref[:, T] - x[:, T], Qf) constraints += [x[:, 0] == x0] constraints += [x[2, :] <= MAX_SPEED] constraints += [x[2, :] >= MIN_SPEED] constraints += [cvxpy.abs(u[0, :]) <= MAX_ACCEL] constraints += [cvxpy.abs(u[1, :]) <= MAX_STEER] prob = cvxpy.Problem(cvxpy.Minimize(cost), constraints) prob.solve(solver=cvxpy.ECOS, verbose=False) if prob.status == cvxpy.OPTIMAL or prob.status == cvxpy.OPTIMAL_INACCURATE: ox = get_nparray_from_matrix(x.value[0, :]) oy = get_nparray_from_matrix(x.value[1, :]) ov = get_nparray_from_matrix(x.value[2, :]) oyaw = get_nparray_from_matrix(x.value[3, :]) oa = get_nparray_from_matrix(u.value[0, :]) odelta = get_nparray_from_matrix(u.value[1, :]) else: print("Error: Cannot solve mpc..") oa, odelta, ox, oy, oyaw, ov = None, None, None, None, None, None return oa, odelta, ox, oy, oyaw, ov
def test_numpy_scalars(self): n = 6 eps = 1e-6 cvxopt.setseed(10) P0 = cvxopt.normal(n, n) eye = cvxopt.spmatrix(1.0, range(n), range(n)) P0 = P0.T * P0 + eps * eye print P0 P1 = cvxopt.normal(n, n) P1 = P1.T*P1 P2 = cvxopt.normal(n, n) P2 = P2.T*P2 P3 = cvxopt.normal(n, n) P3 = P3.T*P3 q0 = cvxopt.normal(n, 1) q1 = cvxopt.normal(n, 1) q2 = cvxopt.normal(n, 1) q3 = cvxopt.normal(n, 1) r0 = cvxopt.normal(1, 1) r1 = cvxopt.normal(1, 1) r2 = cvxopt.normal(1, 1) r3 = cvxopt.normal(1, 1) slack = cp.Variable() # Form the problem x = cp.Variable(n) objective = cp.Minimize( 0.5*cp.quad_form(x,P0) + q0.T*x + r0 + slack) constraints = [0.5*cp.quad_form(x,P1) + q1.T*x + r1 <= slack, 0.5*cp.quad_form(x,P2) + q2.T*x + r2 <= slack, 0.5*cp.quad_form(x,P3) + q3.T*x + r3 <= slack, ] # We now find the primal result and compare it to the dual result # to check if strong duality holds i.e. the duality gap is effectively zero p = cp.Problem(objective, constraints) primal_result = p.solve() # Note that since our data is random, we may need to run this program multiple times to get a feasible primal # When feasible, we can print out the following values print x.value # solution lam1 = constraints[0].dual_value lam2 = constraints[1].dual_value lam3 = constraints[2].dual_value print type(lam1) P_lam = P0 + lam1*P1 + lam2*P2 + lam3*P3 q_lam = q0 + lam1*q1 + lam2*q2 + lam3*q3 r_lam = r0 + lam1*r1 + lam2*r2 + lam3*r3 dual_result = -0.5*q_lam.T*P_lam*q_lam + r_lam print dual_result[0,0] self.assertEquals(intf.size(dual_result), (1,1))
def solve_problem(weights): x = np.diag(np.arange(x_size)) s = np.diag(np.arange(weights_size)) factor_betas = np.arange(weights_size * x_size).reshape([weights_size, x_size]) risk = cvx.quad_form(weights * factor_betas, x) + cvx.quad_form(weights, s) constaints = optimal_holdings._get_constraints(weights, factor_betas, risk) obj = cvx.Maximize([0, 1, 5, -1] * weights) prob = cvx.Problem(obj, constaints) prob.solve(max_iters=500) return np.asarray(weights.value).flatten()
def discretized_optimal_control_end(A, B, C, r, x0, Ce, xde, tf=1.0, n=100): """ this is a function I had to mess up a bit to make work """ """ this function returns the discretized input signal which optimally fulfils a quadratic performance index with a terminal cost on the state """ """ my modification, which I don't really know how to standardize to proper programming form is to include an inequality on a seemingly arbitrary component of the state vector this component represent one row of the A matrix and approximates a constraint that the height should always decrease at least 1.7 ft/second """ xdim = A.shape[0] udim = B.shape[1] R = r.T.dot(r) Q = C.T.dot(C) Qe = Ce.T.dot(Ce) t = np.linspace(0.0, tf, n) dt = t[1] - t[0] subn = 100 Aint = np.eye(xdim) Bint = np.zeros((xdim, udim)) for i in range(0, subn): Aint += (1.0 / subn) * dt * A.dot(Aint) Bint += (1.0 / subn) * dt * Aint.dot(B) A = cvx.Constant(A) Aint = cvx.Constant(Aint) B = cvx.Constant(B) Bint = cvx.Constant(Bint) Q = cvx.Constant(Q) Qe = cvx.Constant(Qe) R = cvx.Constant(R) x0 = cvx.Constant(x0) xde = cvx.Constant(xde) x = cvx.Variable(xdim, n) u = cvx.Variable(udim, n) dt = cvx.Constant(dt) expQ = cvx.quad_form(x[:, 0], Q) expR = cvx.quad_form(u[:, 0], R) physical_constraints = [x[:, 0] == x0] for i in range(1, n): expQ += cvx.quad_form(x[:, i], Q) expR += cvx.quad_form(u[:, i], R) constraint = x[:, i] == Aint * x[:, i - 1] + Bint * u[:, i - 1] # constraint=x[:,i] == x[:,i-1]+dt*(A*x[:,i-1]+B*u[:,i-1]) physical_constraints.append(constraint) physical_constraints.append(-1.0 * x[1, i] + 2.21 * x[3, i] <= -1.7) obj = cvx.Minimize(dt * expR + cvx.quad_form(x[:, -1] - xde, Qe)) prob = cvx.Problem(obj, physical_constraints) return prob.solve(), t, x, u
def q3(): def K(x1,x2): return (1+ np.inner(x1[:-1],x2[:-1]))**2 Q = np.zeros((len(data),len(data))) for i in range(len(data)): for j in range(len(data)): Q[i,j]= data[i,-1]*data[j,-1]*K(data[i],data[j]) alpha = cvx.Variable(len(data)) obj = cvx.Minimize(0.5*cvx.quad_form(alpha,Q)-cvx.sum_entries(alpha)) constraint = [cvx.sum_entries(cvx.mul_elemwise(data[:,-1],alpha)) == 0, alpha>=0] prob = cvx.Problem(obj,constraint) prob.solve() ret = alpha.value svid = next(i for i,x in enumerate(ret) if x>1e-5) b = data[svid,-1] - sum(ret[i,0]*data[i,-1]*K(data[i],data[svid]) for i in range(len(data)) if ret[i,0]>1e-5) def getvalue(X): XX = np.append(X,[-1]) return sum(ret[i,0]*data[i,-1]*K(XX,data[i]) for i in range(len(data))) + b ks = [(i,j,i**2,j**2) for j in range(10) for i in range(10)] vs = [getvalue(k[:2]) for k in ks] lr = lm.LinearRegression() lr.fit(ks,vs) print ret print lr.coef_*9,lr.intercept_*9
def test_robust_regression(self): # # Compare cvxpy solutions to cvxopt ground truth # from cvxpy import (matrix, variable, program, minimize, huber, sum, leq, geq, square, norm2, ones, zeros, quad_form) tol_exp = 5 # Check solution to within 5 decimal places m, n = self.m, self.n A = matrix(self.A) b = matrix(self.b) # Method 1: using huber directly x = variable(n) p = program(minimize(sum(huber(A*x - b, 1.0)))) p.solve(True) np.testing.assert_array_almost_equal( x.value, self.xh, tol_exp) # Method 2: solving the dual QP x = variable(n) u = variable(m) v = variable(m) p = program(minimize(0.5*quad_form(u, 1.0) + sum(v)), [geq(u, 0.0), leq(u, 1.0), geq(v, 0.0), leq(A*x - b, u + v), geq(A*x - b, -u - v)]) p.solve(True) np.testing.assert_array_almost_equal( x.value, self.xh, tol_exp)
def test_least_squares_plot_cost_ests(self, A, b, P, q, r, x, num_replications_list, alpha, fn): # Estimate the true objective value stoch_objf = cvx.sum_squares(A*x-b) fhatmeans, fhatvars, fhatucbs, fhatlcbs = [], [], [], [] for num_replications in num_replications_list: print "Averaging [%d] times the obj. vals. at a candidate point of SAAs with 1 Monte Carlo sample to the stochastic least squares objective." % num_replications (fhatmean, fhatvar, fhatucb, fhatlcb) = self.unconstr_diag.est_cost(stoch_objf, num_replications, alpha) fhatmeans.append(fhatmean) fhatvars.append(fhatvar) fhatucbs.append(fhatucb) fhatlcbs.append(fhatlcb) # Compute the true objective value print "Evaluating the true stochastic least squares objective value at a candidate point." fstar = (cvx.quad_form(x,P) - 2*x.T*q + r).value fstars = np.tile( fstar, len(num_replications_list) ) # Make plots print "Plotting results to [" + fn + "] (on a linear/log scale)." fig, ax = plt.subplots() plt.rc("text", usetex=True) ax.plot( num_replications_list, fhatmeans, "-", label=r"$\hat{f}_{0,N}(x)$", color="blue", lw=self.linewidth ) ax.fill_between( num_replications_list, fhatucbs, fhatlcbs, facecolor="lightskyblue", alpha=0.5 ) ax.plot( num_replications_list, fstars, "-", label=r"$f_0(x)$", color="crimson", lw=self.linewidth ) ax.legend(loc="upper right", fontsize=self.fontsize) ax.set_xlabel(r"\# samples $N$", fontsize=self.fontsize) ax.set_xscale("log") for label in (ax.get_xticklabels() + ax.get_yticklabels()): label.set_fontsize(self.fontsize_axis) fig.savefig(fn, bbox_inches="tight") print "All done." # Return return (fhatmeans, fhatvars, fstars)
def solve_sparse(self, y, w, x_mask=None): assert y.ndim == 1 and w.ndim == 1 and y.shape == w.shape assert w.shape[0] == self.n x = cp.Variable(np.count_nonzero(x_mask)) inv_mask = np.logical_not(x_mask) term1 = cp.square(cp.norm(x-y[x_mask])) term2 = self.c * cp.norm1(cp.diag(w[x_mask]) * x) objective = cp.Minimize(term1 + term2) constraints = [cp.quad_form(x, self.B[np.ix_(x_mask, x_mask)]) <= 1] problem = cp.Problem(objective, constraints) result = problem.solve(solver=cp.SCS) if problem.status != cp.OPTIMAL: warnings.warn(problem.status) if problem.status not in (cp.OPTIMAL, cp.OPTIMAL_INACCURATE, cp.UNBOUNDED_INACCURATE): raise ValueError(problem.status) out = np.zeros(self.n) x = np.asarray(x.value).flatten() out[x_mask] = x return out
def main(): TARGET = 0 y = [] x = [] for line in open("features.train"): vec = line.strip().split() x.append([float(vec[1]),float(vec[2])]) if int(float(vec[0])) == TARGET: y.append(1) else: y.append(-1) Q = np.empty((len(x),len(x))) p = [-1] * len(x) for i in range(0,len(x)): for j in range(0,len(x)): Q[i,j] = y[i]*y[j] * K(x[i],x[j]) alpha = cp.Variable(len(x)) C = 0.01 objective = cp.Minimize(0.5 * cp.quad_form(alpha,Q) + cp.sum_entries(cp.mul_elemwise(p,alpha))) constraints = [cp.sum_entries(cp.mul_elemwise(y,alpha)) == 0] for i in range(0,len(x)): constraints.append(alpha[i]>=0) prob = cp.Problem(objective, constraints) prob.solve() print "sum(alpha)=",sum(alpha.value) #choose any support vector (z,y) to calculate the b print "status:", prob.status print "optimal value", prob.value
def main(): TARGET = 0 y = [] x = [] for line in open("features.train"): vec = line.strip().split() x.append([float(vec[1]),float(vec[2])]) if int(float(vec[0])) == TARGET: y.append(1) else: y.append(-1) w = cp.Variable(2) b = cp.Variable() Q = np.identity(2) xi = cp.Variable(len(x)) C = 0.01 objective = cp.Minimize(0.5 * cp.quad_form(w,Q) + C * cp.sum_entries(xi)) constraints = [] for i in range(0,len(x)): constraints.append(y[i]*(cp.conv(x[i],w) + b) >= 1 - xi[i]) constraints.append(xi[i]>=0) prob = cp.Problem(objective, constraints) prob.solve() print "w=",sum([ item**2 for item in w.value]) #choose any support vector (z,y) to calculate the b print "b=",y[1] - np.dot(w.value, x[1]) print "status:", prob.status print "optimal value", prob.value
def main(): x = [[1,0],[0,1],[0,-1],[-1,0],[0,2],[0,-2],[-2,0]] y = [-1, -1, -1, 1, 1, 1, 1] Q = np.empty((7,7)) for i in range(0,7): for j in range(0,7): Q[i,j] = y[i]*y[j]*K(x[i],x[j]) p = np.array([-1] * 7) alpha = cp.Variable(7) objective = cp.Minimize(0.5 * cp.quad_form(alpha, Q) + cp.sum_entries(cp.mul_elemwise(p, alpha))) constraints = [cp.sum_entries(cp.mul_elemwise(y,alpha)) == 0] for i in range(0,7): constraints.append(alpha[i]>=0) prob = cp.Problem(objective, constraints) prob.solve() z = [[1,math.sqrt(2)*x1, math.sqrt(2)*x2, x1 ** 2, x2 ** 2] for (x1,x2) in x] w = [0] * 5 for i in range(0,7): w += np.dot(float(alpha.value[i]) * y[i], z[i]) print "w=",sum(w) #choose any support vector (z,y) to calculate the b print "b=",y[1] - np.dot(w, z[1]) print "status:", prob.status print "optimal value", prob.value print alpha.value print sum(alpha.value)
def solve_problem(Q, c, verbose=False): u = cvx.Variable(c.size) obj = cvx.Minimize(cvx.quad_form(u, Q)+cvx.sum_entries(c.T*u)) prob = cvx.Problem(obj) prob.solve(verbose=verbose, solver=cvx.SCS) uval = np.array(u.value).ravel() return np.reshape(uval, (c.size // DIM_SIZE, DIM_SIZE))
def project_cvxpy(v, B): x = cp.Variable(len(v)) cp.Problem(cp.Minimize( cp.norm2(x - v) ** 2 ), [cp.quad_form(x, B) <= 1]).solve() sol = np.asarray(x.value)[:, 0] return sol
def test_sparse_quad_form(self): """Test quad form with a sparse matrix. """ Q = cvxopt.spdiag([1,1]) x = cvxpy.Variable(2,1) cost = cvxpy.quad_form(x,Q) prob = cvxpy.Problem(cvxpy.Minimize(cost), [x == [1,2]]) self.assertAlmostEqual(prob.solve(), 5)
def test_non_symmetric(self): """Test when P is constant and not symmetric. """ P = np.array([[2, 2], [3, 4]]) x = cvxpy.Variable(2) cost = cvxpy.quad_form(x, P) prob = cvxpy.Problem(cvxpy.Minimize(cost), [x == [1, 2]]) self.assertAlmostEqual(prob.solve(), 28)
def test_singular_quad_form(self): """Test quad form with a singular matrix. """ # Solve a quadratic program. np.random.seed(1234) for n in (3, 4, 5): for i in range(5): # construct a random 1d finite distribution v = np.exp(np.random.randn(n)) v = v / np.sum(v) # construct a random positive definite matrix A = np.random.randn(n, n) Q = np.dot(A, A.T) # Project onto the orthogonal complement of v. # This turns Q into a singular matrix with a known nullspace. E = np.identity(n) - np.outer(v, v) / np.inner(v, v) Q = np.dot(E, np.dot(Q, E.T)) observed_rank = np.linalg.matrix_rank(Q) desired_rank = n-1 yield assert_equal, observed_rank, desired_rank for action in 'minimize', 'maximize': # Look for the extremum of the quadratic form # under the simplex constraint. x = cvxpy.Variable(n) if action == 'minimize': q = cvxpy.quad_form(x, Q) objective = cvxpy.Minimize(q) elif action == 'maximize': q = cvxpy.quad_form(x, -Q) objective = cvxpy.Maximize(q) constraints = [0 <= x, cvxpy.sum_entries(x) == 1] p = cvxpy.Problem(objective, constraints) p.solve() # check that cvxpy found the right answer xopt = x.value.A.flatten() yopt = np.dot(xopt, np.dot(Q, xopt)) assert_allclose(yopt, 0, atol=1e-3) assert_allclose(xopt, v, atol=1e-3)
def solveQPobj(c, A, Q, bxl, bxu, bcl, bcu): """ Solves a convex program with a quadratic objective maximize c'*x - (1/2) x'*Q*x subject to bcl <= A*x <= bcu bxl <= x <= bxu """ x = cvx.Variable(len(c)) constraints = [A*x <= bcu, bcl <= A*x, bxl <= x, x <= bxu] objective = x.T*c - 0.5 * cvx.quad_form(x, Q) ccu.maximize(objective=objective, constraints=constraints) return x.value
def solveMarkowitzConstraint(c, A, Q, qc, v, x0, bxl, bxu, bcl, bcu): """ Solves a convex program with a quadratic constraint and linear abs penalty maximize c'*x - v'*abs{x - x0} subject to bcl <= A*x <= bcu bxl <= x <= bxu sqrt(x'*Q*x) <= qc """ x = cvx.Variable(len(c)) constraints = [A*x <= bcu, bcl <= A*x, bxl <= x, x <= bxu, cvx.quad_form(x, Q) <= qc*qc] objective = x.T*c - cvx.abs(x - x0).T*v ccu.maximize(objective=objective, constraints=constraints) return x.value
def solveQPcon(c, A, Q, qc, bxl, bxu, bcl, bcu): """ Solves a convex program with a quadratic constraint maximize c'*x subject to bcl <= A*x <= bcu bxl <= x <= bxu sqrt(x'*Q*x) <= qc """ x, constraints = __weight(c, bxl, bxu) constraints = constraints + __constraint(x, A, bcl, bcu) + [cvx.quad_form(x, Q) <= qc*qc] objective = x.T*c ccu.maximize(objective=objective, constraints=constraints) return x.value
def cvxpy_test(): numpy.random.seed(1) n = 10 mu = numpy.abs(numpy.random.randn(n, 1)) Sigma = numpy.random.randn(n, n) Sigma = Sigma.T.dot(Sigma) w = cvxpy.Variable(n) gamma = cvxpy.Parameter(sign='positive') ret = mu.T*w risk = cvxpy.quad_form(w, Sigma) print "csvpy test >>> ", cvxpy.Problem(cvxpy.Maximize(ret - gamma*risk), [cvxpy.sum_entries(w) == 1, w >= 0])
def add_dynamic_cost(self, P, q, r): """Add term to cost of the form u' * P(x, t) * u + q(x, t)' * u + r(x, t) Inputs: Quadratic term, P: numpy array * float -> numpy array Linear term, q: numpy array * float -> numpy array Constant term, r: numpy array * float -> float """ if P is None: P = lambda x, t: zeros((self.m, self.m)) if q is None: q = lambda x, t: zeros(self.m) if r is None: r = lambda x, t: 0 cost = lambda x, t: quad_form(self.u, P(x, t)) + q(x, t) * self.u + r(x, t) self.dynamic_costs.append(cost)
def run_opt(self): """ Run optimization for the minimum risk portfolio that exceeds a required minimum return """ w = cp.Variable(self.n) rets = self.mu.T @ w risk = cp.quad_form(w, self.sigma) # cp.norm(w, 1) <= 2, sum of |x_i| must be <= 2 # requires return greater than min_ret # fully invested portfolio constraints_ls = [ cp.sum(w) == 1, rets >= self.min_ret, cp.norm(w, 1) <= 2 ] prob = cp.Problem(cp.Minimize(risk), constraints_ls) prob.solve() return w.value
def solve_without_round(self): w_c = cvx.Variable(self.alpha_series.size, nonneg=True) # 目标函数 bm = np.array(self.benchmark_weight_series.values) objective = cvx.Minimize(cvx.quad_form((w_c - bm), self.asset_ret_cov)) # 股票权重 + 现金权重 = 1 sum_cons = cvx.sum(w_c) == 1 # 预期收益率约束 ret = np.array(self.alpha_series.values) ret_cons = ret.T * w_c >= self.target_return constraints = [sum_cons, ret_cons] asset_lower_bounds_cons = w_c >= self.asset_lower_boundary_series.values asset_upper_bounds_cons = w_c <= self.asset_upper_boundary_series.values if asset_lower_bounds_cons is not None: constraints += [asset_lower_bounds_cons] if asset_upper_bounds_cons is not None: constraints += [asset_upper_bounds_cons] for el in constraints: assert (el.is_dcp()) prob = cvx.Problem(objective, constraints) prob.solve(solver=cvx.MOSEK, verbose=False) # 返回结果 after_trade_value = self.market_value * pd.Series( index=self.alpha_series.index, data=w_c.value) after_trade_volume = np.round(after_trade_value / self.current_price) after_trade_volume.fillna(0, inplace=True) after_trade_ratio = after_trade_value / after_trade_value.sum() exante_risk = np.sqrt( after_trade_ratio.T.dot(self.asset_ret_cov).dot(after_trade_ratio)) exante_return = after_trade_ratio.T.dot(ret) exante_sr = exante_return / exante_risk solve_result = { "expected_weight": after_trade_ratio, "expected_holding": after_trade_value, "expected_volume": after_trade_volume, "exante_return": exante_return, "exante_risk": exante_risk, "exante_sr": exante_sr, "opt_status": prob.status } return solve_result
def test_yield_constr_cost_min(self): # Create problem data. n = 10 c = numpy.random.randn(n) P, q, r = numpy.eye(n), numpy.random.randn(n), numpy.random.randn() mu, Sigma = numpy.zeros(n), 0.1 * numpy.eye(n) omega = NormalRandomVariable(mu, Sigma) m, eta = 100, 0.95 # Create and solve optimization problem. x = cp.Variable(n) yield_constr = (prob( cp.quad_form(x + omega, P) + (x + omega).T * q + r >= 0, m) <= 1 - eta) p = cp.Problem(cp.Minimize(x.T * c), [yield_constr]) p.solve(solver=cp.ECOS) self.assert_feas(p)
def mpc_lqr(x0, N, A, B, QQ, RR, ysp, usp): """return the MPC control input using a linear system""" B = B.T nx, nu = B.shape QN = QQ P = scipy.sparse.block_diag([ scipy.sparse.kron(scipy.sparse.eye(N), QQ), QN, scipy.sparse.kron(scipy.sparse.eye(N), RR) ]) q = numpy.hstack([ numpy.kron(numpy.ones(N), -QQ @ ysp), -QN @ ysp, numpy.kron(numpy.ones(N), -RR @ usp) ]) # Handling of mu_(k+1) = A @ mu_k + B @ u_k temp1 = scipy.sparse.block_diag( [scipy.sparse.kron(scipy.sparse.eye(N + 1), -numpy.eye(nx))]) temp2 = scipy.sparse.block_diag( [scipy.sparse.kron(scipy.sparse.eye(N + 1, k=-1), A)]) AA = temp1 + temp2 temp1 = scipy.sparse.vstack( [numpy.zeros([nx, N * nu]), scipy.sparse.kron(scipy.sparse.eye(N), B)]) AA = scipy.sparse.hstack([AA, temp1]) bb = numpy.hstack([-x0, numpy.zeros(N * nx)]) n = max(q.shape) x = cvxpy.Variable(n) P = cvxpy.Constant(P) objective = cvxpy.Minimize(0.5 * cvxpy.quad_form(x, P) + q * x) constraints = [AA * x == bb] prob = cvxpy.Problem(objective, constraints) prob.solve(solver='MOSEK') if not prob.status.startswith("optimal"): print(prob.status) print(prob.is_qp()) return None res = numpy.array(x.value).reshape((n, )) return res[(N + 1) * nx:(N + 1) * nx + nu]
def passive_solve2(x_len, x_ori, r_hat, cov, eps, gamma, cash=1): x = cvxpy.Variable(x_len) # optimization vector variable x0 = cvxpy.Parameter(x_len) r = cvxpy.Parameter(x_len) # placeholder for vector c gamma = cvxpy.Parameter(nonneg=True) risk = cvxpy.quad_form(x, cov) # obj = cvxpy.Minimize(cvxpy.norm(x - x0, 2) + gamma*risk) #define objective function obj = cvxpy.Minimize(cvxpy.sum_squares(x - x0) + gamma * risk) #define objective function x0.value = x_ori prob = cvxpy.Problem(obj, [cvxpy.sum(x) == 1, x.T @ r >= eps, x >= 0]) # prob = cvxpy.Problem(obj, [cvxpy.sum(x) == 1, x.T @ r >= eps]) r.value = r_hat gamma.value = gamma0 prob.solve(solver='ECOS') # solve the problem x_opt = x.value # the optimal variable return x_opt
def fit(self, Xs, Xt): """ Computes the KMM weights based on given training and test samples. Parameters ---------- Xs : array_like of shape (n_samples_source, n_features) Source domain data points Xt : array_like of shape (n_samples_target, n_features) Target domain data points Returns ------- self fitted weighter """ ms = Xs.shape[0] mt = Xt.shape[0] # Check if the source and target data points only have one feature if len(Xs.shape) == 1: Xs = np.reshape(Xs, (ms, 1)) Xt = np.reshape(Xt, (mt, 1)) K = self._kernel(Xs, Xs) kappa = (float(ms) / float(mt)) * np.sum(self._kernel(Xs, Xt), axis=1) G = np.concatenate((np.identity(ms), -np.identity(ms), np.ones( (1, ms)), -np.ones((1, ms)))) h = np.concatenate( (np.repeat(self._B, ms), np.zeros(ms), np.array([ms * (1 + self._epsilon), ms * (self._epsilon - 1)]))) x = cv.Variable(ms) objective = cv.Minimize((1 / 2) * cv.quad_form(x, K) - kappa.T @ x) constraints = [G @ x <= h] cv.Problem(objective, constraints).solve(solver="ECOS") self.weights_ = x.value return self
def test_custom_convex_objective_market_neutral_efficient_risk(): target_risk = 0.19 ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.efficient_risk(target_risk, market_neutral=True) built_in = ef.weights # Recreate the market-neutral efficient_risk optimiser using this API ef = EfficientFrontier(*setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)) ef.add_constraint(lambda x: cp.sum(x) == 0) ef.add_constraint( lambda x: cp.quad_form(x, ef.cov_matrix) <= target_risk**2) ef.convex_objective(lambda x: -x @ ef.expected_returns, weights_sum_to_one=False) custom = ef.weights np.testing.assert_allclose(built_in, custom, atol=1e-7)
def get_optimal_weights(covariance_returns, index_weights, scale=2.0): """ Find the optimal weights. Parameters ---------- covariance_returns : 2 dimensional Ndarray The covariance of the returns index_weights : Pandas Series Index weights for all tickers at a period in time scale : int The penalty factor for weights the deviate from the index Returns ------- x : 1 dimensional Ndarray The solution for x """ assert len(covariance_returns.shape) == 2 assert len(index_weights.shape) == 1 assert covariance_returns.shape[0] == covariance_returns.shape[ 1] == index_weights.shape[0] #TODO: Implement function m = covariance_returns.shape[0] # x variables (to be found with optimization) x = cvx.Variable(m) #portfolio variance, in quadratic form portfolio_variance = cvx.quad_form(x, covariance_returns) distance_to_index = cvx.norm(x - index_weights) objective = cvx.Minimize(portfolio_variance + scale * distance_to_index) #constraints constraints = [x >= 0, sum(x) == 1] #use cvxpy to solve the objective problem = cvx.Problem(objective, constraints) min_value = problem.solve() #retrieve the weights of the optimized portfolio x_values = x.value return x_values
def generate_weights(self, inputs: Dict): n_assets = inputs['n_assets'] mean = inputs['mean'] cov = inputs['cov'] weights = cp.Variable(n_assets) risk = cp.quad_form(weights, cov) if self.use_mean: gamma = cp.Constant(self.gamma) ret = mean.T * weights problem = cp.Problem(cp.Maximize(ret - gamma * risk), [cp.sum(weights) == 1, weights >= 0]) else: problem = cp.Problem(cp.Minimize(risk), [cp.sum(weights) == 1, weights >= 0]) problem.solve() return weights.value
def solveMarkowitzConstraint(c, A, Q, qc, v, x0, bxl, bxu, bcl, bcu): """ Solves a convex program with a quadratic constraint and linear abs penalty maximize c'*x - v'*abs{x - x0} subject to bcl <= A*x <= bcu bxl <= x <= bxu sqrt(x'*Q*x) <= qc """ x = cvx.Variable(len(c)) constraints = [ A * x <= bcu, bcl <= A * x, bxl <= x, x <= bxu, cvx.quad_form(x, Q) <= qc * qc ] objective = x.T * c - cvx.abs(x - x0).T * v ccu.maximize(objective=objective, constraints=constraints) return x.value
def ex_ante_tracking_error(w, cov_matrix, benchmark_weights): """ Calculate the (square of) the ex-ante Tracking Error, i.e :math:`\\(w - w_b)^T \\Sigma (w-w_b)`. :param w: asset weights in the portfolio :type w: np.ndarray OR cp.Variable :param cov_matrix: covariance matrix :type cov_matrix: np.ndarray :param benchmark_weights: asset weights in the benchmark :type benchmark_weights: np.ndarray :return: value of the objective function OR objective function expression :rtype: float OR cp.Expression """ relative_weights = w - benchmark_weights tracking_error = cp.quad_form(relative_weights, cov_matrix) return _objective_value(w, tracking_error)
def update_D_hat_cvxpy(t, W_hat, X_hat, A_t, B_t, x_sum, alpha_sum, eps): ''' use cvxpy to update D ''' n_hat, k_cluster = W_hat.shape D_hat = (X_hat @ W_hat) D = cvx.Variable(shape=D_hat.shape) # constraint = [W >= 0, W <= 1] constraint = [D >= 0, D <= 1] # T1 = cvx.trace(B_t * W.T * X_hat.T) # tmp = X_hat * W * A_t * W.T * X_hat.T # T2 = cvx.trace(X_hat * W * A_t * W.T * X_hat.T) # T2 = cvx.trace(W.T * W) XW = D T1 = cvx.sum(cvx.multiply(B_t, XW)) m_dim = XW.shape[0] print('m_dim = ', m_dim) quad_sum = 0 for idx in range(m_dim): quad_sum += cvx.quad_form(XW[idx, :].T, A_t) T2 = quad_sum # tmp = XW * (A_t.T) # T2 = cvx.sum(cvx.multiply(XW, tmp)) print('is T1 cvx? ', T1.is_convex()) print('is T2 cvx? ', T2.is_convex()) # print('tmp shape:', tmp.shape) print('T2 shape:', T2.shape) obj = cvx.Minimize(1 / t * (1 / 2 * x_sum - T1 + 1 / 2 * T2 + alpha_sum)) # obj = cvx.Minimize((1/t) * (1/2 * x_sum - cvx.trace(B_t * W.T * X_hat.T) # + 1/2 * cvx.trace(X_hat * W * A_t * W.T * X_hat.T) + alpha_sum)) prob = cvx.Problem(obj, constraint) # prob.solve(solver = cvx.CVXOPT) prob.solve(solver=cvx.OSQP) # if prob.status != cvx.OPTIMAL: # raise Exception('CVX solver did not converge!') print('residual norm = {:.06f}'.format(prob.value)) D_hat_new = D.value return D_hat_new
def forward_conic_format_solve_problem(Q, q, G, h, A, b, sol_opt=cp.SCS, verbose=False): """ :param Q: :param q: :param G: :param h: :param A: :param b: :param sol_opt: :param verbose: :return: """ nz, neq, nineq = q.shape[0], A.shape[0] if A is not None else 0, G.shape[0] x_ = cp.Variable(nz) # print("x size {}, num of ineq {}".format(x_.size, nineq)) obj = cp.Minimize(0.5 * cp.quad_form(x_, Q) + q.T * x_) eqCon = A * x_ == b if neq > 0 else None if nineq > 0: slacks = cp.Variable(nineq) # define slack variables ineqCon = G * x_ + slacks == h slacksCon = slacks >= 0 else: ineqCon = slacks = slacksCon = None cons = [constraint for constraint in [eqCon, ineqCon, slacksCon] if constraint is not None] prob = cp.Problem(obj, cons) # The current form only accept cvx problem and scs solver option A, b, c, cone_dims = scs_data_from_cvxpy_problem(prob, sol_opt) # @note: after converting into scs conic form # The A, b, c here represents general form of : # min c^T x # s.t. Ax + s = b # s \in \mathcal{K} # where K is a cone # ---------------------------- # calculate time # ---------------------------- # start = time.perf_counter() x, y, s, derivative, adjoint_derivative = diffcp_cprog.solve_and_derivative( A, b, c, cone_dims, eps=1e-5) # end = time.perf_counter() # print("[DIFFCP] Compute solution and set up derivative: %.4f s." % (end - start)) return x, y, s, derivative, adjoint_derivative, A, b, c
def solve_complete(x, obj_no_lap_reg, constraints, L, Ds, SOLVER='OSQP'): ''' Solves normal multi-period portfolio problem ''' (n, p) = x.shape x = cvx.reshape(x, (n * p, 1)) lap_reg = cvx.quad_form(x, L) / 2 optval = cvx.Problem(cvx.Minimize(sum(obj_no_lap_reg) + lap_reg), constraints).solve(solver=SOLVER, parallel=False, eps_abs=1e-3, eps_rel=1e-3, max_iter=1000) #if objectives are slightly off, decrease eps_abs and eps_rel. improves accuracy but decreases speed of convergence. return x.value, optval
def minimize(kernel, y, C, pi_): N = kernel.shape[0] a = cvx.Variable(N) obj = cvx.Minimize((1 / 2) * cvx.quad_form(a, kernel) - cvx.sum_entries(a)) constraints = [a >= 0, a <= cvx.mul_elemwise(C, pi_), cvx.sum_entries(a.T * y) == 0] prob = cvx.Problem(obj, constraints) prob.solve() print("status:", prob.status) return [x[0, 0] for x in a.value]
def risk_adj_return(x, s, Fs, Rs, Ds, mus, n, T, L, gamma=1): ''' Compute objective function to portfolio problem ''' obj = 0 CASH = np.eye(1, n, n - 1).T for ii in range(T): if ii == 0: obj += s.T.dot(cvx.neg(x[ii*n:(ii+1)*n]).value) + gamma*(cvx.sum_squares(Fs[ii].T.dot(x[ii*n:(ii+1)*n])).value +\ Rs[ii]*cvx.sum_squares(x[ii*n:(ii+1)*n]).value) - np.dot(mus[ii].T,x[ii*n:(ii+1)*n]) +Ds[0] * cvx.sum_squares(x[:n]).value - (Ds[0] * CASH).T.dot(x[:n]) else: obj += s.T.dot(cvx.neg(x[ii*n:(ii+1)*n]).value) + gamma*(cvx.sum_squares(Fs[ii].T.dot(x[ii*n:(ii+1)*n])).value +\ Rs[ii]*cvx.sum_squares(x[ii*n:(ii+1)*n]).value) - np.dot(mus[ii].T,x[ii*n:(ii+1)*n]) return float(obj + 0.5 * cvx.quad_form(x, L).value)
def forward_single_d_conic_solve_Filter(Q, q, G, h, A, b, d, epsilon, xi, delta=0.01, T=48, p=None, sol_opt=cp.CVXOPT, verbose=False): nz, neq, nineq = q.shape[0], A.shape[0] if A is not None else 0, G.shape[0] if p.shape == (T,): p = np.expand_dims(p, 1) # convert the price into a column vector if d.shape == (T,): d = np.expand_dims(d, 1) if verbose: print("\n inside the cvx np filter :", T, nz) print([part.shape for part in [Q, q, G, h, A, b]]) x_ = cp.Variable(nz) # GAMMA = cp.Semidef(T) GAMMA = cp.Variable(rows=T, cols=T) # assert T == nz / 3 # print("x size {}, num of ineq {}".format(x_.size, nineq)) term1 = GAMMA * epsilon + d obj = cp.Minimize(0.5 * cp.quad_form(x_, Q) + q.T * x_ + p.T * cp.pos(term1) + cp.pos(cp.norm(GAMMA, "nuc") - xi)) eqCon = A * x_ == b if neq > 0 else None prob_ineqCon = [cp.norm(GAMMA[:, i], 2) <= (d[i, 0] / abs(ut.function_normal_cdf_inv(delta))) for i in range(T)] # ut.function_normal_cdf_inv(delta) eqCon_sdp = None # convert the SDP constraint in the objective, # eqCon_sdp = cp.norm(GAMMA, "nuc") == xi if nineq > 0: slacks = cp.Variable(nineq) # define slack variables ineqCon = G * x_ + slacks == h slacksCon = slacks >= 0 else: ineqCon = slacks = slacksCon = None cons_collected = [eqCon, eqCon_sdp, ineqCon] + prob_ineqCon + [slacksCon] cons = [constraint for constraint in cons_collected if constraint is not None] prob = cp.Problem(obj, cons) A_, b_, c_, cone_dims = scs_data_from_cvxpy_problem(prob, cp_SCS=sol_opt) x, y, s, derivative, adjoint_derivative = diffcp_cprog.solve_and_derivative( A_, b_, c_, cone_dims, eps=1e-5) # end = time.perf_counter() # print("[DIFFCP] Compute solution and set up derivative: %.4f s." % (end - start)) return x, y, s, derivative, adjoint_derivative, A_, b_, c_
def _genModelConstraints(self, x, prepared_constraints, prepared_option): CVXConstraints = [] for iType, iConstraint in prepared_constraints.items(): if iType == "Box": CVXConstraints.extend([ x <= iConstraint["ub"].flatten(), x >= iConstraint["lb"].flatten() ]) elif iType == "LinearIn": CVXConstraints.append( iConstraint["A"] @ x <= iConstraint["b"].flatten()) elif iType == "LinearEq": CVXConstraints.append( iConstraint["Aeq"] @ x == iConstraint["beq"].flatten()) elif iType == "Quadratic": for jSubConstraint in iConstraint: if "X" in jSubConstraint: jSigma = np.dot( np.dot(jSubConstraint["X"], jSubConstraint["F"]), jSubConstraint["X"].T) + np.diag( jSubConstraint["Delta"].flatten()) jSigma = (jSigma + jSigma.T) / 2 elif "Sigma" in jSubConstraint: jSigma = jSubConstraint["Sigma"] CVXConstraints.append( cvx.quad_form(x, jSigma) + jSubConstraint["Mu"].T @ x <= jSubConstraint["q"]) elif iType == "L1": for jSubConstraint in iConstraint: CVXConstraints.append( cvx.norm(x - jSubConstraint["c"].flatten(), p=1) <= jSubConstraint["l"]) elif iType == "Pos": for jSubConstraint in iConstraint: CVXConstraints.append( cvx.pos(x - jSubConstraint["c_pos"].flatten()) <= jSubConstraint["l_pos"]) elif iType == "Neg": for jSubConstraint in iConstraint: CVXConstraints.append( cvx.neg(x - jSubConstraint["c_neg"].flatten()) <= jSubConstraint["l_neg"]) elif iType == "NonZeroNum": raise __QS_Error__("不支持的约束条件: '非零数目约束'!") return CVXConstraints
def solve_quadratic_program(self, P, q): """ Solve the quadratic program optimization problem. This function solved the quadratic program to minimize the objective function f(x) = 1/2(x*P*x)+q*x subject to the additional constraints Gx <= h Where P, q are given and G,h are computed to ensure that x represents a probability vector and subject to honesty constraints if required Args: P (matrix): A matrix representing the P component of the objective function q (list): A vector representing the q component of the objective function Returns: list: The solution of the quadratic program (represents probabilities) Additional information: This method is the only place in the code where we rely on the cvxpy library should we consider another library, only this method needs to change. """ import cvxpy P = numpy.array(P).astype(float) q = numpy.array(q).astype(float).T n = len(q) # G and h constrain: # 1) sum of probs is less then 1 # 2) All probs bigger than 0 # 3) Honesty (measured using fidelity, if given) G_data = [[1] * n] + [([-1 if i == k else 0 for i in range(n)]) for k in range(n)] h_data = [1] + [0] * n if self.fidelity_data is not None: G_data.append(self.fidelity_data['coefficients']) h_data.append(self.fidelity_data['goal']) G = numpy.array(G_data).astype(float) h = numpy.array(h_data).astype(float) x = cvxpy.Variable(n) prob = cvxpy.Problem( cvxpy.Minimize((1 / 2) * cvxpy.quad_form(x, P) + q.T @ x), [G @ x <= h]) prob.solve() return x.value
def step(self): super(NewtonBundle, self).step() # Find lambda (warm start with previous iteration) self.lam_var.value = self.cur_lam prob = cp.Problem(cp.Minimize(cp.quad_form(self.p,np.eye(self.x_dim))), self.constraints+[self.lam_var @ self.dfS == self.p]) prob.solve(warm_start=True, solver=cp.GUROBI) self.lam_cur = self.lam_var.value # Solve optimality conditions for x self.delta = np.sqrt(prob.value) # Solve optimality conditions for new x A = np.zeros([self.x_dim+1+self.k,self.x_dim+1+self.k]) top_left = np.einsum('s,sij->ij',self.lam_cur,self.d2fS) A[0:self.x_dim,0:self.x_dim]=top_left A[0:self.x_dim,self.x_dim:(self.x_dim+self.k)] = self.dfS.T A[self.x_dim,self.x_dim:(self.x_dim+self.k)] = 1 A[(self.x_dim+1):, 0:self.x_dim] = self.dfS A[(self.x_dim+1):,-1] = -1 b = np.zeros(self.x_dim+1+self.k) b[0:self.x_dim] = np.einsum('s,sij,sj->i',self.lam_cur,self.d2fS,self.S) b[self.x_dim] = 1 b[self.x_dim+1:] = np.einsum('ij,ij->i',self.dfS,self.S) - self.fS self.cur_x = (np.linalg.pinv(A)@b)[0:self.x_dim] # Get current gradient and hessian oracle = self.objective.call_oracle(self.cur_x) self.cur_fx = oracle['f'] # k_sub = np.argmax(np.linalg.norm(self.S, axis=1)) k_sub = np.argmin(self.lam_cur) self.S[k_sub, :] = self.cur_x self.fS[k_sub] = self.cur_fx self.dfS[k_sub, :] = oracle['df'] self.d2fS[k_sub, :, :] = oracle['d2f'] # Update current iterate value and update the bundle self.update_params()
def _min_volatility(self, covariance, num_assets): """ Compute minimum volatility portfolio allocation. :param covariance: (pd.Dataframe) Covariance dataframe of asset returns :param num_assets: (int) Number of assets in the portfolio :return: (np.array, float) Portfolio weights and risk value """ weights = cp.Variable(num_assets) weights.value = np.array([1 / num_assets] * num_assets) risk = cp.quad_form(weights, covariance) # Optimisation objective and constraints allocation_objective = cp.Minimize(risk) allocation_constraints = [ cp.sum(weights) == 1, ] if isinstance(self.weight_bounds, tuple): allocation_constraints.extend( [ weights >= self.weight_bounds[0], weights <= min(self.weight_bounds[1], 1) ] ) if isinstance(self.weight_bounds, dict): asset_indices = list(range(num_assets)) for asset_index in asset_indices: lower_bound, upper_bound = self.weight_bounds.get(asset_index, (0, 1)) allocation_constraints.extend( [ weights[asset_index] >= lower_bound, weights[asset_index] <= min(upper_bound, 1) ] ) # Define and solve the problem problem = cp.Problem( objective=allocation_objective, constraints=allocation_constraints ) problem.solve(warm_start=True) if weights.value is None: raise ValueError('No optimal set of weights found.') return weights.value, risk.value ** 0.5
def efficient_return(self, target_return, market_neutral=False): """ Calculate the 'Markowitz portfolio', minimising volatility for a given target return. :param target_return: the desired return of the resulting portfolio. :type target_return: float :param market_neutral: whether the portfolio should be market neutral (weights sum to zero), defaults to False. Requires negative lower weight bound. :type market_neutral: bool, optional :raises ValueError: if ``target_return`` is not a positive float :raises ValueError: if no portfolio can be found with return equal to ``target_return`` :return: asset weights for the Markowitz portfolio :rtype: dict """ if not isinstance(target_return, float) or target_return < 0: raise ValueError("target_return should be a positive float") if target_return > self.expected_returns.max(): raise ValueError( "target_return must be lower than the largest expected return") self._objective = objective_functions.portfolio_variance( self._w, self.cov_matrix) ret = objective_functions.portfolio_return(self._w, self.expected_returns, negative=False) self.objective = cp.quad_form(self._w, self.cov_matrix) ret = self.expected_returns.T @ self._w for obj in self._additional_objectives: self._objective += obj self._constraints.append(ret >= target_return) # The equality constraint is either "weights sum to 1" (default), or # "weights sum to 0" (market neutral). if market_neutral: self._market_neutral_bounds_check() self._constraints.append(cp.sum(self._w) == 0) else: self._constraints.append(cp.sum(self._w) == 1) self._solve_cvxpy_opt_problem() return dict(zip(self.tickers, self.weights))
def solve_qp(P, Q, G, H): r""" Helper function to set up and solve the Quadratic Program (QP) in CVXPY. A QP problem has the following form: minimize 1/2 x' P x + Q' x subject to G x <= H Here the QP solver is based on CVXPY and uses OSQP. Parameters ---------- P : ndarray n x n matrix for the primal QP objective function. Q : ndarray n x 1 matrix for the primal QP objective function. G : ndarray m x n matrix for the inequality constraint. H : ndarray m x 1 matrix for the inequality constraint. Returns ------- x : array Optimal solution to the QP problem. """ try: import cvxpy as cvx except ImportError: raise ImportError( "Using MSMT in pyAFQ requires the the cvxpy package. " "You can install it using `pip install cvxpy` or `pip " "install pyAFQ[msmt]`.") x = cvx.Variable(Q.shape[0]) P = cvx.Constant(P) objective = cvx.Minimize(0.5 * cvx.quad_form(x, P) + Q * x) constraints = [G * x <= H] # setting up the problem prob = cvx.Problem(objective, constraints) try: prob.solve() opt = np.array(x.value).reshape((Q.shape[0],)) except (cvx.error.SolverError, cvx.error.DCPError) as e: opt = np.empty((Q.shape[0],)) opt[:] = np.NaN return opt
def compute(self, today, assets,out,returns): print("------------------------------- Markowitz:",today) #print ("Markowitz factor:",returns) gamma = cvx.Parameter(sign="positive") gamma.value = 1 # gamma is a Parameter that trades off riskmanager and return. #returns = np.nan_to_num(returns.T) # time,stock to stock,time #print ("Markowitz factor2:",returns) #cov_mat = np.cov(returns) #Sigma = cov_mat Sigma = np.nan_to_num(returns) Sigma = Sigma.T.dot(Sigma) #print ("Markowitz factor2:",Sigma) ######################################################## w = cvx.Variable(len(assets)) risk = cvx.quad_form(w, Sigma) mu = np.array([self.target_ret] * len(assets)) expected_return = np.reshape(mu,(-1, 1)).T * w # w is a vector of stock holdings as fractions of total assets. objective = cvx.Maximize(expected_return - gamma * risk) # Maximize(expected_return - expected_variance) ######################################################### constraints = [cvx.sum_entries(w) == 0] # dollar-neutral long/short sector_dist = {} idx = 0 class_nos = get_sectors_no(assets) #print ("Markowitz class_nos:",class_nos) for classid in class_nos: if classid not in sector_dist: _ = [] sector_dist[classid] = _ sector_dist[classid].append(idx) idx += 1 #print("sector size :", len(sector_dist),idx,sector_dist) for k, v in sector_dist.items(): constraints.append(cvx.sum_entries(w[v]) < (1 / len(sector_dist) + self.max_sector_exposure)) constraints.append(cvx.sum_entries(w[v]) >= (1 / len(sector_dist) - self.max_sector_exposure)) prob = cvx.Problem(objective, constraints) prob.solve() if prob.status != 'optimal': print ("Optimal failed %s , do nothing" % prob.status) return None #print ("Markowit weight",np.squeeze(np.asarray(w.value))) # Remo out[:] = np.squeeze(np.asarray(w.value)) #每行中的列1
def get_dual_variables_cvxpy_solver( H, q, lb, ub, A_eq=None, A_ineq=None, b_eq=None, b_ineq=None, ): """ Solves the same problem as hopfiel with cvxpy :param H: :param q: :param lb: :param ub: :param binary_indicator: :param solver: cvxpy solver :return: """ n = q.shape[0] x = cvx.Variable(n) constraints = [lb <= x, x <= ub] if A_eq is not None and b_eq is not None: constraints += [A_eq * x - b_eq == 0] if A_ineq is not None and b_ineq is not None: n_ineq = len(b_ineq) s = cvx.Variable(n_ineq) constraints += [A_ineq * x - b_ineq - s == 0, s <= 0] objective = 1 / 2 * cvx.quad_form(x, H) + q.T * x objective = cvx.Minimize(objective) problem = cvx.Problem(objective, constraints) problem.solve() if A_eq is not None and b_eq is not None and A_ineq is not None and b_ineq is not None: return constraints[2].dual_value, constraints[3].dual_value elif (A_ineq is not None and b_ineq is not None) or (A_eq is not None and b_eq is not None): return constraints[2].dual_value else: return None
def _fit_cvxpy(self, K, D, time): import cvxpy n_pairs = D.shape[0] a = cvxpy.Variable(n_pairs) alpha = cvxpy.Parameter(sign="positive", value=self.alpha) P = D.dot(D.dot(K).T).T obj = cvxpy.Minimize(0.5 * cvxpy.quad_form(a, P) - cvxpy.sum_entries(a)) constraints = [a >= 0., a <= alpha] prob = cvxpy.Problem(obj, constraints) prob.solve(verbose=self.verbose) coef = a.value.T.A sv = numpy.flatnonzero(coef > 1e-5) return coef, sv
def test_optimize_twoasset_portfolio(fn): varA, varB, rAB = 0.1, 0.05, 0.25 cov = np.sqrt(varA) * np.sqrt(varB) * rAB x = cvx.Variable(2) P = np.array([[varA, cov], [cov, varB]]) quad_form = cvx.quad_form(x, P) objective = cvx.Minimize(quad_form) constraints = [sum(x) == 1] problem = cvx.Problem(objective, constraints) min_value = problem.solve() xA, xB = x.value fn_inputs = {'varA': varA, 'varB': varB, 'rAB': rAB} fn_correct_outputs = OrderedDict([('xA', xA), ('xB', xB)]) assert_output(fn, fn_inputs, fn_correct_outputs)
def test_QCQP_compute_fhat(self, q0, r0, x, num_replications, alpha): n = q0.size fhats = [] for i in range(num_replications): A0 = np.random.randn(n, n) P0 = A0.T.dot(A0) fhat = (0.5 * cvx.quad_form(x, P0) + x.T.dot(q0) + r0).value fhats.append(fhat) fhat_avg = np.mean(fhats) fhat_se = scipy.stats.sem(fhats) critval = UnconstrDiagnostics.get_critval(alpha) fhat_ucb = fhat_avg + critval * fhat_se fhat_lcb = fhat_avg - critval * fhat_se return (fhat_avg, fhat_ucb, fhat_lcb)
def maximum_Sharpe(means, cov): y = cvx.Variable(len(means)) expected_return = y.T @ means expected_vol = cvx.quad_form(y, cov) utility = expected_vol objective = cvx.Minimize(utility) constraints = [ expected_return == 1, # fully-invested ] problem = cvx.Problem(objective, constraints) problem.solve() return np.array( y.value.flat).round(4), expected_return.value, expected_vol.value
def mpc_control(x0): x = cvxpy.Variable(nx, T + 1) u = cvxpy.Variable(nu, T) A, B = get_model_matrix() cost = 0.0 constr = [] for t in range(T): cost += cvxpy.quad_form(x[:, t + 1], Q) cost += cvxpy.quad_form(u[:, t], R) constr += [x[:, t + 1] == A * x[:, t] + B * u[:, t]] constr += [x[:, 0] == x0] prob = cvxpy.Problem(cvxpy.Minimize(cost), constr) start = time.time() prob.solve(verbose=False) elapsed_time = time.time() - start print("calc time:{0} [sec]".format(elapsed_time)) if prob.status == cvxpy.OPTIMAL: ox = get_nparray_from_matrix(x.value[0, :]) dx = get_nparray_from_matrix(x.value[1, :]) theta = get_nparray_from_matrix(x.value[2, :]) dtheta = get_nparray_from_matrix(x.value[3, :]) ou = get_nparray_from_matrix(u.value[0, :]) return ox, dx, theta, dtheta, ou
def test_QCQP_compute_pstarhat(self, q0, r0, q1, r1, x, num_replications, num_samples, alpha): n = q0.size pstarhats = [] for k in range(num_replications): obj, constr = 0, 0 for l in range(num_samples): A0 = np.random.randn(n,n) P0 = A0.T.dot(A0) obj += (1.0/num_samples) * ( 0.5*cvx.quad_form(x, P0) + x.T*q0 + r0 ) A1 = np.random.randn(n,n) P1 = A1.T.dot(A1) constr += (1.0/num_samples) * ( 0.5*cvx.quad_form(x, P1) + x.T*q1 + r1 ) pstarhat = self.constr_diag.est_optval(HowEstConstrOptVal.LAGRANGIAN, obj, [constr <= 0]) pstarhats.append(pstarhat) pstarhat_avg = np.mean(pstarhats) pstarhat_se = scipy.stats.sem(pstarhats) critval = UnconstrDiagnostics.get_critval(alpha, HowGetCritVal.T, num_replications-1) pstarhat_ucb = pstarhat_avg + critval*pstarhat_se pstarhat_lcb = pstarhat_avg - critval*pstarhat_se return (pstarhat_avg, pstarhat_ucb, pstarhat_lcb)
def cvxpy_solve_qp(P, q, G=None, h=None, A=None, b=None, initvals=None, solver=None): """ Solve a Quadratic Program defined as: minimize (1/2) * x.T * P * x + q.T * x subject to G * x <= h A * x == b calling a given solver using the CVXPY <http://www.cvxpy.org/> modelling language. Parameters ---------- P : array, shape=(n, n) Primal quadratic cost matrix. q : array, shape=(n,) Primal quadratic cost vector. G : array, shape=(m, n) Linear inequality constraint matrix. h : array, shape=(m,) Linear inequality constraint vector. A : array, shape=(meq, n), optional Linear equality constraint matrix. b : array, shape=(meq,), optional Linear equality constraint vector. initvals : array, shape=(n,), optional Warm-start guess vector (not used). solver : string, optional Solver name in ``cvxpy.installed_solvers()``. Returns ------- x : array, shape=(n,) Solution to the QP, if found, otherwise ``None``. """ if initvals is not None: print("CVXPY: note that warm-start values are ignored by wrapper") n = q.shape[0] x = Variable(n) P = Constant(P) # see http://www.cvxpy.org/en/latest/faq/ objective = Minimize(0.5 * quad_form(x, P) + q * x) constraints = [] if G is not None: constraints.append(G * x <= h) if A is not None: constraints.append(A * x == b) prob = Problem(objective, constraints) prob.solve(solver=solver) x_opt = array(x.value).reshape((n,)) return x_opt
def use_modeling_tool(A, B, N, Q, R, P, x0, umax=None, umin=None, xmin=None, xmax=None): """ solve MPC with modeling tool for test """ (nx, nu) = B.shape # mpc calculation x = cvxpy.Variable(nx, N + 1) u = cvxpy.Variable(nu, N) costlist = 0.0 constrlist = [] for t in range(N): costlist += 0.5 * cvxpy.quad_form(x[:, t], Q) costlist += 0.5 * cvxpy.quad_form(u[:, t], R) constrlist += [x[:, t + 1] == A * x[:, t] + B * u[:, t]] if xmin is not None: constrlist += [x[:, t] >= xmin] if xmax is not None: constrlist += [x[:, t] <= xmax] costlist += 0.5 * cvxpy.quad_form(x[:, N], P) # terminal cost if xmin is not None: constrlist += [x[:, N] >= xmin] if xmax is not None: constrlist += [x[:, N] <= xmax] prob = cvxpy.Problem(cvxpy.Minimize(costlist), constrlist) prob.constraints += [x[:, 0] == x0] # inital state constraints if umax is not None: prob.constraints += [u <= umax] # input constraints if umin is not None: prob.constraints += [u >= umin] # input constraints prob.solve(verbose=True) return x.value, u.value
def test_non_psd(self): """Test error when P is symmetric but not definite. """ P = np.array([[1, 0], [0, -1]]) x = cvxpy.Variable(2) # Forming quad_form is okay with warnings.catch_warnings(): warnings.simplefilter("ignore") cost = cvxpy.quad_form(x, P) prob = cvxpy.Problem(cvxpy.Minimize(cost), [x == [1, 2]]) with self.assertRaises(Exception) as cm: prob.solve() self.assertEqual(str(cm.exception), "Problem does not follow DCP rules.")
def solveMarkowitzObjective(c, A, Q, v, x0, bxl, bxu, bcl, bcu): """ Solves a convex program with a quadratic constraint and linear abs penalty maximize c'*x - (1/2) x'*Q*x - v'*abs{x - x0} subject to bcl <= A*x <= bcu bxl <= x <= bxu """ x = cvx.Variable(len(c)) constraints = [A*x <= bcu, bcl <= A*x, bxl <= x, x <= bxu] objective = x.T*c -0.5 * cvx.quad_form(x, Q) - cvx.abs(x - x0).T*v ccu.maximize(objective=objective, constraints=constraints, verbose=True) return x.value
def tps_fit3_cvx(x_na, y_ng, bend_coef, rot_coef, wt_n): """ Use cvx instead of just matrix multiply. Working with null space of matrices. """ if wt_n is None: wt_n = co.matrix(np.ones(len(x_na))) n,d = x_na.shape K_nn = tps_kernel_matrix(x_na) _,_,VT = nlg.svd(np.c_[x_na,np.ones((x_na.shape[0],1))].T) Nmat = VT.T[:,d+1:] rot_coefs = np.diag(np.ones(d) * rot_coef if np.isscalar(rot_coef) else rot_coef) A = cp.Variable(Nmat.shape[1],d) B = cp.Variable(d,d) c = cp.Variable(d,1) Y = co.matrix(y_ng) K = co.matrix(K_nn) N = co.matrix(Nmat) X = co.matrix(x_na) W = co.matrix(np.diag(wt_n).copy()) R = co.matrix(rot_coefs) ones = co.matrix(np.ones((n,1))) constraints = [] # For correspondences V1 = cp.Variable(n,d) constraints.append(V1 == Y-K*N*A-X*B - ones*c.T) V2 = cp.Variable(n,d) constraints.append(V2 == cp.sqrt(W)*V1) # For bending cost Q = [] # for quadratic forms for i in range(d): Q.append(cp.quad_form(A[:,i], N.T*K*N)) # For rotation cost # Element wise square root actually works here as R is diagonal and positive V3 = cp.Variable(d,d) constraints.append(V3 == cp.sqrt(R)*B) # Orthogonality constraints for bending are taken care of already because working with the null space #constraints.extend([X.T*A == 0, ones.T*A == 0]) # TPS objective objective = cp.Minimize(cp.sum_squares(V2) + bend_coef*sum(Q) + cp.sum_squares(V3)) p = cp.Problem(objective, constraints) p.solve(verbose=True) return np.array(B.value), np.squeeze(np.array(c.value)) , Nmat.dot(np.array(A.value))