001/*******************************************************************************
002 * Copyright (c) 2016 Pablo Pavon Mariņo.
003 * All rights reserved. This program and the accompanying materials
004 * are made available under the terms of the GNU Lesser Public License v2.1
005 * which accompanies this distribution, and is available at
006 * http://www.gnu.org/licenses/lgpl.html
007 ******************************************************************************/
008
009
010
011
012
013 
014
015
016
017
018package com.net2plan.examples.ocnbook.offline;
019
020import java.util.List;
021import java.util.Map;
022
023import cern.colt.matrix.tdouble.DoubleFactory2D;
024import cern.colt.matrix.tdouble.DoubleMatrix1D;
025import cern.colt.matrix.tdouble.DoubleMatrix2D;
026import cern.jet.math.tdouble.DoubleFunctions;
027
028import com.jom.OptimizationProblem;
029import com.net2plan.interfaces.networkDesign.Configuration;
030import com.net2plan.interfaces.networkDesign.IAlgorithm;
031import com.net2plan.interfaces.networkDesign.Link;
032import com.net2plan.interfaces.networkDesign.Net2PlanException;
033import com.net2plan.interfaces.networkDesign.NetPlan;
034import com.net2plan.libraries.NetworkPerformanceMetrics;
035import com.net2plan.libraries.WirelessUtils;
036import com.net2plan.utils.InputParameter;
037import com.net2plan.utils.Triple;
038
039/**
040 * Finds a fair allocation of the transmission power in a wireless network, solving a formulation.
041 * @net2plan.description
042 * @net2plan.keywords Capacity assignment (CA), Transmission power optimization, JOM, NUM, Wireless 
043 * @net2plan.ocnbooksections Section 5.5
044 * @net2plan.inputParameters 
045 * @author Pablo Pavon-Marino
046 */
047public class Offline_ca_wirelessTransmissionPower implements IAlgorithm
048{
049
050        private InputParameter solverName = new InputParameter ("solverName", "#select# ipopt", "The solver name to be used by JOM. ");
051        private InputParameter solverLibraryName = new InputParameter ("solverLibraryName", "" , "The solver library full or relative path, to be used by JOM. Leave blank to use JOM default.");
052        private InputParameter maxSolverTimeInSeconds = new InputParameter ("maxSolverTimeInSeconds", (double) -1 , "Maximum time granted to the solver to solve the problem. If this time expires, the solver returns the best solution found so far (if a feasible solution is found)");
053        private InputParameter alphaFairnessFactor = new InputParameter ("alphaFairnessFactor", (double) 2 , "Fairness alpha factor" , 0 , true , Double.MAX_VALUE , true);
054        private InputParameter pathLossExponent = new InputParameter ("pathLossExponent", (double) 2 , "Exponent in the the path loss model, computing attenuation for different distances to the transmitter" , 0 , true , Double.MAX_VALUE , true);
055        private InputParameter worseRiseOverThermal_nu = new InputParameter ("worseRiseOverThermal_nu", (double) 10 , "Worse case ratio between interference power and thermal power. Used to set the thermal power in the receivers" , 0 , true , Double.MAX_VALUE , true);
056        private InputParameter interferenceAttenuationFactor_nu = new InputParameter ("interferenceAttenuationFactor_nu", (double) 1E6 , "The interference power received in natural units is multiplied by this to reduce its effect" , 0 , true , Double.MAX_VALUE , true);
057        private InputParameter maxTransmissionPower_logu = new InputParameter ("maxTransmissionPower_logu", (double) 3 , "The maximum link transmission power in logarithmic units (e.g. dBm)");
058        private InputParameter minTransmissionPower_logu = new InputParameter ("minTransmissionPower_logu", (double) 0 , "The minimum link transmission power in logarithmic units (e.g. dBm)");
059
060        @Override
061        public String executeAlgorithm(NetPlan netPlan, Map<String, String> algorithmParameters, Map<String, String> net2planParameters)
062        {
063                /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */
064                InputParameter.initializeAllInputParameterFieldsOfObject(this, algorithmParameters);
065                final int E = netPlan.getNumberOfLinks();
066                if (E == 0) throw new Net2PlanException ("The input topology has no links");
067                
068                /* Initialize the gains between links, normalizing them so that the maximum gain is one */
069                DoubleMatrix2D mac_g_nu_ee = WirelessUtils.computeInterferenceMatrixNaturalUnits (netPlan.getLinks () , interferenceAttenuationFactor_nu.getDouble() , pathLossExponent.getDouble());
070                //System.out.println("NOT normalized Gnu_ee: " + Gnu_ee);
071                final double maxGainValue = mac_g_nu_ee.getMaxLocation() [0];
072                mac_g_nu_ee.assign (DoubleFunctions.div(maxGainValue));
073                //System.out.println("normalized mac_g_nu_ee: " + mac_g_nu_ee);
074                
075                /* Initialize the thermal noise at the receivers, to have a worse case ROT (rise over thermal) */
076                double worseInterferenceReceivedAtMaxPower_nu = WirelessUtils.computeWorseReceiverInterferencePower_nu (maxTransmissionPower_logu.getDouble()  , mac_g_nu_ee);
077
078                /* Adjust the thermal noise in the receivers so that we have a given ROT */
079                final double mac_receptionThermalNoise_nu = worseInterferenceReceivedAtMaxPower_nu / worseRiseOverThermal_nu.getDouble();
080                
081                /* Make the formulation  */
082                DoubleMatrix2D G_ee = DoubleFactory2D.sparse.make (E,E);
083                DoubleMatrix2D G_eep = mac_g_nu_ee.copy ();
084                for (int e = 0; e < E ; e ++) { G_ee.set(e,e,mac_g_nu_ee.get(e,e)); G_eep.set (e,e,0); }
085                
086                OptimizationProblem op = new OptimizationProblem();
087                op.addDecisionVariable("p_e", false , new int[] { 1 , E }, minTransmissionPower_logu.getDouble() , maxTransmissionPower_logu.getDouble());
088                op.setInputParameter("b", 1-alphaFairnessFactor.getDouble());
089                op.setInputParameter("s2", mac_receptionThermalNoise_nu);
090                op.setInputParameter("G_ee", G_ee);
091                op.setInputParameter("G_eep", G_eep);
092                
093                /* For the objective function we use that e^(ln(x) = x */
094                if (alphaFairnessFactor.getDouble() == 1)
095                        op.setObjectiveFunction("maximize", "sum ( ln ( ln (  exp(p_e)*G_ee ./ (s2 + exp(p_e)*G_eep)  ) ) )");
096                else
097                        op.setObjectiveFunction("maximize", "(1/b) * sum (   ln (  exp(p_e)*G_ee ./ (s2 + exp(p_e)*G_eep)  )^b   )  ");
098                
099                /* Call the solver to solve the problem */
100                op.solve(solverName.getString (), "solverLibraryName", solverLibraryName.getString () ,  "maxSolverTimeInSeconds" , maxSolverTimeInSeconds.getDouble ());
101
102                /* If no solution is found, quit */
103                if (op.feasibleSolutionDoesNotExist()) throw new Net2PlanException("The problem has no feasible solution");
104                if (op.foundUnboundedSolution()) throw new Net2PlanException ("Found an unbounded solution");
105                if (!op.solutionIsFeasible()) throw new Net2PlanException("A feasible solution was not found");
106        
107                /* Retrieve the optimum solutions. Convert the bps into Erlangs */
108                final double optNetworkUtility = op.getOptimalCost(); // Warning: I saw in some tests, that IPOPT returned this value different to the optimum solution cost: I could not see if I did something wrong
109                DoubleMatrix1D p_e = op.getPrimalSolution("p_e").view1D ();
110
111                /* Update the netplan object with the resulting capacities */
112                for (Link e : netPlan.getLinks())
113                {
114                        final double sinr_e = WirelessUtils.computeSINRLink(e.getIndex () ,p_e , mac_g_nu_ee , mac_receptionThermalNoise_nu); 
115                        e.setCapacity(Math.log(sinr_e));
116                        e.setAttribute("p_e" , "" + p_e.get(e.getIndex ())); 
117                }
118
119                /* Check constraints */
120                if (p_e.getMinLocation() [0] < minTransmissionPower_logu.getDouble() - 1E-3) throw new RuntimeException ("Bad");
121                if (p_e.getMaxLocation() [0] > maxTransmissionPower_logu.getDouble() + 1E-3) throw new RuntimeException ("Bad");
122                final boolean allMaxPower = (p_e.getMinLocation() [0] >= maxTransmissionPower_logu.getDouble() - 1E-3);
123
124                System.out.println("Optimum solution: u_e: " + netPlan.getVectorLinkCapacity());
125                System.out.println("Optimum solution: p_e: " + p_e);
126                System.out.println("ALL AT THE MAX POWER: " + allMaxPower);     
127
128                final double optimumNetUtilityFromCapacities = NetworkPerformanceMetrics.alphaUtility(netPlan.getVectorLinkCapacity() , alphaFairnessFactor.getDouble()); 
129                return "Ok! Solution guaranteed to be optimal: " + op.solutionIsOptimal() + ", Optimal net utility: " + optimumNetUtilityFromCapacities + ", from JOM output: " + optNetworkUtility;
130        }
131
132        @Override
133        public String getDescription()
134        {
135                return "This algorithm computes the optimum transmission power of each link in a wireless network subject to interferences. The link capacity is approximated as proportional to the logarithm of the signal-to-noise (including interferences) ratio. The target when optimizing the transmission power is enforcing a fair allocation of the resulting link capacities. Initially, the input network interference matrix is normalized so that the worst case rise-over-thermal (ROT) of any link matches a given value.";
136        }
137
138        @Override
139        public List<Triple<String, String, String>> getParameters()
140        {
141                /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */
142                return InputParameter.getInformationAllInputParameterFieldsOfObject(this);
143        }
144
145}