Power control¶
This example is adapted from Boyd, Kim, Vandenberghe, and Hassibi, “A Tutorial on Geometric Programming.”
The problem data is adapted from the corresponding example in CVX’s example library (Almir Mutapcic).
This example formulates and solves a power control problem for communication systems, in which the goal is to minimize the total transmitter power across n trasmitters, each trasmitting positive power levels \(P_1\), \(P_2\), \(\ldots\), \(P_n\) to \(n\) receivers, labeled \(1, \ldots, n\), with receiver \(i\) receiving signal from transmitter \(i\).
The power received from transmitter \(j\) at receiver \(i\) is \(G_{ij} P_{j}\), where \(G_{ij} > 0\) represents the path gain from transmitter \(j\) to receiver \(i\). The signal power at receiver \(i\) is \(G_{ii} P_i\), and the interference power at receiver \(i\) is \(\sum_{k \neq i} G_{ik}P_k\). The noise power at receiver \(i\) is \(\sigma_i\), and the signal to noise ratio (SINR) of the \(i\)th receiver-transmitter pair is
The transmitters and receivers are constrained to have a minimum SINR \(S^{\text{min}}\), and the \(P_i\) are bounded between \(P_i^{\text{min}}\) and \(P_i^{\text{max}}\). This gives the problem
import cvxpy as cp
import numpy as np
# Problem data
n = 5 # number of transmitters and receivers
sigma = 0.5 * np.ones(n) # noise power at the receiver i
p_min = 0.1 * np.ones(n) # minimum power at the transmitter i
p_max = 5 * np.ones(n) # maximum power at the transmitter i
sinr_min = 0.2 # threshold SINR for each receiver
# Path gain matrix
G = np.array(
[[1.0, 0.1, 0.2, 0.1, 0.05],
[0.1, 1.0, 0.1, 0.1, 0.05],
[0.2, 0.1, 1.0, 0.2, 0.2],
[0.1, 0.1, 0.2, 1.0, 0.1],
[0.05, 0.05, 0.2, 0.1, 1.0]])
p = cp.Variable(shape=(n,), pos=True)
objective = cp.Minimize(cp.sum(p))
S_p = []
for i in range(n):
S_p.append(cp.sum(cp.hstack(G[i, k]*p[k] for k in range(n) if i != k)))
S = sigma + cp.hstack(S_p)
signal_power = cp.multiply(cp.diag(G), p)
inverse_sinr = S/signal_power
constraints = [
p >= p_min,
p <= p_max,
inverse_sinr <= (1/sinr_min),
]
problem = cp.Problem(objective, constraints)
problem.is_dgp()
True
problem.solve(gp=True)
problem.value
0.9615384629119621
p.value
array([0.18653846, 0.16730769, 0.23461538, 0.19615385, 0.17692308])
inverse_sinr.value
array([5., 5., 5., 5., 5.])
(1/sinr_min)
5.0