I'm trying to implement a semidefinite programming problem in cvxpy. The optimization variables are complex. I'm new to cvxpy, writing a positive semidefinite constraint is not as straight as in cvx. I have read the cvxpy documentation, but I didn't understand how such constraints are expressed. My code is as shown below. I have written the same problem in cvx and would want to use cvxpy to solve the same problem.
import math
import cvxpy as cp
import numpy as np
import scipy.io as sio
import time
N = 100
ntx = 4
nrx = 4
N0 = 1 # calculate noise variance
gamma1 = np.arange(20.0, 101.0, 10)
delta = 0.0001
Power_t = np.zeros((N, len(gamma1)))
for j in range(N):
H_hat = np.sqrt(0.5)*(np.random.randn(ntx, nrx) + 1j*np.random.randn(ntx, nrx)) # CSI known at the BS
H_R = np.bmat([[np.real(H_hat), -np.imag(H_hat)],
[np.imag(H_hat), np.real(H_hat)]])
for r in range(len(gamma1)):
gamma = np.power(10, (gamma1[r]/10))
T1 = cp.Variable((nrx,nrx), hermitian = True)
T2 = cp.Variable((nrx,nrx), hermitian = True)
T3 = cp.Variable((nrx,nrx), hermitian = True)
T4 = cp.Variable((nrx,nrx), hermitian = True)
OBJ_func = cp.real(cp.trace(T1)) + cp.real(cp.trace(T2)) + cp.real(cp.trace(T3)) + cp.real(cp.trace(T4))
s = cp.Variable(nrx)
OBJ = cp.Minimize ( OBJ_func )
# Create constraints.
# Qi calculations
Q1 = T1 - gamma*(T2+T3+T4)
Q2 = T2 - gamma*(T1+T3+T4)
Q3 = T3 - gamma*(T1+T2+T4)
Q4 = T4 - gamma*(T1+T2+T3)
constr1 = cp.vstack( [ cp.reshape(cp.hstack([ H_hat[:,0].T @ Q1 @ H_hat[:, 1]- gamma*N0 - s[0]*delta, H_hat[:,0].T @ Q1]),(1, 5)),
cp.hstack([Q1 @ H_hat[:,0].reshape(-1, 1), delta*np.eye(nrx, nrx) + Q1])
] )
constr2 = cp.vstack( [ cp.reshape(cp.hstack([ H_hat[:,1].T @ Q2 @ H_hat[:, 1]- gamma*N0 - s[1]*delta, H_hat[:,1].T @ Q2]),(1, 5)),
cp.hstack([Q2 @ H_hat[:,1].reshape(-1, 1), delta*np.eye(nrx, nrx) + Q2])
] )
constr3 = cp.vstack( [ cp.reshape(cp.hstack([ H_hat[:,2].T @ Q3 @ H_hat[:, 2]- gamma*N0 - s[2]*delta, H_hat[:,2].T @ Q3]),(1, 5)),
cp.hstack([Q3 @ H_hat[:,2].reshape(-1, 1), delta*np.eye(nrx, nrx) + Q3])
] )
constr4 = cp.vstack( [ cp.reshape(cp.hstack([ H_hat[:,3].T @ Q4 @ H_hat[:, 3]- gamma*N0 - s[3]*delta, H_hat[:,3].T @ Q4]),(1, 5)),
cp.hstack([Q4 @ H_hat[:,3].reshape(-1, 1), delta*np.eye(nrx, nrx) + Q4])
] )
constr11 = []
constr21 = []
constr31 = []
constr41 = []
constr11 += [ constr1 >> 0 ]
constr21 += [ constr2 >> 0 ]
constr31 += [ constr3 >> 0 ]
constr41 += [ constr4 >> 0 ]
T11 = []
T21 = []
T31 = []
T41 = []
T11 += [ T1 >> 0 ]
T21 += [ T2 >> 0 ]
T31 += [ T3 >> 0 ]
T41 += [ T4 >> 0 ]
constraints = [constr11, constr21, constr31, constr41, T11, T21, T31, T41, s >= 0]
prob = cp.Problem(OBJ, constraints)
prob.solve(verbose=False)
Power_t[j, r] = (np.trace(T1.value) + np.trace(T2.value) + np.trace(T3.value) + np.trace(T4.value))
Power = np.sum(Power_t, 0) /(N)
plt.semilogx(delta, 10*np.log10(Power),'k-*','linewidth',2)
plt.grid
I couldn't figure out where I went wrong because it has been throwing in the error below. I will appreciate it you could help.
AttributeError: 'Problem' object has no attribute '_compute_once_variables'
During handling of the above exception, another exception occurred:
AttributeError Traceback (most recent call last)
<ipython-input-3-b34bde0c69df> in <module>()
82
83 prob = cp.Problem(OBJ, constraints)
---> 84 prob.solve(verbose=False)
85
86 Power_t[j, r] = (np.trace(T1.value) + np.trace(T2.value) + np.trace(T3.value) + np.trace(T4.value))
/usr/local/lib/python3.6/dist-packages/cvxpy/problems/problem.py in solve(self, *args, **kwargs)
288 else:
289 solve_func = Problem._solve
--> 290 return solve_func(self, *args, **kwargs)
291
292 @classmethod
/usr/local/lib/python3.6/dist-packages/cvxpy/problems/problem.py in _solve(self, solver, warm_start, verbose, parallel, gp, qcp, **kwargs)
566 solver, warm_start, verbose, **kwargs)
567
--> 568 self._construct_chains(solver=solver, gp=gp)
569 data, solving_inverse_data = self._solving_chain.apply(
570 self._intermediate_problem)
/usr/local/lib/python3.6/dist-packages/cvxpy/problems/problem.py in _construct_chains(self, solver, gp)
509
510 except Exception as e:
--> 511 raise e
512
513 def _solve(self,
/usr/local/lib/python3.6/dist-packages/cvxpy/problems/problem.py in _construct_chains(self, solver, gp)
495 try:
496 candidate_solvers = self._find_candidate_solvers(solver=solver,
--> 497 gp=gp)
498
499 self._intermediate_chain =
/usr/local/lib/python3.6/dist-packages/cvxpy/problems/problem.py in _find_candidate_solvers(self, solver, gp)
454 candidates['qp_solvers'] = [] # No QP solvers allowed
455
--> 456 if self.is_mixed_integer():
457 candidates['qp_solvers'] = [
458 s for s in candidates['qp_solvers']
/usr/local/lib/python3.6/dist-packages/cvxpy/utilities/performance_utils.py in _compute_once(self)
41 return getattr(self, attr_name)
42 except AttributeError:
---> 43 setattr(self, attr_name, func(self))
44 return getattr(self, attr_name)
45 return _compute_once
/usr/local/lib/python3.6/dist-packages/cvxpy/problems/problem.py in is_mixed_integer(self)
167 def is_mixed_integer(self):
168 return any(v.attributes['boolean'] or v.attributes['integer']
--> 169 for v in self.variables())
170
171 @perf.compute_once
/usr/local/lib/python3.6/dist-packages/cvxpy/utilities/performance_utils.py in _compute_once(self)
41 return getattr(self, attr_name)
42 except AttributeError:
---> 43 setattr(self, attr_name, func(self))
44 return getattr(self, attr_name)
45 return _compute_once
/usr/local/lib/python3.6/dist-packages/cvxpy/problems/problem.py in variables(self)
180 vars_ = self.objective.variables()
181 for constr in self.constraints:
--> 182 vars_ += constr.variables()
183 return unique_list(vars_)
184
AttributeError: 'list' object has no attribute 'variables'