IA_CoMP
Interference Alignment and Coordinated Multipoint
IA2/calculate_beamformers2.cpp
00001 // Copyright 2011-2013, Per Zetterberg, KTH Royal Institute of Technology
00002 // This program is free software: you can redistribute it and/or modify
00003 // it under the terms of the GNU General Public License as published by
00004 // the Free Software Foundation, either version 3 of the License, or
00005 // (at your option) any later version.
00006 //
00007 // This program is distributed in the hope that it will be useful,
00008 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 // GNU General Public License for more details.
00011 //
00012 // You should have received a copy of the GNU General Public License
00013 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00014 //
00015 
00016 #include "IA2_node.hpp"
00017 #include <itpp/itcomm.h>
00018 #include <itpp/stat/misc_stat.h>
00019 
00020 void IA2_node::calculate_beamformers(void) {
00021  
00022   // Perform the distrinuted IA algo found in "Approaching the Capacity
00023   // of Wireless Networks through Distributed Interference
00024   // Alignment", by Krishna Gomadam, Viveck R. Cadambe and
00025   // Syed A. Jafar. IEEE Globecom 2008 and ArXiv http://arxiv.org/abs/0803.3816.
00026   // The ArXiv version is most detailed.
00027 
00028   // If max_SINR=true (see below) then  the Max-SNIR version is used.
00029 
00030   /* The matrix Vbig[i1](:,:) contains, as it's i2:th column, the
00031     precoder for stream i1 on the ix_all(i2) subcarrier.
00032     The vector ix_all contains all the subcarrier which
00033     are used (not all are). 
00034     The subcarrier numbers we use are actually
00035     1,...,ai[0].rightmost_carrier
00036     and ai[0].leftmost_carrier to Nfft-1. These are the ones
00037     closest to the 0Hz unused DC subcarrier.
00038     Note that subcarrier numbers greater than Nfft/2 wraps
00039     into the negative part of the spectrum.
00040     The two carriers ix_all(ai[0].pilot_carrier1_sub) and 
00041     ix_all(ai[0].pilot_carrier2_sub)
00042     are in the middle of the positive and negative part of the
00043     spectrum, respectively. The names indicate that there would be only
00044     pilots being transmitted on these subcarriers. However, this is
00045     not the case. Since we have set "do_use_pilot_carriers=false".
00046     
00047     Note that the paper by Gadambe&Jafar referenced above
00048     is defined for a single carrier. We use the fact that we
00049     have multiple subcarriers to speed up convergence,
00050     The idea is that adjacent subcarriers should have similiar
00051     channel responses and thus we use the adjacent subcarrier
00052     as the starting point for the iteration. 
00053   */
00054   
00055   /* Define a matrix to store all the beamformers on a singe subcarrier */
00056   cmat v_old(num_ant_bs,num_streams);
00057   
00058   /* Initialize v_old at the beamformers we used in previous time-slot
00059      on the carrier pilot_carrier1_sub. */
00060   for (uint32_t i1=0;i1<num_streams;i1++) {
00061     for (uint32_t i3=0;i3<num_ant_bs;i3++) {
00062         v_old(i3,i1)=Vbig[i1](i3,ai[0].pilot_carrier1_sub);
00063     };
00064   };
00065 
00066   /* Update the beamformers starting from subcarrier index 
00067      ix_all(ai[0].pilot_carrier1_sub) and ending at 
00068      ix_all(ai[0].rightmost_carrier_sub) */
00069   iteration(v_old,ai[0].pilot_carrier1_sub,ai[0].rightmost_carrier_sub,1);
00070   /* Update the beamformers starting from subcarrier index 
00071      ix_all(ai[0].pilot_carrier1_sub) and ending at ix_all(0) */
00072   iteration(v_old,ai[0].pilot_carrier1_sub,0,-1);
00073 
00074 
00075   /* Initialize v_old at the beamformers we used in previous time-slot
00076      on the carrier pilot_carrier1_sub. */
00077   for (uint32_t i1=0;i1<num_streams;i1++) {
00078     for (uint32_t i3=0;i3<num_ant_bs;i3++) {
00079         v_old(i3,i1)=Vbig[i1](i3,ai[0].pilot_carrier2_sub);
00080     };
00081   };
00082 
00083   /* Update the beamformers starting from subcarrier index 
00084      ix_all(ai[0].pilot_carrier2_sub) and ending at ix_all(length_ix_all-1) 
00085      i.e. the maximum used subcarrier number.*/
00086   iteration(v_old,ai[0].pilot_carrier2_sub,ai[0].length_ix_all-1,1);
00087 
00088   /* Update the beamformers starting from subcarrier index 
00089      ix_all(ai[0].pilot_carrier2_sub) and ending at ix_all(length_ix_all-1) 
00090      i.e. the maximum used subcarrier number.*/
00091   iteration(v_old,ai[0].pilot_carrier2_sub,ai[0].leftmost_carrier_sub,-1);      
00092 
00093 
00094 
00095 };
00096 
00097 void IA2_node::iteration(const cmat v_old_in,int subcarrier_ix_start,int subcarrier_ix_stop,int increment) {
00098 
00099   cmat B(num_ant_ms,num_ant_ms); // Interference plus noise covariance matrix   
00100   cmat Hi(num_ant_ms,num_ant_bs); // Intermediate channel matrix
00101   cmat Br(num_ant_bs,num_ant_bs); // Reverse interference plus noise matrix
00102   cmat v_old;
00103 
00104   cvec v(num_ant_bs); // Intermediate precoding vector
00105   cvec u(num_ant_ms); // Intermediate receiving vector
00106   cvec h(num_ant_ms); // Intermediate kind of channel vector
00107   cvec hr(num_ant_bs); // Intermediate kind of channel vector
00108   complex<double> noise_variance;
00109   cmat u_old(num_ant_ms,num_ms);
00110   noise_variance=5901.6;
00111   ivec bs_antenna_ix_for_ms_ix[3];
00112   bool max_SINR=true;
00113   cmat E, Er;
00114   vec d, dr;
00115   vec SINR(3);
00116   vec SINR_min="1e10 1e10 1e10";
00117 
00118   v_old=v_old_in;
00119 
00120   if (!max_SINR) {
00121     E.set_size(num_ant_ms,num_ant_ms);
00122     Er.set_size(num_ant_bs,num_ant_bs);
00123     d.set_length(num_ant_ms);
00124     dr.set_length(num_ant_bs);
00125   };
00126     
00127   if (scenario==1) { // IA
00128     // The indecies of the base-station antennas, numbered from 0 to 5,
00129     // used by MS 0,1 and 2 in the IA approach.
00130     bs_antenna_ix_for_ms_ix[0]="0 1";
00131     bs_antenna_ix_for_ms_ix[1]="2 3";
00132     bs_antenna_ix_for_ms_ix[2]="4 5";
00133   };
00134   if (scenario==2) { // COMP
00135     // The indecies of the base-station antennas, numbered from 0 to 5,
00136     // used by MS 0,1 and 2 in the CoMP approach.
00137     bs_antenna_ix_for_ms_ix[0]="0 1 2 3 4 5";
00138     bs_antenna_ix_for_ms_ix[1]="0 1 2 3 4 5";
00139     bs_antenna_ix_for_ms_ix[2]="0 1 2 3 4 5";
00140   }
00141 
00142   for (int ix=subcarrier_ix_start;
00143        ix!=subcarrier_ix_stop+increment;ix+=increment) {
00144 
00145     for (int iter=0;iter<10;iter++) {
00146 
00147       /* Calculate all receive combiners */
00148       for (uint32_t i1=0;i1<num_streams;i1++) {
00149 
00150         /* B is going to be the noise+interference covariance matrix 
00151            for MS i1. Start with the noise. */
00152         eye(num_ant_ms,B);
00153         B=B*noise_variance;
00154 
00155         for (uint32_t i2=0;i2<num_streams;i2++) {
00156           
00157 
00158           //cout << "================= \n";
00159           //cout << "v_old=" << v_old << endl;
00160 
00161           /* v is the pre-coder of stream i2 */
00162           v=v_old.get_col(i2);
00163           if (!(i1==i2)) {
00164 
00165             
00166             // Fill Hi with the MIMO channel from interfering stream i2
00167             // from the viewpoint of stream (i.e. MS)  i1.    
00168 
00169             for (uint32_t i3=0;i3<num_ant_bs;i3++) {
00170               for (uint32_t i4=0;i4<num_ant_ms;i4++) {
00171 
00172                 Hi(i4,i3)=H[stream_ix_to_ms_ix(i1)][bs_antenna_ix_for_ms_ix[i2](i3)](i4,ix);
00173               };
00174             }; 
00175 
00176             // h is the vector channel given that stream i2 use pre-coder v.
00177             h=Hi*v;
00178             
00179             /* B is the total downlink interference covariance matrix for i1*/
00180             B=B+outer_product(h,h,true);
00181           }; 
00182           //cout << "B=" << B << ";" << endl;
00183        
00184         };
00185 
00186         if (max_SINR) {
00187         
00188           /* v is now the pre-coder of the desired stream */
00189           v=v_old.get_col(i1);
00190           /* Fill Hi with MIMO channel of the desired stream */
00191           for (uint32_t i3=0;i3<num_ant_bs;i3++) {
00192             for (uint32_t i4=0;i4<num_ant_ms;i4++) {
00193               Hi(i4,i3)=H[stream_ix_to_ms_ix(i1)][bs_antenna_ix_for_ms_ix[i1](i3)](i4,ix);
00194             };
00195           }; 
00196           /* Calculate MSSE */
00197           h=Hi*v;
00198           u=inv(B)*h;
00199           u=u/norm(u,2);
00200           u_old.set_col(i1,u);
00201 
00202           //cout << "Hd=" << Hi << ";" << endl;
00203           //cout << "u=" << u << ";" << endl;
00204  
00205         } 
00206         else 
00207         {
00208           eig_sym(B,d,E);
00209           u=E.get_col(0);
00210           u_old.set_col(i1,u); 
00211         };
00212         /* Calculate the SINR given everything is perfect */
00213         SINR(i1)=abs(dot(conj(u),h));
00214         SINR(i1)=SINR(i1)*SINR(i1)/abs((dot(conj(u),B*u)));
00215       };
00216       
00217  
00218  
00219       /* Calcute new downlink beamformers */
00220       for (uint32_t i1=0;i1<num_streams;i1++) {         
00221 
00222         /* Br is the reciprocal interference plus noise covariance matrix */
00223         eye(num_ant_bs,Br);
00224         Br=Br*noise_variance;
00225         for (uint32_t i2=0;i2<num_streams;i2++) {
00226           if (i1!=i2) {
00227             /* u is receiver filter of stream i2 - now acting as transmitter */
00228             u=u_old.get_col(i2);
00229             /* Hi is the reciprocal MIMO channel from MS i2 to BS i1 */
00230             for (uint32_t i3=0;i3<num_ant_bs;i3++) {
00231               for (uint32_t i4=0;i4<num_ant_ms;i4++) {
00232                 Hi(i4,i3)=H[stream_ix_to_ms_ix(i2)][bs_antenna_ix_for_ms_ix[i1](i3)](i4,ix);
00233               };
00234             };
00235             
00236             /* Reciprocal vector channel with u as transmitter */
00237             hr=hermitian_transpose(Hi)*u; 
00238             Br=Br+outer_product(hr,hr,true);
00239           };
00240         };
00241         if (max_SINR) {
00242           /* u is the reciprocal beamformer of stream i1 */
00243           u=u_old.get_col(i1);
00244           /* Hi is the desired reciprocal channel of stream i1 */
00245           for (uint32_t i3=0;i3<num_ant_bs;i3++) {
00246             for (uint32_t i4=0;i4<num_ant_ms;i4++) {
00247               Hi(i4,i3)=H[stream_ix_to_ms_ix(i1)][bs_antenna_ix_for_ms_ix[i1](i3)](i4,ix);
00248             };
00249           };
00250 
00251           /* Calculate new reciprocal beamformer */ 
00252           hr=hermitian_transpose(Hi)*u;
00253           v=inv(Br)*hr;
00254           v=v/norm(v,2);
00255           Vbig[i1].set_col(ix,v);
00256           v_old.set_col(i1,v);
00257 
00258           //cout << "Hd=" << Hi << ";" << endl;
00259           //cout << "v=" << v_old << ";" << endl;
00260         }
00261         else 
00262         {
00263           eig_sym(Br,dr,Er);
00264           v=Er.get_col(0);
00265           Vbig[i1].set_col(ix,v);
00266           v_old.set_col(i1,v);
00267         };
00268       };
00269     };
00270     for (uint32_t i1=0;i1<num_ms;i1++) {
00271       // Stor the worst SNIR of stream 0,1,2 in SINR_min
00272       // (worst over subcarriers). 
00273       if (SINR(i1)<SINR_min(i1)) 
00274         SINR_min(i1)=SINR(i1);  
00275     };
00276   };
00277   //cout << "SINR_min=" << SINR_min << endl;
00278 };
 All Classes Functions Variables