n <- 5 # number of transmitters and receivers
sigma <- rep(0.5, n) # noise power at the receiver i
p_min <- rep(0.1, n) # minimum power at the transmitter i
p_max <- rep(5, n) # maximum power at the transmitter i
sinr_min <- 0.2 # threshold SINR for each receiver
# Path gain matrix
G <- matrix(
c(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),
nrow = 5, ncol = 5, byrow = TRUE
)Power Control
Introduction
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\) transmitters, each transmitting 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 interference-plus-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^{\min}\), and the \(P_i\) are bounded between \(P_i^{\min}\) and \(P_i^{\max}\). This gives the problem
\[ \begin{array}{ll} \mbox{minimize} & P_1 + \cdots + P_n \\ \mbox{subject to} & P_i^{\min} \leq P_i \leq P_i^{\max}, \\ & 1/S^{\min} \geq \frac{\sigma_i + \sum_{k \neq i} G_{ik}P_k}{G_{ii}P_i}. \end{array} \]
Problem Data
Problem Formulation
p <- Variable(n, pos = TRUE)
objective <- Minimize(sum_entries(p))
## For each receiver, compute interference-plus-noise and inverse SINR
inverse_sinr <- lapply(1:n, function(i) {
## Interference from all other transmitters
others <- setdiff(1:n, i)
interf <- Reduce(`+`, lapply(others, function(k) G[i, k] * p[k]))
S_i <- sigma[i] + interf
## Inverse SINR = (noise + interference) / signal
S_i / (G[i, i] * p[i])
})
sinr_constraints <- lapply(inverse_sinr, function(inv) inv <= 1 / sinr_min)
constraints <- c(list(p >= p_min, p <= p_max), sinr_constraints)
problem <- Problem(objective, constraints)
cat("Is problem DGP?", is_dgp(problem), "\n")Is problem DGP? TRUE
Solution
result <- psolve(problem, gp = TRUE)
check_solver_status(problem)
cat("Optimal total power:", result, "\n")
cat("Optimal power levels:", value(p), "\n")Optimal total power: 0.5534431
Optimal power levels: 0.1100843 0.1078223 0.1153666 0.1111531 0.1090168
We can verify that all the SINR constraints are active at the optimal solution. The inverse SINR values should all be equal to \(1/S^{\min}\) at the optimum:
for (i in 1:n) {
cat("Inverse SINR for receiver", i, ":", value(inverse_sinr[[i]]), "\n")
}Inverse SINR for receiver 1 : 5
Inverse SINR for receiver 2 : 5
Inverse SINR for receiver 3 : 5
Inverse SINR for receiver 4 : 5
Inverse SINR for receiver 5 : 5
Session Info
R version 4.5.3 (2026-03-11)
Platform: aarch64-apple-darwin20
Running under: macOS Tahoe 26.3.1
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
time zone: America/Los_Angeles
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] CVXR_1.8.1
loaded via a namespace (and not attached):
[1] slam_0.1-55 cli_3.6.5 knitr_1.51 ECOSolveR_0.6.1
[5] rlang_1.1.7 xfun_0.56 clarabel_0.11.2 otel_0.2.0
[9] gurobi_13.0-1 Rglpk_0.6-5.1 highs_1.12.0-3 cccp_0.3-3
[13] scs_3.2.7 S7_0.2.1 jsonlite_2.0.0 backports_1.5.0
[17] rprojroot_2.1.1 htmltools_0.5.9 Rmosek_11.1.1 gmp_0.7-5.1
[21] piqp_0.6.2 rmarkdown_2.30 grid_4.5.3 evaluate_1.0.5
[25] fastmap_1.2.0 yaml_2.3.12 compiler_4.5.3 codetools_0.2-20
[29] htmlwidgets_1.6.4 Rcpp_1.1.1 here_1.0.2 osqp_1.0.0
[33] lattice_0.22-9 digest_0.6.39 checkmate_2.3.4 Matrix_1.7-4
[37] tools_4.5.3
References
- Boyd, S., Kim, S.-J., Vandenberghe, L., Hassibi, A. (2007). A Tutorial on Geometric Programming. Optimization and Engineering, 8(1), 67–127.