I have a quadratic program that CVXPY rejects because of DCP error. However I am certain that my formulation (see code below) satisfies the quadratic program (I'm trying to match this). I suspect it is due to how my functions are computed; Is there a way to rewrite it such that CVXPY (their ruleset) accepts it? Thanks.
def run_QP(n, p, L, Y, X, sigma, B_prop):
# Configuring our inputs to suit LP
Y_LP = Y.flatten('F')
X_LP = np.zeros((n*L,p*L))
for l in range(L):
X_LP[n*l:n*(l+1),p*l:p*(l+1)] = X
C_LP = np.eye(p)
for l in range(L-1):
C_LP = np.concatenate((C_LP, np.eye(p)), axis=1)
one_p = np.ones(p)
# Setting the objective matrix and vector
constant = 1/(p*(sigma**2))
P = constant * (X_LP.T @ X_LP)
print('P\n',P)
I_pL = np.eye(p*L)
temp_term = -1*cp.log(B_prop[0]) * (one_p.T @ I_pL[0:p,:])
for l in range(1,L):
I_pL_trun = I_pL[p*l:p*(l+1),:]
temp_term -= cp.log(B_prop[l]) * (one_p.T @ I_pL_trun)
q = -1*constant*(Y_LP.T @ X_LP) + temp_term
# Setting the equality constraints matrix
A = np.concatenate((X_LP, C_LP), axis=0)
# Setting the equality constraints vector
b = np.concatenate((Y_LP, one_p), axis=0)
# Define and solve the CVXPY problem.
B_LP = cp.Variable(p*L)
objective = cp.Minimize((1/2)*cp.quad_form(B_LP, P) + q.T @ B_LP)
constraints = []
constraints.append(A @ B_LP == b)
problem = cp.Problem(objective, constraints)
problem.solve()
# Reconfiguring our outputs to suit pooled data
B_QP_est = problem.value
B_est = np.zeros((p,L))
for l in range(L):
B_col = B_QP_est[p*l:p*(l+1)]
B_est[:,l] = B_col
return B_est
B_bar_prob = [0.5,0.5]
L = 2
alpha = 0.5
p = 100
n = 20
sigma = 0.1
indices = np.random.choice(np.array([0, 1]), size=p, p=B_bar_prob)
B = np.eye(np.max(indices)+1)[indices]
X = binomial(1, alpha, (n, p))
Psi = normal(0, sigma, (n, L))
Y = np.dot(X, B) + Psi
B_prop = np.sum(B, axis=0) / n
B_hat = run_QP(n, p, L, Y, X, sigma, B_prop)
The error I get:
DCPError: Problem does not follow DCP rules. Specifically:
The objective is not DCP. Its following subexpressions are not:
QuadForm(var423, [[13. 7. 5. ... 0. 0. 0.]
[ 7. 10. 4. ... 0. 0. 0.]
[ 5. 4. 8. ... 0. 0. 0.]
...
[ 0. 0. 0. ... 9. 5. 5.]
[ 0. 0. 0. ... 5. 13. 6.]
[ 0. 0. 0. ... 5. 6. 10.]])