001/******************************************************************************* 002 * Copyright (c) 2017 Pablo Pavon Marino and others. 003 * All rights reserved. This program and the accompanying materials 004 * are made available under the terms of the 2-clause BSD License 005 * which accompanies this distribution, and is available at 006 * https://opensource.org/licenses/BSD-2-Clause 007 * 008 * Contributors: 009 * Pablo Pavon Marino and others - initial API and implementation 010 *******************************************************************************/ 011 012 013 014package com.net2plan.examples.ocnbook.offline; 015 016import cern.colt.matrix.tdouble.DoubleFactory1D; 017import cern.colt.matrix.tdouble.DoubleMatrix1D; 018import cern.jet.math.tdouble.DoubleFunctions; 019import com.jom.OptimizationProblem; 020import com.net2plan.interfaces.networkDesign.Demand; 021import com.net2plan.interfaces.networkDesign.IAlgorithm; 022import com.net2plan.interfaces.networkDesign.Net2PlanException; 023import com.net2plan.interfaces.networkDesign.NetPlan; 024import com.net2plan.utils.Constants.RoutingType; 025import com.net2plan.utils.InputParameter; 026import com.net2plan.utils.Triple; 027 028import java.util.List; 029import java.util.Map; 030 031/** 032 * Solves the congestion control problem using a NUM formulation. 033 * @net2plan.description 034 * @net2plan.keywords Bandwidth assignment (BA), JOM, NUM, TCP 035 * @net2plan.ocnbooksections Section 6.2, Section 6.3 036 * @net2plan.inputParameters 037 * @author Pablo Pavon-Marino 038 */ 039public class Offline_ba_numFormulations implements IAlgorithm 040{ 041 private InputParameter shortestPathType = new InputParameter ("shortestPathType", "#select# hops km" , "Criteria to compute the shortest path. Valid values: 'hops' or 'km'"); 042 private InputParameter alphaFairnessFactor = new InputParameter ("alphaFairnessFactor", (double) 2 , "Fairness alpha factor" , 0 , true , Double.MAX_VALUE , true); 043 private InputParameter utilityFunctionType = new InputParameter ("utilityFunctionType", "#select# alphaFairness TCP-Reno TCP-Vegas", "The type of utility function of each demand, in the NUM problem to solve: standard alpha-fairness (alpha parameter is given by alphaFairnessFactor), an utility function suitable for TCP-Reno NUM model (each demand is a TCP connection) and the same for TCP-Vegas"); 044 private InputParameter solverName = new InputParameter ("solverName", "#select# ipopt glpk xpress cplex", "The solver name to be used by JOM. GLPK and IPOPT are free, XPRESS and CPLEX commercial. GLPK, XPRESS and CPLEX solve linear problems w/w.o integer contraints. IPOPT is can solve nonlinear problems (if convex, returns global optimum), but cannot handle integer constraints"); 045 private InputParameter solverLibraryName = new InputParameter ("solverLibraryName", "" , "The solver library full or relative path, to be used by JOM. Leave blank to use JOM default."); 046 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)"); 047 048 @Override 049 public String executeAlgorithm(NetPlan netPlan, Map<String, String> algorithmParameters, Map<String, String> net2planParameters) 050 { 051 /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */ 052 InputParameter.initializeAllInputParameterFieldsOfObject(this, algorithmParameters); 053 if (!shortestPathType.getString().equalsIgnoreCase("km") && !shortestPathType.getString().equalsIgnoreCase("hops")) 054 throw new Net2PlanException("Wrong shortestPathType parameter"); 055 056 /* Initialize variables */ 057 final int E = netPlan.getNumberOfLinks(); 058 final int D = netPlan.getNumberOfDemands(); 059 final double PRECISION_FACTOR = Double.parseDouble(net2planParameters.get("precisionFactor")); 060 if (E == 0 || D == 0) throw new Net2PlanException("This algorithm requires a topology with links and a demand set"); 061 062 /* Remove all unicast routed traffic. Any multicast routed traffic is kept */ 063 netPlan.removeAllUnicastRoutingInformation(); 064 netPlan.setRoutingTypeAllDemands(RoutingType.SOURCE_ROUTING); 065 066 /* Add all the k-shortest candidate routes to the netPlan object carrying no traffic */ 067 final DoubleMatrix1D linkCostVector = shortestPathType.getString().equalsIgnoreCase("hops")? DoubleFactory1D.dense.make (E , 1.0) : netPlan.getVectorLinkLengthInKm(); 068 069 netPlan.addRoutesFromCandidatePathList(netPlan.computeUnicastCandidatePathList(linkCostVector , 1 , -1, -1, -1, -1, -1, -1, null)); // one route per demand, so P equals D 070 final int P = netPlan.getNumberOfRoutes(); 071 072 /* Create the optimization problem object (JOM library) */ 073 OptimizationProblem op = new OptimizationProblem(); 074 075 /* Set some input parameters to the problem */ 076 op.setInputParameter("u_e", netPlan.getVectorLinkSpareCapacity(), "row"); /* for each link, its unused capacity (the one not used by any mulitcast trees) */ 077 op.setInputParameter("A_ep", netPlan.getMatrixLink2RouteAssignment()); /* 1 in position (e,p) if link e is traversed by path p, 0 otherwise */ 078 op.addDecisionVariable("h_p", false , new int[] { 1, P }, 0, Double.MAX_VALUE); /* the traffic carried by the demand in the macroscopic equilibrium */ 079 op.addConstraint("A_ep * h_p' <= u_e'" , "pi_e"); // the capacity constraints (E constraints) 080 081 /* Write the problem formulations */ 082 if (utilityFunctionType.getString ().equals ("alphaFairness")) 083 { 084 op.setInputParameter("oneMinusAlpha", 1-alphaFairnessFactor.getDouble()); 085 if (alphaFairnessFactor.getDouble() == 1) 086 op.setObjectiveFunction("maximize", "sum(ln(h_p))"); 087 else if (alphaFairnessFactor.getDouble() == 0) 088 op.setObjectiveFunction("maximize", "sum(h_p)"); 089 else 090 op.setObjectiveFunction("maximize", "(1/oneMinusAlpha) * sum(h_p ^ oneMinusAlpha)"); 091 092 } 093 else if (utilityFunctionType.getString ().equals ("TCP-Reno")) 094 { 095 op.setInputParameter("rtt_p", netPlan.getVectorRoutePropagationDelayInMiliseconds().assign (DoubleFunctions.mult (2)) , "row"); /* round-trip-time in miliseconds for each connection */ 096 op.setObjectiveFunction("maximize", "sum (-1.5 / (rtt_p .* h_p))"); 097 } 098 else if (utilityFunctionType.getString ().equals ("TCP-Vegas")) 099 { 100 op.setObjectiveFunction("maximize", "sum(ln(h_p))"); 101 } 102 else throw new Net2PlanException ("Unknown optimization target " + utilityFunctionType.getString()); 103 104 /* Call the solver to solve the problem */ 105 op.solve(solverName.getString (), "solverLibraryName", solverLibraryName.getString () , "maxSolverTimeInSeconds" , maxSolverTimeInSeconds.getDouble ()); 106 107 /* If no solution is found, quit */ 108 if (op.feasibleSolutionDoesNotExist()) throw new Net2PlanException("The problem has no feasible solution"); 109 if (op.foundUnboundedSolution()) throw new Net2PlanException ("Found an unbounded solution"); 110 if (!op.solutionIsFeasible()) throw new Net2PlanException("A feasible solution was not found"); 111 112 /* Save the solution found in the netPlan object */ 113 final DoubleMatrix1D h_p = op.getPrimalSolution("h_p").view1D(); 114 netPlan.setVectorRouteCarriedTrafficAndOccupiedLinkCapacities(h_p , h_p); 115 for (Demand d : netPlan.getDemands ()) d.setOfferedTraffic(d.getCarriedTraffic()); // make the offered traffic equal to the carried traffic 116 117// System.out.println ("Total carried traffic: " + netPlan.getVectorDemandOfferedTraffic().zSum()); 118// System.out.println ("Network utility: " + op.getOptimalCost()); 119 120 return "Ok!: The solution found is guaranteed to be optimal: " + op.solutionIsOptimal() + ". Total carried traffic: " + netPlan.getVectorDemandOfferedTraffic().zSum() + ", Network utility: " + op.getOptimalCost(); 121 } 122 123 @Override 124 public String getDescription() 125 { 126 return "Given a network topology, the capacities in the links, and the set of unicast demands, this algorithm assigns the shortest path route to each demand, then optimizes the traffic to inject by each demand (that is, assigns bandwidth), with different optimization targets based on some form of fairness in resource allocation"; 127 } 128 129 130 @Override 131 public List<Triple<String, String, String>> getParameters() 132 { 133 /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */ 134 return InputParameter.getInformationAllInputParameterFieldsOfObject(this); 135 } 136}