#!/usr/bin/env python # coding: utf-8 # ![MOSEK ApS](https://www.mosek.com/static/images/branding/webgraphmoseklogocolor.png ) # # Optimization for multiuser communications # We consider a multiple-input multiple-output (MIMO) communication system # with $n$ transmitters and $n$ receivers. Each transmitter transmits with power $p_j$ and the # gain from transmitter $j$ to receiver $i$ is $G_{ij}$. The signal power from transmitter $i$ to receiver $i$ is then # # $$ S_i = G_{ii} p_i $$ # # and the interference is # # $$ I_i = \sum_{j\neq i} G_{ij} p_j + \sigma_i $$ # # where $\sigma_i$ is an additive noise component. In this notebook we consider different strategies for optimizing the signal-to-inference-plus-noise ratio (SINR) # # $$ s_i = \frac{G_{ii} p_i}{\sum_{j\neq i} G_{ij} p_j + \sigma_i} $$ # # with a bound on the total transmitted power $ \sum_i p_i \leq P $. # ## Minimizing total power for given SINRs # Suppose we are given lower bounds $s_i \geq \gamma_i$. We can then minimize the required power # $$ # \begin{array}{ll} # \text{minimize} & \sum_i p_i \\ # \text{subject to} & s_i \geq \gamma_i \\ # & \sum_i p_i \leq P, # \end{array} # $$ # which is equivalent to a linear optimization problem # $$ # \begin{array}{ll} # \text{minimize} & \sum_i p_i \\ # \text{subject to} & G_{ii} p_i \geq \gamma_i\left ( \sum_{j\neq i} G_{ij} p_j + \sigma_i \right ) \\ # & \sum_i p_i \leq P. # \end{array} # $$ # ## Maximizing the worst SINR # Alternatively we can maximize the smallest $s_i$, # # $$ # \begin{array}{ll} # \text{maximize} & t \\ # \text{subject to} & s_i \geq t \\ # & \sum_i p_i \leq P. # \end{array} # $$ # # Equivalently we can minimize the inverse, # # $$ # \begin{array}{ll} # \text{minimize} & t^{-1} \\ # \text{subject to} & t \left ( \sum_{j\neq i} G_{ij} p_j + \sigma_i \right ) G_{ii}^{-1} p_i^{-1} \leq 1 \\ # & \sum_i p_i \leq P, # \end{array} # $$ # # which can be rewritten as a geometric programming problem # # $$ # \begin{array}{ll} # \text{minimize} & -z\\ # \text{subject to} & # \log \left ( \sum_{j\neq i}e^{z + q_j - q_i + \log(G_{ij}/G_{ii})} + e^{z - q_i + \log(\sigma_i/G_{ii})} \right ) \leq 0\\ # & \log \left ( \sum_i e^{q_i-\log P}\right) \leq 0 # \end{array} # $$ # # with $p_i := e^{q_i}$ and $t := e^z$. To rewrite the geometric program into conic form, we note that # # $$ # \log \left( \sum_{i=1}^n e^{a_i^T x + b_i}\right) \leq 0 \qquad \Longleftrightarrow \qquad # \sum_i u_i\leq 1, \quad (u_i, 1, a_i^Tx + b_i)\in K_\text{exp}, \: i=1,\dots n. # $$ # In[1]: import sys import numpy as np from mosek.fusion import * import matplotlib.pyplot as plt # In[2]: def logsumexp(M, A, x, b): u = M.variable(A.shape[0]) M.constraint( Expr.sum(u), Domain.lessThan(1.0)) M.constraint( Expr.hstack(u, Expr.constTerm(A.shape[0], 1.0), Expr.add(Expr.mul(A, x), b)), Domain.inPExpCone()) # In[3]: def max_worst_sinr(G, P, sigma): n = G.shape[0] with Model('MAX_WORST_SINR') as M: qz = M.variable('qz', n+1) # concatenation of q and z M.objective('Objective',ObjectiveSense.Minimize,Expr.neg(qz.index(n))) for i in range(n): A = np.zeros((n,n+1)) b = np.zeros(n) for j in [k for k in range(n) if k!=i]: A[j,[i,j,n]] = [-1, 1, 1] b[j] = G[i,j]/G[i,i] A[i, [i, n]] = [-1, 1] b[i] = sigma[i]/G[i,i] # If any Gij == 0, then we filter out row j idx = np.nonzero(b)[0] logsumexp(M, A[idx,:], qz, np.log(b[idx])) logsumexp(M, np.eye(n), qz.slice(0,n), -np.log(P)*np.ones(n)) M.setLogHandler(sys.stdout) M.solve() pt = np.exp(qz.level()) return (pt[0:n], pt[n]) # In[4]: P = 0.5 G = np.array([[1.0,0.1,0.2,0.1,0.0], [0.1,1.0,0.1,0.1,0.0], [0.2,0.1,2.0,0.2,0.2], [0.1,0.1,0.2,1.0,0.1], [0.0,0.0,0.2,0.1,1.0]]) sigma = 0.01*np.ones(G.shape[0]) # In[5]: p1, t1 = max_worst_sinr(G, P, sigma) # In[6]: p1, t1 # In[7]: SINR1 = (np.diagonal(G)*p1)/(np.dot(G,p1) - np.diagonal(G)*p1 + sigma) SINR1 # ## Maximizing the best SINR # The solution to # $$ # \begin{array}{ll} # \text{maximize} & t_i \\ # \text{subject to} & s_i \leq t_i \\ # & \sum_i p_i \leq P # \end{array} # $$ # is trivial; we choose the index $k$ maximizing $P_{ii}/\sigma_i$ and take $p_k=P$ and $p_j=0,\: j\neq k$. # In[8]: def max_best_SINR(G,P,sigma): GSD = [G[i][i]/sigma[i] for i in range(G.shape[0])] P_max = max(GSD) #Thus, maximum of the best SINR is equal to... return(P_max*P) # In[9]: max_best_SINR(G,P,sigma) # ## Maximizing average SINR # We can maximize the average SINR as # $$ # \begin{array}{ll} # \text{maximize} & \sum_i t_i \\ # \text{subject to} & s_i \geq t_i \\ # & 0 \leq p_i \leq P_i \\ # & \sum_i p_i \leq P, # \end{array} # $$ # which corresponds to an intractable non-convex bilinear optimization problem. However, in the low-SINR regime, we can approximate the above problem by maximizing $\sum_i \log t_i$, or equivalently minimizing $\prod_i t_i^{-1}$: # $$ # \begin{array}{ll} # \text{minimize} & \prod_i t_i^{-1} \\ # \text{subject to} & t_i \left ( \sum_{j\neq i} G_{ij} p_j + \sigma_i \right ) G_{ii}^{-1} p_i^{-1} \leq 1 \\ # & 0 \leq p_i \leq P_i \\ # & \sum_i p_i \leq P, # \end{array} # $$ # which again corresponds to a geometric programming problem. # In[10]: def min_Geo_mean(G,P,sigma): n = G.shape[0] with Model('MIN_GEO_MEAN') as M: t = M.variable('t',n) x = M.variable('x',n) q = M.variable('q',n) logsumexp(M,np.eye(n),q,-np.log(P)*np.ones(n)) M.constraint(Expr.hstack(x,Expr.constTerm(n, 1.0),Expr.neg(t)),Domain.inPExpCone()) M.objective('Objective',ObjectiveSense.Minimize,Expr.sum(x)) for i in range(n): A = np.zeros((n,n+1)) b = np.zeros(n) for j in [k for k in range(n) if k!=i]: A[j,[i,j,n]] = [-1,1,1] b[j] = G[i,j]/G[i,i] A[i,[i,n]] = [-1,1] b[i] = sigma[i]/G[i,i] idx = np.nonzero(b)[0] logsumexp(M,A[idx,:],Expr.vstack(q,t.index(i)),np.log(b[idx])) M.setLogHandler(sys.stdout) M.solve() T = t.level() p = np.exp(q.level()) return(T,p) # In[11]: t2,p2 = min_Geo_mean(G, P, sigma) # In[12]: p2,t2 # In[13]: SINR2 = (np.diagonal(G)*p2)/(np.dot(G,p2) - np.diagonal(G)*p2 + sigma) SINR2 # # Comparing the SINR for the cases above... # In[14]: fig,ax = plt.subplots(figsize = (13,10)) bar_width = 0.35 p_num = np.arange(1,G.shape[0]+1) B1 = ax.bar(p_num,SINR1,bar_width,label = 'Max Worst SINR') B2 = ax.bar(p_num+bar_width,SINR2,bar_width,label = 'Max Average SINR') ax.set_ylabel('SINR') ax.set_xticks(p_num + bar_width/2) x_tiK = ['p{}'.format(i+1) for i in range(G.shape[0])] ax.set_xticklabels(x_tiK) ax.set_xlabel('Transmitter') ax.legend() plt.show() # Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. The **MOSEK** logo and name are trademarks of Mosek ApS. The code is provided as-is. Compatibility with future release of **MOSEK** or the `Fusion API` are not guaranteed. For more information contact our [support](mailto:support@mosek.com).