Power Control

Author

CVXPY Developers and Balasubramanian Narasimhan

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 P1,P2,,Pn to n receivers, labeled 1,,n, with receiver i receiving signal from transmitter i.

The power received from transmitter j at receiver i is GijPj, where Gij>0 represents the path gain from transmitter j to receiver i. The signal power at receiver i is GiiPi, and the interference power at receiver i is kiGikPk. The noise power at receiver i is σi, and the signal to interference-plus-noise ratio (SINR) of the i-th receiver-transmitter pair is

Si=GiiPiσi+kiGikPk.

The transmitters and receivers are constrained to have a minimum SINR Smin, and the Pi are bounded between Pimin and Pimax. This gives the problem

minimizeP1++Pnsubject toPiminPiPimax,1/Sminσi+kiGikPkGiiPi.

Problem Data

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
)

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/Smin 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.2 (2025-10-31)
Platform: aarch64-apple-darwin20
Running under: macOS Tahoe 26.3

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 datasets  utils     methods   base     

other attached packages:
[1] CVXR_1.8.0.9207

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] Rcplex_0.3-8      Rmosek_11.1.1     rprojroot_2.1.1   htmltools_0.5.9  
[21] gmp_0.7-5.1       piqp_0.6.2        rmarkdown_2.30    grid_4.5.2       
[25] evaluate_1.0.5    fastmap_1.2.0     yaml_2.3.12       compiler_4.5.2   
[29] codetools_0.2-20  htmlwidgets_1.6.4 Rcpp_1.1.1        here_1.0.2       
[33] osqp_1.0.0        lattice_0.22-9    digest_0.6.39     checkmate_2.3.4  
[37] Matrix_1.7-4      tools_4.5.2      

References

  • Boyd, S., Kim, S.-J., Vandenberghe, L., Hassibi, A. (2007). A Tutorial on Geometric Programming. Optimization and Engineering, 8(1), 67–127.