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

$$ S_i = \frac{G_{ii}P_i}{\sigma_i + \sum_{k \neq i} G_{ik}P_k}. $$

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

$$ \begin{array}{ll} \mbox{minimize} & P_1 + \cdots + P_n \\ \mbox{subject to} & P_i^{\text min} \leq P_i \leq P_i^{\text max}, \\ & 1/S^{\text min} \geq \frac{\sigma_i + \sum_{k \neq i} G_{ik}P_k}{G_{ii}P_i} \end{array}. $$

In [1]:
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 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)

In [2]:
problem.is_dgp()


Out[2]:
True

In [3]:
problem.solve(gp=True)
problem.value


Out[3]:
0.9615384629119621

In [4]:
p.value


Out[4]:
array([0.18653846, 0.16730769, 0.23461538, 0.19615385, 0.17692308])

In [5]:
inverse_sinr.value


Out[5]:
array([5., 5., 5., 5., 5.])

In [6]:
(1/sinr_min)


Out[6]:
5.0