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 014 015package com.net2plan.examples.ocnbook.offline; 016 017import cern.colt.matrix.tdouble.DoubleFactory1D; 018import cern.colt.matrix.tdouble.DoubleFactory2D; 019import cern.colt.matrix.tdouble.DoubleMatrix1D; 020import cern.colt.matrix.tdouble.DoubleMatrix2D; 021import cern.jet.math.tdouble.DoubleFunctions; 022import com.jom.DoubleMatrixND; 023import com.jom.OptimizationProblem; 024import com.net2plan.interfaces.networkDesign.*; 025import com.net2plan.utils.Constants.RoutingType; 026import com.net2plan.utils.Constants.SearchType; 027import com.net2plan.utils.*; 028 029import java.io.File; 030import java.io.PrintWriter; 031import java.util.*; 032import java.util.Map.Entry; 033 034/** 035 * This algorithm is devoted to solve the several network planning problems in an optical WDM network (fiber placement, RWA, under different recovery schemes), appearing in the case study in the book section mentioned below. 036 * @net2plan.description 037 * @net2plan.keywords WDM, Topology assignment (TA), Flow assignment (FA), GRASP, JOM 038 * @net2plan.ocnbooksections Section 12.10 039 * @net2plan.inputParameters 040 * @author Pablo Pavon-Marino 041 */ 042public class Offline_tcfa_wdmPhysicalDesign_graspAndILP implements IAlgorithm 043{ 044 /* Stat */ 045 private double stat_totalCost , stat_costinks , stat_costCirc , stat_costNodes; 046 private int stat_numLinks , stat_numCirc , stat_numNodesDeg2 , stat_numNodesDeg3; 047 private int stat_numItGRASP , stat_numLSIterationsReducingCost , stat_numSolverCalls , stat_numSolverCallsOk; 048 private double stat_totalTimeSecs , stat_totalTimeCreateProgramsSecs , stat_totalTimeSolverSecs; 049 050 /* Parameters */ 051 private DoubleMatrix1D linkCost_e; 052 private Random rng; 053 private NetPlan netPlan; 054 055 /* Control */ 056 private int Efm, N, nSRGs , D , R; 057 private DoubleMatrix1D numCircH_d; 058 private DoubleMatrix2D A_er , A_dr , A_rs , A_se , Aout_ne , Ain_ne, Abid_dd , Abid_rr , Abid_ee; 059 private Map<Demand,Demand> opposite_d; 060 private Map<Route,Route> opposite_r; 061 private int [][] routeList_d; // for each demand, the array of route ids assigned to it 062 private int [][] traversedLinks_r; // for each demand, the array of route ids assigned to it 063 064 065 private InputParameter algorithm_randomSeed = new InputParameter ("algorithm_randomSeed", (long) 1 , "Seed of the random number generator"); 066 private InputParameter algorithm_outputFileNameRoot = new InputParameter ("algorithm_outputFileNameRoot", "tcfaWDM_graspAndILP" , "Root of the file name to be used in the output files. If blank, no output"); 067 private InputParameter algorithm_maxExecutionTimeInSeconds = new InputParameter ("algorithm_maxExecutionTimeInSeconds", (double) 300 , "Algorithm maximum running time in seconds" , 0 , false , Double.MAX_VALUE , true); 068 private InputParameter tcfa_circuitCost = new InputParameter ("tcfa_circuitCost", (double) 3.0 , "Cost of each circuit" , 0 , true , Double.MAX_VALUE , true); 069 private InputParameter tcfa_circuitCapacity_Gbps = new InputParameter ("tcfa_circuitCapacity_Gbps", (double) 10.0 , "Capacity of an optical circuit" , 0 , true , Double.MAX_VALUE , true); 070 private InputParameter tcfa_srgType = new InputParameter ("tcfa_srgType" , "#select# perBidirectionalLinkBundle noFailure", "Determines how the SRGs are initialized. The design must be tolerant to single SRG failures"); 071 private InputParameter tcfa_srgMttfPer1000Km_hrs = new InputParameter ("tcfa_srgMttfPer1000Km_hrs" , (double) 4380 , "Mean Time To Fail (MTTF) of the SRGs defined is this value multiplied by the link length divided by 1000", 0 , false , Double.MAX_VALUE , true); 072 private InputParameter tcfa_srgMttr_hrs = new InputParameter ("tcfa_srgMttr_hrs" , (double) 24 , "Mean Time To Repair (MTTR) of the SRGs", 0 , true , Double.MAX_VALUE , true); 073 private InputParameter tcfa_recoveryType = new InputParameter ("tcfa_recoveryType" , "#select# 1+1 shared restoration", "Determines the type of network recovery mechanism in the network."); 074 private InputParameter tcfa_maxPathLengthInKm = new InputParameter ("tcfa_maxPathLengthInKm" , (double) 10000 , "Maximum length that a lightpath can have", 0 , true , Double.MAX_VALUE , true); 075 private InputParameter tcfa_maxPathNumberOfHops = new InputParameter ("tcfa_maxPathNumberOfHops" , (int) 4 , "Maximum number of hops that a lightpath can make", 1 , Integer.MAX_VALUE); 076 private InputParameter tcfa_maxNumberPathsPerDemand = new InputParameter ("tcfa_maxNumberPathsPerDemand" , (int) 200 , "Maximum number of paths in the candidate path list, for each demand", 1 , Integer.MAX_VALUE); 077 private InputParameter tcfa_linkCapacity_numCirc = new InputParameter ("tcfa_linkCapacity_numCirc" , (int) 80 , "Number of wavelengths available per fiber", 1 , Integer.MAX_VALUE); 078 private InputParameter tcfa_linkCostPerKm = new InputParameter ("tcfa_linkCostPerKm" , (double) 0.4 , "Cost of one km of optical fiber", 0 , true , Double.MAX_VALUE , true); 079 private InputParameter tcfa_costNodeDegree2 = new InputParameter ("tcfa_costNodeDegree2" , (double) 4.0 , "Cost of one OADM of degree lower or equal than two", 0 , true , Double.MAX_VALUE , true); 080 private InputParameter tcfa_costNodeDegreeHigherThan2 = new InputParameter ("tcfa_costNodeDegreeHigherThan2" , (double) 4.0 , "Cost of one OADM of degree higher than two", 0 , true , Double.MAX_VALUE , true); 081 private InputParameter tcfa_networkDiameterKmToNormalize = new InputParameter ("tcfa_networkDiameterKmToNormalize" , (double) 4500 , "The link lengths are normalized so the longest link has this value", 0 , true , Double.MAX_VALUE , true); 082 private InputParameter tcfa_maxNumIterations = new InputParameter ("tcfa_maxNumIterations", (int) 10000 , "Maximum number of iterations" , 1 , Integer.MAX_VALUE); 083 private InputParameter algorithm_solverName = new InputParameter ("solverName", "#select# glpk ipopt 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"); 084 private InputParameter algorithm_solverLibraryName = new InputParameter ("solverLibraryName", "", "The solver library full or relative path, to be used by JOM. Leave blank to use JOM default."); 085 private InputParameter algorithm_maxSolverTimeInSeconds = new InputParameter ("maxSolverTimeInSeconds", (double) 2 , "Maximum time granted to the solver in to solve each problem instance. If this time expires, the solver returns the best solution found so far (if a feasible solution is found)"); 086 private InputParameter tcfa_bidirectionalLinks = new InputParameter ("tcfa_bidirectionalLinks", true , "If true, the topology of fibers deployed is constrained to be bidirectional (the same number of fibers in both directions)"); 087 088 @Override 089 public String executeAlgorithm(NetPlan netPlan, Map<String, String> algorithmParameters, Map<String, String> net2planParameters) 090 { 091 /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */ 092 InputParameter.initializeAllInputParameterFieldsOfObject(this, algorithmParameters); 093 if (netPlan.getNumberOfNodes() == 0) throw new Net2PlanException ("The input design has no nodes"); 094 095 096 try{ 097 this.netPlan = netPlan; 098 /* Initializations */ 099 100 netPlan.removeAllLinks(); netPlan.setRoutingTypeAllDemands(RoutingType.SOURCE_ROUTING); 101 this.N = netPlan.getNumberOfNodes(); 102 this.rng = new Random (algorithm_randomSeed.getLong ()); 103 104 /* Initialize links */ 105 for (Node n1 : netPlan.getNodes()) for (Node n2 : netPlan.getNodes()) if (n1 != n2) netPlan.addLink(n1, n2, 0.01, netPlan.getNodePairEuclideanDistance(n1, n2), 200000 , null); 106 final double linkLengthKmFromEuclideanDistanceFactor = tcfa_networkDiameterKmToNormalize.getDouble() / netPlan.getVectorLinkLengthInKm().getMaxLocation() [0]; 107 for (Link e : netPlan.getLinks()) e.setLengthInKm(e.getLengthInKm() * linkLengthKmFromEuclideanDistanceFactor); 108 this.Efm = netPlan.getNumberOfLinks(); if (Efm != N*(N-1)) throw new RuntimeException ("Bad, Efm" + Efm + ", N: " + N); 109 this.linkCost_e = DoubleFactory1D.dense.make(Efm); for (Link e : netPlan.getLinks ()) linkCost_e.set(e.getIndex () , tcfa_linkCostPerKm.getDouble() * e.getLengthInKm()); 110 111 /* If there is no traffic, create uniform traffic matrix */ 112 if (netPlan.getNumberOfDemands() == 0) 113 for (Node n1 : netPlan.getNodes()) for (Node n2 : netPlan.getNodes()) if (n1 != n2) netPlan.addDemand(n1, n2, tcfa_circuitCapacity_Gbps.getDouble(), RoutingType.SOURCE_ROUTING , null); 114 115 116 /* Convert the demand offered traffic in the upper multiple of circuit capacity */ 117 DoubleMatrix2D trafficMatrix = netPlan.getMatrixNode2NodeOfferedTraffic(); 118 netPlan.removeAllDemands(); 119 for (Node n1 : netPlan.getNodes()) for (Node n2 : netPlan.getNodes()) if (n1.getIndex () > n2.getIndex ()) 120 { 121 final double maxTrafficBidir = Math.max(trafficMatrix.get(n1.getIndex (), n2.getIndex ()), trafficMatrix.get(n2.getIndex (), n1.getIndex ())); 122 netPlan.addDemand(n1, n2, tcfa_circuitCapacity_Gbps.getDouble() * Math.ceil(maxTrafficBidir / tcfa_circuitCapacity_Gbps.getDouble()) , RoutingType.SOURCE_ROUTING , null); 123 netPlan.addDemand(n2, n1, tcfa_circuitCapacity_Gbps.getDouble() * Math.ceil(maxTrafficBidir / tcfa_circuitCapacity_Gbps.getDouble()) , RoutingType.SOURCE_ROUTING , null); 124 } 125 126 /* If 1+1 then decouple demands in one per channel */ 127 if (tcfa_recoveryType.getString ().equals("1+1")) 128 { 129 NetPlan npcopy = netPlan.copy(); 130 netPlan.removeAllDemands(); 131 for (Demand d : npcopy.getDemands()) 132 { 133 final int numChannels = (int) Math.round (d.getOfferedTraffic() / tcfa_circuitCapacity_Gbps.getDouble ()); 134 for (int cont = 0 ; cont < numChannels ; cont ++) netPlan.addDemand(netPlan.getNodeFromId (d.getIngressNode().getId ()), netPlan.getNodeFromId (d.getEgressNode().getId ()), tcfa_circuitCapacity_Gbps.getDouble () , RoutingType.SOURCE_ROUTING , d.getAttributes()); 135 } 136 } 137 138 /* Initialize routes and demands to make it bidirectional */ 139 Pair<Map<Demand,Demand>,Map<Route,Route>> pair = initializeNetPlanLinksBidirDemandsAndRoutes (netPlan); 140 this.opposite_d = pair.getFirst(); 141 this.opposite_r = pair.getSecond(); 142 143 /* Initialize demand info */ 144 this.D = netPlan.getNumberOfDemands(); 145 this.numCircH_d = netPlan.getVectorDemandOfferedTraffic().assign(DoubleFunctions.div(this.tcfa_circuitCapacity_Gbps.getDouble ())).assign(DoubleFunctions.rint); 146 //System.out.println("Total number of circuits to establish: " + numCircH_d.zSum()); 147 148 //if (1==1) throw new RuntimeException ("Stop"); 149 this.R = netPlan.getNumberOfRoutes(); 150 //System.out.println ("numCircH_d: " + numCircH_d); 151 152 /* Initialize SRG information */ 153 initializeSRGs(netPlan); 154 this.nSRGs = netPlan.getNumberOfSRGs(); 155 this.routeList_d = new int [D][]; for (Demand d : netPlan.getDemands ()) routeList_d [d.getIndex ()] = getIndexes (d.getRoutes ()); 156 this.traversedLinks_r = new int [R][]; for (Route r : netPlan.getRoutes ()) traversedLinks_r [r.getIndex ()] = getIndexes (r.getSeqLinks()); 157 158 159 /* Initialize aux arrays for speed-up */ 160 this.A_dr = netPlan.getMatrixDemand2RouteAssignment(); 161 for (Demand d : netPlan.getDemands ()) if (d.getRoutes().isEmpty()) throw new Net2PlanException ("A demand has no assigned routes"); 162 this.A_er = netPlan.getMatrixLink2RouteAssignment(); 163 this.A_se = DoubleFactory2D.dense.make(1 + nSRGs , Efm , 1.0); // 1 if link OK, 0 if fails 164 for (int contSRG = 0 ; contSRG < nSRGs ; contSRG ++) 165 for (Link e : netPlan.getSRG (contSRG).getLinksAllLayers()) 166 A_se.set(contSRG+1 , e.getIndex () , 0.0); 167 this.A_rs = DoubleFactory2D.dense.make(R , 1 + nSRGs , 1.0); // 1 if link OK, 0 if fails 168 for (Route r : netPlan.getRoutes ()) for (Link e : r.getSeqLinks()) for (SharedRiskGroup srg : e.getSRGs()) 169 A_rs.set(r.getIndex (),1+srg.getIndex () , 0.0); 170 171 /* Check if the problem may have a solution: demands have at least one path in any failure state */ 172 if (A_dr.zMult(A_rs, null).getMinLocation() [0] == 0) { System.out.println("A_dr.zMult(A_rs, null): " + A_dr.zMult(A_rs, null)); throw new Net2PlanException ("Some demands cannot be routed in some failure state. We need more paths! (e.g. extend the path reach)"); } 173 174 this.Aout_ne = netPlan.getMatrixNodeLinkOutgoingIncidence(); 175 this.Ain_ne = netPlan.getMatrixNodeLinkIncomingIncidence(); 176 this.Abid_dd = DoubleFactory2D.sparse.make(D,D); for (Entry<Demand,Demand> entry : opposite_d.entrySet()) { Abid_dd.set(entry.getKey().getIndex (), entry.getValue().getIndex (), 1.0); Abid_dd.set(entry.getValue().getIndex (), entry.getKey().getIndex (), 1.0); } 177 this.Abid_rr = DoubleFactory2D.sparse.make(R,R); for (Entry<Route,Route> entry : opposite_r.entrySet()) { Abid_rr.set(entry.getKey().getIndex (), entry.getValue().getIndex (), 1.0); Abid_rr.set(entry.getValue().getIndex (), entry.getKey().getIndex (), 1.0); } 178 this.Abid_ee = DoubleFactory2D.sparse.make(Efm,Efm); for (Link e : netPlan.getLinks ()) { Abid_ee.set(e.getIndex (), oppositeLink(e).getIndex (), 1.0); Abid_ee.set(oppositeLink(e).getIndex (), e.getIndex (), 1.0); } 179 180 final long algorithmInitialtime = System.nanoTime(); 181 final long algorithmEndtime = algorithmInitialtime + (long) (algorithm_maxExecutionTimeInSeconds.getDouble() * 1E9); 182 183 /* Up stage */ 184 ArrayList<Integer> shuffledDemands = new ArrayList<Integer> (D); for (int d = 0 ; d < D ; d ++) shuffledDemands.add(d); 185 Collections.shuffle(shuffledDemands , rng); 186 if (tcfa_recoveryType.getString ().equals("shared")) 187 { 188 DoubleMatrix1D best_xr = null; DoubleMatrix1D best_pe = null; double bestCost = Double.MAX_VALUE; 189 int iterationCounter = 0; 190 while ((System.nanoTime() < algorithmEndtime) && (iterationCounter < tcfa_maxNumIterations.getInt ())) 191 { 192 DoubleMatrix1D thisIt_xr = greedyAndLocalSearch_shared(algorithmEndtime , netPlan); 193 DoubleMatrix1D thisIt_pe = A_er.zMult(thisIt_xr, null); thisIt_pe.assign(DoubleFunctions.div(tcfa_linkCapacity_numCirc.getInt ())).assign(DoubleFunctions.ceil); 194 double thisItCost = computeCost_shared(thisIt_xr, thisIt_pe); 195 if (thisItCost < bestCost) { best_xr = thisIt_xr; best_pe = thisIt_pe; bestCost = thisItCost; } 196 iterationCounter ++; 197 } 198 stat_numItGRASP = iterationCounter; 199 for (Route r : netPlan.getRoutes ()) r.setCarriedTraffic(tcfa_circuitCapacity_Gbps.getDouble () * best_xr.get(r.getIndex ()) , tcfa_circuitCapacity_Gbps.getDouble () * best_xr.get(r.getIndex ())); 200 for (Link e : netPlan.getLinks ()) e.setCapacity(tcfa_linkCapacity_numCirc.getInt () * tcfa_circuitCapacity_Gbps.getDouble () * best_pe.get(e.getIndex())); 201 } else if (tcfa_recoveryType.getString ().equals("1+1")) 202 { 203 DoubleMatrix1D best_xr = null; DoubleMatrix1D best_x2r = null; DoubleMatrix1D best_pe = null; double bestCost = Double.MAX_VALUE; 204 int iterationCounter = 0; 205 while ((System.nanoTime() < algorithmEndtime) && (iterationCounter < tcfa_maxNumIterations.getInt ())) 206 { 207 Pair<DoubleMatrix1D,DoubleMatrix1D> thisItSolution = greedyAndLocalSearch_11(algorithmEndtime , netPlan); 208 DoubleMatrix1D thisIt_xr = thisItSolution.getFirst(); 209 DoubleMatrix1D thisIt_x2r = thisItSolution.getSecond(); 210 DoubleMatrix1D thisIt_pe = computePe_11(thisIt_xr, thisIt_x2r); 211 double thisItCost = computeCost_11(thisIt_xr, thisIt_x2r , thisIt_pe); 212 if (thisItCost < bestCost) { best_xr = thisIt_xr; best_x2r = thisIt_x2r; best_pe = thisIt_pe; bestCost = thisItCost; } 213 iterationCounter ++; 214 } 215 stat_numItGRASP = iterationCounter; 216 for (Demand d : netPlan.getDemands ()) 217 { 218 if (Math.abs(best_xr.viewSelection(routeList_d [d.getIndex ()]).zSum() - 1) > 1E-3) throw new RuntimeException ("Bad"); 219 if (Math.abs(best_x2r.viewSelection(routeList_d [d.getIndex ()]).zSum() - 1) > 1E-3) throw new RuntimeException ("Bad"); 220 Route primaryRoute = null; Route backupRoute = null; 221 for (Route r : d.getRoutes ()) if (Math.abs(best_xr.get(r.getIndex ()) - 1) <= 1e-3) { primaryRoute = r; primaryRoute.setCarriedTraffic(tcfa_circuitCapacity_Gbps.getDouble () , tcfa_circuitCapacity_Gbps.getDouble ()); break; } 222 for (Route r : d.getRoutes ()) if (Math.abs(best_x2r.get(r.getIndex ()) - 1) <= 1e-3) { backupRoute = r; backupRoute.setCarriedTraffic(0 , tcfa_circuitCapacity_Gbps.getDouble ()); break; } 223 primaryRoute.addBackupRoute(backupRoute); 224 } 225 for (Link e : netPlan.getLinks ()) e.setCapacity(tcfa_linkCapacity_numCirc.getInt () * tcfa_circuitCapacity_Gbps.getDouble () * best_pe.get(e.getIndex())); 226 227 } else if (tcfa_recoveryType.getString ().equals("restoration")) 228 { 229 DoubleMatrix2D best_xrs = null; DoubleMatrix1D best_pe = null; double bestCost = Double.MAX_VALUE; 230 int iterationCounter = 0; 231 while ((System.nanoTime() < algorithmEndtime) && (iterationCounter < tcfa_maxNumIterations.getInt ())) 232 { 233 DoubleMatrix2D thisIt_xrs = greedyAndLocalSearch_restoration(algorithmEndtime , netPlan); 234 DoubleMatrix1D thisIt_pe = computePe_restoration (thisIt_xrs); 235 double thisItCost = computeCost_shared(thisIt_xrs.viewColumn(0), thisIt_pe); 236 if (thisItCost < bestCost) { best_xrs = thisIt_xrs; best_pe = thisIt_pe; bestCost = thisItCost; } 237 iterationCounter ++; 238 } 239 stat_numItGRASP = iterationCounter; 240 for (Route r : netPlan.getRoutes ()) r.setCarriedTraffic(tcfa_circuitCapacity_Gbps.getDouble () * best_xrs.get(r.getIndex (),0) , tcfa_circuitCapacity_Gbps.getDouble () * best_xrs.get(r.getIndex (),0)); 241 for (Link e : netPlan.getLinks ()) e.setCapacity(tcfa_linkCapacity_numCirc.getInt () * tcfa_circuitCapacity_Gbps.getDouble () * best_pe.get(e.getIndex())); 242 } else throw new RuntimeException ("Bad"); 243 244 /* Remove unused routes and links */ 245 for (Route r : new HashSet<Route>(netPlan.getRoutes())) if (!r.isBackupRoute() && r.getCarriedTraffic() == 0) r.remove(); 246 for (Link e : new HashSet<Link>(netPlan.getLinks())) if (e.getCapacity() == 0) e.remove(); 247 248 Quadruple<Double,Double,Double,Double> q = computeCost (netPlan); 249 stat_totalCost = q.getFirst(); 250 stat_costinks = q.getSecond(); 251 stat_costNodes = q.getThird(); 252 stat_costCirc = q.getFourth(); 253 stat_numLinks = (int) (netPlan.getVectorLinkCapacity().zSum () / (tcfa_linkCapacity_numCirc.getInt () * tcfa_circuitCapacity_Gbps.getDouble ())); 254 stat_numCirc = (int) Math.round(netPlan.getVectorDemandCarriedTraffic().zSum() / tcfa_circuitCapacity_Gbps.getDouble ()); if (tcfa_recoveryType.getString ().equals("1+1")) stat_numCirc *=2; 255 for (Node n : netPlan.getNodes()) if (n.getOutgoingLinks().size() > 2) stat_numNodesDeg3 ++; else stat_numNodesDeg2 ++; 256 stat_totalTimeSecs = (System.nanoTime() - algorithmInitialtime)*1e-9; 257 checkSolution (netPlan); 258 259 double averageLinkUtilization = netPlan.getVectorLinkUtilization().zSum() / stat_numLinks; 260 final String fileNameStem = algorithm_outputFileNameRoot.getString() + "_" + tcfa_srgType.getString() + "_c" + tcfa_circuitCapacity_Gbps.getDouble () + "_t" + algorithm_maxExecutionTimeInSeconds.getDouble() + "_r" + tcfa_recoveryType.getString (); 261 try 262 { 263 PrintWriter pw = new PrintWriter (new File (fileNameStem + "_allResults.txt")); 264 pw.println(stat_totalCost ); 265 pw.println( stat_costinks ); 266 pw.println( stat_costNodes ); 267 pw.println( stat_costCirc ); 268 pw.println( stat_numLinks ); 269 pw.println( stat_numCirc ); 270 pw.println( stat_numNodesDeg2 ); 271 pw.println( stat_numNodesDeg3 ); 272 pw.println( stat_numItGRASP ); 273 pw.println( stat_numLSIterationsReducingCost ); 274 pw.println( stat_numSolverCalls ); 275 pw.println( stat_numSolverCallsOk ); 276 pw.println( stat_totalTimeSecs ); 277 pw.println( stat_totalTimeCreateProgramsSecs ); 278 pw.println( stat_totalTimeSolverSecs ); 279 pw.println( averageLinkUtilization ); 280 pw.close (); 281 } catch (Exception e) { e.printStackTrace(); throw new RuntimeException ("Not possible to write in File " + fileNameStem + "_allResults.txt"); } 282 283 284 netPlan.setAttribute("stat_totalCost", ""+stat_totalCost); 285 netPlan.setAttribute("stat_costinks", ""+stat_costinks); 286 netPlan.setAttribute("stat_costNodes", ""+stat_costNodes); 287 netPlan.setAttribute("stat_costCirc", ""+stat_costCirc); 288 netPlan.setAttribute("stat_numLinks", ""+stat_numLinks); 289 netPlan.setAttribute("stat_numCirc", ""+stat_numCirc); 290 netPlan.setAttribute("stat_numNodesDeg2", ""+stat_numNodesDeg2); 291 netPlan.setAttribute("stat_numNodesDeg3", ""+stat_numNodesDeg3); 292 netPlan.setAttribute("stat_numItGRASP", ""+stat_numItGRASP); 293 netPlan.setAttribute("stat_numLSIterationsReducingCost", ""+stat_numLSIterationsReducingCost); 294 netPlan.setAttribute("stat_numSolverCalls", ""+stat_numSolverCalls); 295 netPlan.setAttribute("stat_numSolverCallsOk", ""+stat_numSolverCallsOk); 296 netPlan.setAttribute("stat_totalTimeSecs", ""+stat_totalTimeSecs); 297 netPlan.setAttribute("stat_totalTimeCreateProgramsSecs", ""+stat_totalTimeCreateProgramsSecs); 298 netPlan.setAttribute("stat_totalTimeSolverSecs", ""+stat_totalTimeSolverSecs); 299 300 netPlan.saveToFile(new File (fileNameStem + ".n2p")); 301 302// if (netPlan.getDemandTotalBlockedTraffic() > 1E-3) throw new RuntimeException ("Bad"); 303// if (netPlan.getLinksOversubscribed().size() > 0) throw new RuntimeException ("Bad"); 304 //System.out.println("JOM sol: cost: " + stat_totalCost + ", num links: "+ stat_numLinks); 305 306 return "Ok! cost: " + stat_totalCost + ", num links: "+ stat_numLinks; 307 308 } catch (Exception e) { e.printStackTrace(); throw new RuntimeException ("BAD OUT"); } 309 310 } 311 312 @Override 313 public String getDescription() 314 { 315 return "This algorithm is devoted to solve the several network planning problems appearing in the case study in Section 12.10 of the book mentioned below. The context is the planning of a WDM optical network, given a set of node locations, and a set of end-to-end optical connections (lightpaths) to establish. The algorithm should decide on the fibers to deploy, and the routing of the lightpaths on the fibers, minimizing the total network cost. The cost model includes the fiber renting cost (paid to a dark fiber provider), OADM cost (separating between OADMs of degree two, and degree higher than two), and the cost of the transponders. The network must be tolerant to a set of user-defined failures (defined by SRGs). The algorithm permits choosing between two recovery types: 1+1, and shared protection. In the latter, the number of lightpaths between two nodes that survive to any of the failures is at least the number of optical connections requested for that node pair. For solving the problem, the algorithm uses a GRASP heuristic, to govern the iterative search that is performed using small ILPs solved with JOM in each iteration."; 316 } 317 318 @Override 319 public List<Triple<String, String, String>> getParameters() 320 { 321 /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */ 322 return InputParameter.getInformationAllInputParameterFieldsOfObject(this); 323 } 324 325 private Quadruple<Double,Double,Double,Double> computeCost (NetPlan np) 326 { 327 double costLinks = 0; 328 for (Link e : np.getLinks ()) 329 costLinks += linkCost_e.get(e.getIndex ()) * e.getCapacity() / (tcfa_linkCapacity_numCirc.getInt () * tcfa_circuitCapacity_Gbps.getDouble ()); 330 331 double costCircuits = 0; 332 for (Route r : np.getRoutes ()) // sums both lps and 1+1 if there are any 333 { 334 final double lineRate = r.isBackupRoute()? r.getRoutesIAmBackup().iterator().next().getCarriedTrafficInNoFailureState() : r.getCarriedTrafficInNoFailureState(); 335 costCircuits += tcfa_circuitCost.getDouble () * (lineRate / tcfa_circuitCapacity_Gbps.getDouble ()); 336 } 337 double costNodes = 0; 338 for (Node n : np.getNodes()) 339 { 340 final int nodeDegree = (int) Math.max(n.getOutgoingLinks().size(), n.getIncomingLinks().size()); 341 costNodes += (nodeDegree <= 2)? tcfa_costNodeDegree2.getDouble () : tcfa_costNodeDegreeHigherThan2.getDouble (); 342 } 343 final double totalCost = costLinks+ costCircuits + costNodes; 344 345 System.out.println("Total cost: " + totalCost + ", links %: " + (costLinks/totalCost) + ", circ %: " + (costCircuits/totalCost) + ", nodes %: " + (costNodes/totalCost)); 346 347 System.out.println("-- From np cost total :" + totalCost + ", links: " + costLinks + ", nodes: " + costNodes + ", circ: " + costCircuits); 348 349 return Quadruple.of(totalCost,costLinks,costNodes,costCircuits); 350 } 351 352 private double computeCost_shared (DoubleMatrix1D x_r , DoubleMatrix1D p_e) 353 { 354 double costLinks = p_e.zDotProduct(linkCost_e); 355 final double costCircuits = tcfa_circuitCost.getDouble () * x_r.zSum(); 356 double costNodes = 0; 357 DoubleMatrix1D degree_n = Aout_ne.zMult(p_e, null); 358 for (int n = 0; n < N ; n ++) 359 costNodes += (degree_n.get(n) <= 2)? tcfa_costNodeDegree2.getDouble () : tcfa_costNodeDegreeHigherThan2.getDouble (); 360 final double totalCost = costLinks+ costCircuits + costNodes; 361 //System.out.println("-- shared cost total :" + totalCost + ", links: " + costLinks + ", nodes: " + costNodes + ", circ: " + costCircuits); 362 return totalCost; 363 } 364 private double computeCost_11 (DoubleMatrix1D x_r , DoubleMatrix1D x2_r , DoubleMatrix1D p_e) 365 { 366 double costLinks = p_e.zDotProduct(linkCost_e); 367 final double costCircuits = tcfa_circuitCost.getDouble () * (x_r.zSum() + x2_r.zSum()); 368 double costNodes = 0; 369 DoubleMatrix1D degree_n = Aout_ne.zMult(p_e, null); 370 for (int n = 0; n < N ; n ++) 371 costNodes += (degree_n.get(n) <= 2)? tcfa_costNodeDegree2.getDouble () : tcfa_costNodeDegreeHigherThan2.getDouble (); 372 final double totalCost = costLinks+ costCircuits + costNodes; 373 //System.out.println("-- shared cost total :" + totalCost + ", links: " + costLinks + ", nodes: " + costNodes + ", circ: " + costCircuits); 374 return totalCost; 375 } 376 377 private static Link oppositeLink (Link e) { return e.getNetPlan ().getNodePairLinks(e.getDestinationNode(), e.getOriginNode() , false).iterator().next(); } 378 379 private Pair<Map<Demand,Demand>,Map<Route,Route>> initializeNetPlanLinksBidirDemandsAndRoutes (NetPlan np) 380 { 381 /* Remove lower half demands from np */ 382 np.removeAllRoutes(); 383 for (Node n1 : np.getNodes()) for (Node n2 : np.getNodes()) if (n1.getIndex () > n2.getIndex ()) for (Demand d : np.getNodePairDemands(n1, n2,false)) d.remove (); 384 np.addRoutesFromCandidatePathList(netPlan.computeUnicastCandidatePathList(null , tcfa_maxNumberPathsPerDemand.getInt(), tcfa_maxPathLengthInKm.getDouble(), tcfa_maxPathNumberOfHops.getInt(), -1, -1, -1, -1 , null)); 385 386 /* Add symmetric demands and routes */ 387 Map<Demand,Demand> opposite_d = new HashMap<Demand,Demand> (); 388 Map<Route,Route> opposite_r = new HashMap<Route,Route> (); 389 for (Demand d : new HashSet<Demand> (np.getDemands())) 390 { 391 final Demand opDemand = np.addDemand(d.getEgressNode(), d.getIngressNode(), d.getOfferedTraffic(), RoutingType.SOURCE_ROUTING , null); 392 opposite_d.put(d,opDemand); 393 opposite_d.put(opDemand,d); 394 for (Route r : new HashSet<Route> (d.getRoutes ())) 395 { 396 final Route oppRoute = np.addRoute(opDemand, r.getCarriedTraffic(), r.getOccupiedCapacity() , oppositeSeqLinks (r.getSeqLinks()), null); 397 opposite_r.put(r,oppRoute); opposite_r.put(oppRoute,r); 398 } 399 } 400 return Pair.of(opposite_d,opposite_r); 401 } 402 403 private void initializeSRGs (NetPlan np) 404 { 405 np.removeAllSRGs(); 406 if (tcfa_srgType.getString ().equals("perBidirectionalLinkBundle")) 407 { 408 for (Node n1 : np.getNodes()) for (Node n2 : np.getNodes()) if (n1.getIndex () < n2.getIndex()) 409 { 410 final double linkLengthKm = np.getNodePairLinks(n1, n2,false).iterator().next().getLengthInKm(); 411 final SharedRiskGroup srg = np.addSRG(tcfa_srgMttfPer1000Km_hrs.getDouble () * linkLengthKm / 1000, tcfa_srgMttr_hrs.getDouble (), null); 412 for (Link e : np.getNodePairLinks(n1, n2,true)) srg.addLink(e); 413 } 414 } 415 else if (tcfa_srgType.getString ().equals("noFailure")) 416 { 417 } else throw new Net2PlanException ("Wrong SRG type"); 418 } 419 420 private List<Link> oppositeSeqLinks (List<Link> s) 421 { 422 LinkedList<Link> oppList = new LinkedList<Link> (); 423 for (Link e : s) oppList.addFirst(oppositeLink(e)); 424 return (List<Link>) oppList; 425 } 426 427 private void checkSolution (NetPlan np) 428 { 429 if (np.getDemandsBlocked().size() != 0) 430 { 431 System.out.println("np.getDemandsBlocked(): " + np.getDemandsBlocked()); 432 System.out.println("np.getDemandOfferedTrafficMap(): " + np.getVectorDemandOfferedTraffic()); 433 System.out.println("np.getDemandBlockedTrafficMap(): " + np.getVectorDemandBlockedTraffic()); 434 throw new RuntimeException ("Bad"); 435 } 436 if (np.getLinksOversubscribed().size() != 0) 437 { 438 System.out.println("np.getLinksOversubscribed(): " + np.getLinksOversubscribed()); 439 System.out.println("np.getLinkCapacityMap(): " + np.getVectorLinkCapacity()); 440 System.out.println("np.getLinkCarriedTrafficMap(): " + np.getVectorLinkCarriedTraffic()); 441 throw new RuntimeException ("Bad"); 442 } 443 444 /* Check bidirectional topology */ 445 for (Node n1 : np.getNodes()) 446 for (Node n2 : np.getNodes()) 447 if (n1.getIndex () > n2.getIndex ()) 448 { 449 Set<Link> thisLinks = np.getNodePairLinks(n1, n2,false); 450 Set<Link> oppLinks = np.getNodePairLinks(n2, n1,false); 451 if (thisLinks.size() > 1) throw new RuntimeException ("Bad"); 452 if (oppLinks.size() > 1) throw new RuntimeException ("Bad"); 453 if (tcfa_bidirectionalLinks.getBoolean()) 454 { 455 if (thisLinks.size() != oppLinks.size()) throw new RuntimeException ("Bad"); 456 if (thisLinks.size() > 0) 457 if (thisLinks.iterator().next().getCapacity() != oppLinks.iterator().next().getCapacity() ) throw new RuntimeException ("Bad"); 458 } 459 } 460 461 /* Check bidirectional routes */ 462 for (Route r : np.getRoutes()) 463 { 464 final Route oppRoute = opposite_r.get(r); 465 if (!np.getRoutes().contains(oppRoute)) throw new RuntimeException ("Bad"); 466 if (r.getCarriedTraffic() != oppRoute.getCarriedTraffic()) throw new RuntimeException ("Bad"); 467 } 468 469 if (tcfa_recoveryType.getString ().equals("1+1")) 470 { // one prot segment, and link disjoint 471 for (Route r : np.getRoutesAreNotBackup()) 472 { 473 if (r.getBackupRoutes().size() != 1) throw new RuntimeException ("Bad: " + r.getBackupRoutes().size()); 474 final Route backupRoute = r.getBackupRoutes().get(0); 475 List<Link> seqLinks = new ArrayList<Link> (r.getSeqLinks()); 476 seqLinks.retainAll(backupRoute.getSeqLinks()); 477 if (!seqLinks.isEmpty()) 478 { 479 System.out.println ("Route : "+ r + " links: " + r.getSeqLinks() + ", backup route " + backupRoute + " links: " + backupRoute.getSeqLinks() + ", route carried traffic: " + r.getCarriedTraffic() + ", backup occupied capacity: " + backupRoute.getOccupiedCapacity()); 480 throw new RuntimeException ("Bad"); 481 } 482 } 483 } 484 485 } 486 487 private DoubleMatrix1D jomStep_shared (Set<Integer> demandsChange , DoubleMatrix1D maxPe , DoubleMatrix1D x_r) 488 { 489 final long initTimeBeforeCreatingProgram = System.nanoTime(); 490 if (demandsChange.isEmpty()) throw new RuntimeException ("Bad"); 491 final int [] dChange = IntUtils.toArray(demandsChange); 492 int [] rChange = new int [0]; for (int d : dChange) rChange = IntUtils.concatenate(rChange, routeList_d [d]); 493 final int Rrest = rChange.length; 494 x_r.viewSelection(rChange).assign(0); 495 DoubleMatrix2D A_dRestrRest = A_dr.viewSelection(dChange, rChange); 496 DoubleMatrix2D A_erRest = A_er.viewSelection(null, rChange); 497 DoubleMatrix2D A_rRests = A_rs.viewSelection(rChange,null); 498 DoubleMatrix1D occupiedWithoutChangingR_e = A_er.zMult (x_r,null); 499 DoubleMatrix2D Abid_rRestrRest = DoubleFactory2D.sparse.make(Rrest,Rrest); 500 for (int rRest = 0 ; rRest < Rrest ; rRest ++) 501 { 502 final int r = rChange [rRest]; 503 final int opp_r = opposite_r.get(netPlan.getRoute(r)).getIndex (); 504 final int [] oppRrest = IntUtils.find(rChange, opp_r, SearchType.ALL); 505 if (oppRrest.length != 1) throw new RuntimeException ("Bad"); 506 Abid_rRestrRest.set(rRest , oppRrest [0] , 1.0); Abid_rRestrRest.set(oppRrest [0], rRest , 1); 507 } 508 OptimizationProblem op = new OptimizationProblem(); 509 op.setInputParameter("R",R); 510 op.setInputParameter("U",tcfa_linkCapacity_numCirc.getInt ()); 511 op.setInputParameter("c_e", linkCost_e.toArray() , "row"); 512 op.setInputParameter("c", tcfa_circuitCost.getDouble ()); 513 op.setInputParameter("d3Cost", tcfa_costNodeDegreeHigherThan2.getDouble ()); 514 op.setInputParameter("onesS", DoubleUtils.ones(1+nSRGs) , "row"); 515 op.setInputParameter("onesE", DoubleUtils.ones(Efm) , "row"); 516 op.setInputParameter("A_dRestrRest", new DoubleMatrixND (A_dRestrRest)); 517 op.setInputParameter("h_dRest", numCircH_d.viewSelection(dChange).toArray(), "row"); 518 op.setInputParameter("A_rRests", new DoubleMatrixND (A_rRests)); 519 op.setInputParameter("A_erRest", new DoubleMatrixND (A_erRest)); 520 op.setInputParameter("Aout_ne", new DoubleMatrixND (Aout_ne)); 521 op.setInputParameter("Abid_rRestrRest", new DoubleMatrixND (Abid_rRestrRest)); 522 op.setInputParameter("occup_e", occupiedWithoutChangingR_e.toArray(), "row"); 523 524 op.addDecisionVariable("d3_n", true, new int[] { 1, N }, 0, 1); 525 op.addDecisionVariable("p_e", true, new int[] { 1, Efm }, DoubleUtils.zeros(Efm) , (maxPe == null)? DoubleUtils.constantArray(Efm, Double.MAX_VALUE) : maxPe.toArray()); 526 op.addDecisionVariable("x_rRest", true, new int[] { 1, Rrest}, 0 , Double.MAX_VALUE); /* 1 if there is a link from node i to node j, 0 otherwise */ 527 528 op.setObjectiveFunction("minimize", "sum(c_e .* p_e) + c * sum (x_rRest) + d3Cost * sum(d3_n)"); 529 op.addConstraint("A_dRestrRest * diag(x_rRest) * A_rRests >= h_dRest' * onesS"); /* the flow-conservation constraints (NxD constraints) */ 530 op.addConstraint("A_erRest * x_rRest' + occup_e' <= U * p_e'"); /* the capacity constraints (E constraints) */ 531 op.addConstraint("Aout_ne * p_e' <= 2 + R * d3_n'"); /* the capacity constraints (E constraints) */ 532 op.addConstraint("x_rRest == x_rRest * Abid_rRestrRest"); 533 if (tcfa_bidirectionalLinks.getBoolean()) { op.setInputParameter("Abid_ee", new DoubleMatrixND (Abid_ee)); op.addConstraint("p_e == p_e * Abid_ee"); } 534 535 stat_totalTimeCreateProgramsSecs += eTime (initTimeBeforeCreatingProgram); 536 537 double solverTimeAllowed = algorithm_maxSolverTimeInSeconds.getDouble(); 538 do 539 { 540 final long t = System.nanoTime(); 541 try 542 { 543 stat_numSolverCalls ++; op.solve(algorithm_solverName.getString() , "solverLibraryName", algorithm_solverLibraryName.getString () , "maxSolverTimeInSeconds" , solverTimeAllowed); 544 } catch (Exception e) { System.out.println ("-- EXTRA TIME FOR SOLVER, NOW: " + solverTimeAllowed); solverTimeAllowed += 2; stat_totalTimeSolverSecs += eTime(t); continue;} 545 stat_totalTimeSolverSecs += eTime(t); 546 if (solverTimeAllowed != algorithm_maxSolverTimeInSeconds.getDouble()) System.out.println ("-- EXTRA TIME FOR SOLVER, NOW: " + solverTimeAllowed); 547 solverTimeAllowed *= 2; // duplicate the time if not feasible solution is found 548 } while (!op.solutionIsFeasible()); 549 stat_numSolverCallsOk ++; 550 final double [] new_x_rRest = op.getPrimalSolution("x_rRest").to1DArray(); 551 x_r.viewSelection(rChange).assign(new_x_rRest); 552 return x_r; 553 } 554 555 private Pair<DoubleMatrix1D,DoubleMatrix1D> jomStep_11 (Set<Integer> demandsChange , DoubleMatrix1D maxPe , DoubleMatrix1D x_r , DoubleMatrix1D x2_r) 556 { 557// System.out.println ("demandsChange :" + demandsChange); 558 final long initTimeBeforeCreatingProgram = System.nanoTime(); 559 560 if (demandsChange.isEmpty()) throw new RuntimeException ("Bad"); 561 final int [] dChange = IntUtils.toArray(demandsChange); 562// System.out.println ("dChange :" + Arrays.toString(dChange)); 563 int [] rChange = new int [0]; for (int d : dChange) rChange = IntUtils.concatenate(rChange, routeList_d [d]); 564 final int Rrest = rChange.length; 565 final int Drest = dChange.length; 566 x_r.viewSelection(rChange).assign(0); 567 x2_r.viewSelection(rChange).assign(0); 568 DoubleMatrix2D A_dRestrRest = A_dr.viewSelection(dChange, rChange); 569 DoubleMatrix2D A_erRest = A_er.viewSelection(null, rChange); 570 DoubleMatrix2D A_rRests = A_rs.viewSelection(rChange,null); 571 DoubleMatrix1D occupiedWithoutChangingR_e = A_er.zMult (x_r,null); 572 DoubleMatrix1D backup_occupiedWithoutChangingR_e = A_er.zMult (x2_r,null); 573 for (int e = 0;e < Efm; e ++) occupiedWithoutChangingR_e.set(e, occupiedWithoutChangingR_e.get(e) + backup_occupiedWithoutChangingR_e.get(e)); 574 DoubleMatrix2D Abid_rRestrRest = DoubleFactory2D.sparse.make(Rrest,Rrest); 575 for (int rRest = 0 ; rRest < Rrest ; rRest ++) 576 { 577 final int r = rChange [rRest]; final int opp_r = opposite_r.get(netPlan.getRoute (r)).getIndex (); 578 final int [] oppRrest = IntUtils.find(rChange, opp_r, SearchType.ALL); if (oppRrest.length != 1) throw new RuntimeException ("Bad"); 579 Abid_rRestrRest.set(rRest , oppRrest [0] , 1.0); Abid_rRestrRest.set(oppRrest [0], rRest , 1); 580 } 581 582 OptimizationProblem op = new OptimizationProblem(); 583 op.setInputParameter("R",R); 584 op.setInputParameter("U",tcfa_linkCapacity_numCirc.getInt ()); 585 op.setInputParameter("c_e", linkCost_e.toArray() , "row"); 586 op.setInputParameter("c", tcfa_circuitCost.getDouble ()); 587 op.setInputParameter("d3Cost", tcfa_costNodeDegreeHigherThan2.getDouble ()); 588 op.setInputParameter("onesS", DoubleUtils.ones(1+nSRGs) , "row"); 589 op.setInputParameter("onesE", DoubleUtils.ones(Efm) , "row"); 590 op.setInputParameter("A_dRestrRest", new DoubleMatrixND (A_dRestrRest)); 591 op.setInputParameter("h_dRest", numCircH_d.viewSelection(dChange).toArray(), "row"); 592 op.setInputParameter("A_rRests", new DoubleMatrixND (A_rRests)); 593 op.setInputParameter("A_erRest", new DoubleMatrixND (A_erRest)); 594 op.setInputParameter("Aout_ne", new DoubleMatrixND (Aout_ne)); 595 op.setInputParameter("Abid_rRestrRest", new DoubleMatrixND (Abid_rRestrRest)); 596 op.setInputParameter("occup_e", occupiedWithoutChangingR_e.toArray(), "row"); 597 598 op.addDecisionVariable("d3_n", true, new int[] { 1, N }, 0, 1); 599 op.addDecisionVariable("p_e", true, new int[] { 1, Efm }, DoubleUtils.zeros(Efm) , (maxPe == null)? DoubleUtils.constantArray(Efm, Double.MAX_VALUE) : maxPe.toArray()); 600 op.addDecisionVariable("x_rRest", true, new int[] { 1, Rrest}, 0 , 1); 601 op.addDecisionVariable("x2_rRest", true, new int[] { 1, Rrest}, 0 , 1); 602 603 op.setObjectiveFunction("minimize", "sum(c_e .* p_e) + d3Cost * sum(d3_n)"); 604 op.addConstraint("A_dRestrRest * x_rRest' == h_dRest'"); /* the flow-conservation constraints (NxD constraints) */ 605 op.addConstraint("A_dRestrRest * x2_rRest' == h_dRest'"); /* the flow-conservation constraints (NxD constraints) */ 606 op.addConstraint("A_erRest * (x_rRest+x2_rRest)' + occup_e' <= U * p_e'"); /* the capacity constraints (E constraints) */ 607 op.addConstraint("Aout_ne * p_e' <= 2 + R*d3_n'"); /* the capacity constraints (E constraints) */ 608 op.addConstraint("A_dRestrRest * diag(x_rRest+x2_rRest) * A_erRest' <= 1"); 609 op.addConstraint("x_rRest == x_rRest * Abid_rRestrRest"); 610 op.addConstraint("x2_rRest == x2_rRest * Abid_rRestrRest"); 611 if (tcfa_bidirectionalLinks.getBoolean()) { op.setInputParameter("Abid_ee", new DoubleMatrixND (Abid_ee)); op.addConstraint("p_e == p_e * Abid_ee"); } 612 613// System.out.println("Abid_rr sum filas: " + Abid_rRestrRest.zMult(DoubleFactory1D.dense.make(Rrest,1), null)); 614// System.out.println("Abid_rr sum cols: " + Abid_rRestrRest.zMult(DoubleFactory1D.dense.make(Rrest,1), null , 1 , 0 , true)); 615// System.out.println("Abid_rr non zeros: " + Abid_rRestrRest.zSum()); 616 stat_totalTimeCreateProgramsSecs += eTime (initTimeBeforeCreatingProgram); 617 618 double solverTimeAllowed = algorithm_maxSolverTimeInSeconds.getDouble (); 619 do 620 { 621 final long t = System.nanoTime(); 622 try 623 { 624 stat_numSolverCalls ++; op.solve(algorithm_solverName.getString() , "solverLibraryName", algorithm_solverLibraryName.getString () , "maxSolverTimeInSeconds" , solverTimeAllowed); 625 } catch (Exception e) { System.out.println ("-- EXTRA TIME FOR SOLVER, NOW: " + solverTimeAllowed); solverTimeAllowed += 2; stat_totalTimeSolverSecs += eTime(t); continue; } 626 if (solverTimeAllowed != algorithm_maxSolverTimeInSeconds.getDouble ()) System.out.println ("-- EXTRA TIME FOR SOLVER, NOW: " + solverTimeAllowed); 627 stat_totalTimeSolverSecs += eTime(t); 628 solverTimeAllowed *= 2; // duplicate the time if not feasible solution is found 629 //System.out.println ("Time to create program: " + (1E-9*(t-initTimeBeforeCreatingProgram)) + ", solver time " + ((System.nanoTime()-t)*1E-9) + " s ; "); 630 } while (!op.solutionIsFeasible()); 631 stat_numSolverCallsOk ++; 632 final double[] new_x_rRest = op.getPrimalSolution("x_rRest").to1DArray(); 633 final double[] new_x2_rRest = op.getPrimalSolution("x2_rRest").to1DArray(); 634 635 x_r.viewSelection(rChange).assign(new_x_rRest); 636 x2_r.viewSelection(rChange).assign(new_x2_rRest); 637 return Pair.of(x_r,x2_r); 638 } 639 640 private DoubleMatrix2D jomStep_restoration (Set<Integer> demandsChange , DoubleMatrix1D maxPe , DoubleMatrix2D x_rs) 641 { 642 final long initTimeBeforeCreatingProgram = System.nanoTime(); 643 if (demandsChange.isEmpty()) throw new RuntimeException ("Bad"); 644 final int [] dChange = IntUtils.toArray(demandsChange); 645 int [] rChange = new int [0]; for (int d : dChange) rChange = IntUtils.concatenate(rChange, routeList_d [d]); 646 final int Rrest = rChange.length; 647 final int Drest = dChange.length; 648 x_rs.viewSelection(rChange,null).assign(0); 649// DoubleMatrix2D A_dRestrRest = A_dr.viewSelection(dChange, rChange); 650 DoubleMatrix2D A_dRestrRest = DoubleFactory2D.sparse.make(Drest,Rrest); 651 for (int rRest = 0 ; rRest < Rrest ; rRest ++) 652 { 653 final int r = rChange [rRest]; final int dRest [] = IntUtils.find(dChange, netPlan.getRoute (r).getDemand().getIndex () , SearchType.ALL); 654 if (dRest.length != 1) throw new RuntimeException ("Bad"); 655 A_dRestrRest.set(dRest [0], rRest , 1.0); 656 } 657 658 DoubleMatrix2D A_erRest = A_er.viewSelection(null, rChange); 659 DoubleMatrix2D A_rRests = A_rs.viewSelection(rChange,null); 660 DoubleMatrix2D occupiedWithoutChangingR_es = A_er.zMult (x_rs,null); 661 DoubleMatrix2D Abid_rRestrRest = DoubleFactory2D.sparse.make(Rrest,Rrest); 662 for (int rRest = 0 ; rRest < Rrest ; rRest ++) 663 { 664 final int r = rChange [rRest]; final int opp_r = opposite_r.get(netPlan.getRoute (r)).getIndex (); 665 final int [] oppRrest = IntUtils.find(rChange, opp_r, SearchType.ALL); 666 if (oppRrest.length != 1) throw new RuntimeException ("Bad"); 667 Abid_rRestrRest.set(rRest , oppRrest [0] , 1.0); Abid_rRestrRest.set(oppRrest [0], rRest , 1); 668 } 669 670 OptimizationProblem op = new OptimizationProblem(); 671 op.setInputParameter("R",R); 672 op.setInputParameter("U",tcfa_linkCapacity_numCirc.getInt ()); 673 op.setInputParameter("c_e", linkCost_e.toArray() , "row"); 674 op.setInputParameter("c", tcfa_circuitCost.getDouble ()); 675 op.setInputParameter("d3Cost", tcfa_costNodeDegreeHigherThan2.getDouble ()); 676 op.setInputParameter("onesS", DoubleUtils.ones(1+nSRGs) , "row"); 677 op.setInputParameter("onesE", DoubleUtils.ones(Efm) , "row"); 678 op.setInputParameter("A_dRestrRest", new DoubleMatrixND (A_dRestrRest)); 679 op.setInputParameter("h_dRest", numCircH_d.viewSelection(dChange).toArray(), "row"); 680 op.setInputParameter("A_rRests", new DoubleMatrixND (A_rRests)); 681 op.setInputParameter("A_erRest", new DoubleMatrixND (A_erRest)); 682 op.setInputParameter("Aout_ne", new DoubleMatrixND (Aout_ne)); 683 op.setInputParameter("Abid_rRestrRest", new DoubleMatrixND (Abid_rRestrRest)); 684 op.setInputParameter("occup_es", occupiedWithoutChangingR_es.toArray()); 685 686 op.addDecisionVariable("d3_n", true, new int[] { 1, N }, 0, 1); 687 op.addDecisionVariable("p_e", true, new int[] { 1, Efm }, DoubleUtils.zeros(Efm) , (maxPe == null)? DoubleUtils.constantArray(Efm, Double.MAX_VALUE) : maxPe.toArray()); 688 op.addDecisionVariable("x_rRests", true, new int[] { Rrest, 1+nSRGs}, 0 , Double.MAX_VALUE); /* 1 if there is a link from node i to node j, 0 otherwise */ 689 690 op.setObjectiveFunction("minimize", "sum(c_e .* p_e) + d3Cost * sum(d3_n)"); 691 op.addConstraint("A_dRestrRest * x_rRests(all,0) == h_dRest'"); /* the flow-conservation constraints (NxD constraints) */ 692 op.addConstraint("A_dRestrRest * (x_rRests .* A_rRests) >= h_dRest' * onesS"); /* the flow-conservation constraints (NxD constraints) */ 693 op.addConstraint("A_erRest * x_rRests + occup_es <= U * p_e' * onesS"); /* the capacity constraints (E constraints) */ 694 op.addConstraint("Aout_ne * p_e' <= 2 + R*d3_n'"); /* the capacity constraints (E constraints) */ 695 op.addConstraint("x_rRests == Abid_rRestrRest * x_rRests"); 696 op.addConstraint("x_rRests >= diag(x_rRests(all,0)) * A_rRests"); // if not affected by failure, do not change 697 if (tcfa_bidirectionalLinks.getBoolean()) { op.setInputParameter("Abid_ee", new DoubleMatrixND (Abid_ee)); op.addConstraint("p_e == p_e * Abid_ee"); } 698 699 stat_totalTimeCreateProgramsSecs += eTime (initTimeBeforeCreatingProgram); 700 701 double solverTimeAllowed = algorithm_maxSolverTimeInSeconds.getDouble (); 702 do 703 { 704 final long t = System.nanoTime(); 705 try { stat_numSolverCalls ++; op.solve(algorithm_solverName.getString() , "solverLibraryName", algorithm_solverLibraryName.getString () , "maxSolverTimeInSeconds" , solverTimeAllowed); } catch (Exception e) { System.out.println ("-- EXTRA TIME FOR SOLVER, NOW: " + solverTimeAllowed); solverTimeAllowed += 2; stat_totalTimeSolverSecs += eTime(t); continue;} 706 if (solverTimeAllowed != algorithm_maxSolverTimeInSeconds.getDouble ()) System.out.println ("-- EXTRA TIME FOR SOLVER, NOW: " + solverTimeAllowed); 707 stat_totalTimeSolverSecs += eTime(t); 708 solverTimeAllowed *= 2; // duplicate the time if not feasible solution is found 709 //System.out.println ("Time to create program: " + (1E-9*(t-initTimeBeforeCreatingProgram)) + ", solver time " + ((System.nanoTime()-t)*1E-9) + " s ; "); 710 } while (!op.solutionIsFeasible()); 711 stat_numSolverCallsOk ++; 712 final DoubleMatrix2D new_x_rRests = op.getPrimalSolution("x_rRests").view2D(); 713 final DoubleMatrix1D new_pe = DoubleFactory1D.dense.make(op.getPrimalSolution("p_e").to1DArray()); 714 x_rs.viewSelection(rChange, null).assign(new_x_rRests); 715 return x_rs; 716 } 717 718 private DoubleMatrix1D greedyAndLocalSearch_shared (long algorithmEndtime , NetPlan np) 719 { 720 final long initGreedy = System.nanoTime(); 721 ArrayList<Pair<Node,Node>> shuffledNodePairs = new ArrayList<Pair<Node,Node>> (N*(N-1)/2); 722 for (Node n1 : np.getNodes ()) for (Node n2 : np.getNodes ()) if (n1.getIndex () < n2.getIndex ()) shuffledNodePairs.add(Pair.of(n1, n2)); 723 Collections.shuffle(shuffledNodePairs , rng); 724 DoubleMatrix1D current_xr = DoubleFactory1D.dense.make(R); 725 for (Pair<Node,Node> nodePair : shuffledNodePairs) 726 { 727 Set<Integer> thisDemand = new HashSet<Integer> (); 728 for (Demand d : np.getNodePairDemands(nodePair.getFirst(), nodePair.getSecond() , true)) 729 thisDemand.add(d.getIndex()); 730// System.out.println("thsiDemand: " + thisDemand); 731 if (jomStep_shared(thisDemand , null , current_xr) == null) throw new RuntimeException ("Returned null"); 732 } 733 DoubleMatrix1D current_pe = A_er.zMult(current_xr, null); current_pe.assign(DoubleFunctions.div(tcfa_linkCapacity_numCirc.getInt ())).assign(DoubleFunctions.ceil); 734 double current_cost = computeCost_shared(current_xr, current_pe); 735 //DoubleMatrix1D best_xr = current_xr.copy(); DoubleMatrix1D best_pe = current_pe.copy(); double bestCost = ; 736 737 //System.out.println("---- Greedy solution Time " + (1E-9*(System.nanoTime() - initGreedy)) +", Cost : "+ current_cost + ", num links: " + current_pe.zSum()); 738 739 while (System.nanoTime() < algorithmEndtime) 740 { 741 //DoubleMatrix1D bestNeighbor_xr = null; DoubleMatrix1D bestNeighbor_pe = null; double bestNeighborCost = Double.MAX_VALUE; Pair<Long,Long> bestNeighborNodePair = null; 742 Collections.shuffle(shuffledNodePairs ,rng); 743 final long initLSIteration = System.nanoTime(); 744 745 boolean improvedSolution = false; 746 for (Pair<Node,Node> nodePair : shuffledNodePairs) 747 { 748// System.out.println("Pair: " + nodePair + ". Tabu list: " + tabuList_n1n2 + ", IS TABU: " + tabuList_n1n2.contains(nodePair)); 749 Set<Integer> demandsToChange = new HashSet<Integer> (); 750 for (Demand d : np.getNodePairDemands(nodePair.getFirst(), nodePair.getSecond() , true)) 751 demandsToChange.add(d.getIndex ()); 752 DoubleMatrix1D thisNeighbor_xr = current_xr.copy(); // do not modify the original one 753 if (jomStep_shared(demandsToChange , null , thisNeighbor_xr) == null) throw new RuntimeException ("Returned null"); 754 DoubleMatrix1D thisNeighbor_pe = A_er.zMult(thisNeighbor_xr, null); thisNeighbor_pe.assign(DoubleFunctions.div(tcfa_linkCapacity_numCirc.getInt ())).assign(DoubleFunctions.ceil); 755 final double thisNeighborCost = computeCost_shared (thisNeighbor_xr , thisNeighbor_pe); 756 if (thisNeighborCost < current_cost) 757 { 758 current_xr = thisNeighbor_xr; current_pe = thisNeighbor_pe; current_cost = thisNeighborCost; improvedSolution = true; 759 System.out.println("NEW BEST COST: " + current_cost + ", num links: " + current_pe.zSum()); 760 break; 761 } 762 } 763 764 //System.out.println("- Local search TIME: " + ((System.nanoTime()-initLSIteration)*1e-9) + ", current cost: " + current_cost + ", num links: " + current_pe.zSum() + ", IMPROVED: " + improvedSolution); 765 766 if (!improvedSolution) break; else stat_numLSIterationsReducingCost ++; // end grasp iteration 767 } 768 769 return current_xr; 770 } 771 772 private Pair<DoubleMatrix1D,DoubleMatrix1D> greedyAndLocalSearch_11 (long algorithmEndtime , NetPlan np) 773 { 774 final long initGreedy = System.nanoTime(); 775 ArrayList<Pair<Node,Node>> shuffledNodePairs = new ArrayList<Pair<Node,Node>> (N*(N-1)/2); 776 for (Node n1 : np.getNodes ()) for (Node n2 : np.getNodes ()) if (n1.getIndex () < n2.getIndex ()) shuffledNodePairs.add(Pair.of(n1, n2)); 777 Collections.shuffle(shuffledNodePairs , rng); 778 DoubleMatrix1D current_xr = DoubleFactory1D.dense.make(R); 779 DoubleMatrix1D current_x2r = DoubleFactory1D.dense.make(R); 780 for (Pair<Node,Node> nodePair : shuffledNodePairs) 781 { 782 Set<Integer> thisDemand = new HashSet<Integer> (); 783 for (Demand d : np.getNodePairDemands(nodePair.getFirst(), nodePair.getSecond() , true)) 784 thisDemand.add(d.getIndex()); 785 final long t = System.nanoTime(); if (jomStep_11(thisDemand , null , current_xr , current_x2r) == null) throw new RuntimeException ("Returned null"); 786 //System.out.println("Node pair " + nodePair + " time increasing it: " + (1E-9*(System.nanoTime()-t)) + ", num demands: " + thisDemand.size()); 787 } 788 DoubleMatrix1D current_pe = computePe_11 (current_xr , current_xr); 789 double current_cost = computeCost_11(current_xr, current_x2r , current_pe); 790 791 //System.out.println("---- Greedy solution Time " + (1E-9*(System.nanoTime() - initGreedy)) +", Cost : "+ current_cost + ", num links: " + current_pe.zSum()); 792 793 while (System.nanoTime() < algorithmEndtime) 794 { 795 Collections.shuffle(shuffledNodePairs ,rng); 796 final long initLSIteration = System.nanoTime(); 797 798 boolean improvedSolution = false; 799 for (Pair<Node,Node> nodePair : shuffledNodePairs) 800 { 801 Set<Integer> demandsToChange = new HashSet<Integer> (); 802 for (Demand d : np.getNodePairDemands(nodePair.getFirst(), nodePair.getSecond() , true)) 803 demandsToChange.add(d.getIndex()); 804 DoubleMatrix1D thisNeighbor_xr = current_xr.copy(); // do not modify the original one 805 DoubleMatrix1D thisNeighbor_x2r = current_x2r.copy(); // do not modify the original one 806 if (jomStep_11(demandsToChange , null , thisNeighbor_xr , thisNeighbor_x2r) == null) throw new RuntimeException ("Returned null"); 807 DoubleMatrix1D thisNeighbor_pe = computePe_11(thisNeighbor_xr, thisNeighbor_x2r); 808 final double thisNeighborCost = computeCost_11 (thisNeighbor_xr , thisNeighbor_x2r , thisNeighbor_pe); 809 if (thisNeighborCost < current_cost) 810 { 811 current_xr = thisNeighbor_xr; current_x2r = thisNeighbor_x2r; current_pe = thisNeighbor_pe; current_cost = thisNeighborCost; improvedSolution = true; 812 System.out.println("NEW BEST COST: " + current_cost + ", num links: " + current_pe.zSum()); 813 break; 814 } 815 } 816 817 //System.out.println("- Local search TIME: " + ((System.nanoTime()-initLSIteration)*1e-9) + ", current cost: " + current_cost + ", num links: " + current_pe.zSum() + ", IMPROVED: " + improvedSolution); 818 819 if (!improvedSolution) break; else stat_numLSIterationsReducingCost ++; // end grasp iteration 820 } 821 822 return Pair.of(current_xr , current_x2r); 823 } 824 private DoubleMatrix2D greedyAndLocalSearch_restoration (long algorithmEndtime , NetPlan np) 825 { 826 final long initGreedy = System.nanoTime(); 827 ArrayList<Pair<Node,Node>> shuffledNodePairs = new ArrayList<Pair<Node,Node>> (N*(N-1)/2); 828 for (Node n1 : np.getNodes ()) for (Node n2 : np.getNodes ()) if (n1.getIndex () < n2.getIndex()) shuffledNodePairs.add(Pair.of(n1, n2)); 829 Collections.shuffle(shuffledNodePairs , rng); 830 DoubleMatrix2D current_xrs = DoubleFactory2D.dense.make(R,1+nSRGs); 831 for (Pair<Node,Node> nodePair : shuffledNodePairs) 832 { 833 Set<Integer> thisDemand = new HashSet<Integer> (); 834 for (Demand d : np.getNodePairDemands(nodePair.getFirst(), nodePair.getSecond(),true)) 835 thisDemand.add(d.getIndex ()); 836// System.out.println("thsiDemand: " + thisDemand); 837 if (jomStep_restoration(thisDemand , null , current_xrs) == null) throw new RuntimeException ("Returned null"); 838 } 839 DoubleMatrix1D current_pe = computePe_restoration(current_xrs); 840 double current_cost = computeCost_shared(current_xrs.viewColumn(0), current_pe); 841 842 //System.out.println("---- Greedy solution Time " + (1E-9*(System.nanoTime() - initGreedy)) +", Cost : "+ current_cost + ", num links: " + current_pe.zSum() + ", SRGs: " + nSRGs); 843 844 while (System.nanoTime() < algorithmEndtime) 845 { 846 Collections.shuffle(shuffledNodePairs ,rng); 847 final long initLSIteration = System.nanoTime(); 848 849 boolean improvedSolution = false; 850 for (Pair<Node,Node> nodePair : shuffledNodePairs) 851 { 852 Set<Integer> demandsToChange = new HashSet<Integer> (); 853 for (Demand d : np.getNodePairDemands(nodePair.getFirst(), nodePair.getSecond() , true)) 854 demandsToChange.add(d.getIndex()); 855 DoubleMatrix2D thisNeighbor_xrs = current_xrs.copy(); // do not modify the original one 856 if (jomStep_restoration(demandsToChange , null , thisNeighbor_xrs) == null) throw new RuntimeException ("Returned null"); 857 DoubleMatrix1D thisNeighbor_pe = computePe_restoration(thisNeighbor_xrs); 858 final double thisNeighborCost = computeCost_shared (thisNeighbor_xrs.viewColumn(0) , thisNeighbor_pe); 859 if (thisNeighborCost < current_cost) 860 { 861 current_xrs = thisNeighbor_xrs; current_pe = thisNeighbor_pe; current_cost = thisNeighborCost; improvedSolution = true; 862 System.out.println("NEW BEST COST: " + current_cost + ", num links: " + current_pe.zSum()); 863 break; 864 } 865 } 866 867 //System.out.println("- Local search TIME: " + ((System.nanoTime()-initLSIteration)*1e-9) + ", current cost: " + current_cost + ", num links: " + current_pe.zSum() + ", IMPROVED: " + improvedSolution); 868 869 if (!improvedSolution) break; else stat_numLSIterationsReducingCost ++; // end grasp iteration 870 } 871 872 return current_xrs; 873 } 874 875 private DoubleMatrix1D computePe_11 (DoubleMatrix1D x_r , DoubleMatrix1D x2_r) 876 { 877 DoubleMatrix1D p_e = A_er.zMult(x_r, null); 878 DoubleMatrix1D backup_occup_e = A_er.zMult(x2_r, null); 879 for (int e = 0 ; e < Efm ; e ++) p_e.set(e , p_e.get(e) + backup_occup_e.get(e)); 880 p_e.assign(DoubleFunctions.div(tcfa_linkCapacity_numCirc.getInt ())).assign(DoubleFunctions.ceil); 881 return p_e; 882 } 883 private DoubleMatrix1D computePe_restoration (DoubleMatrix2D x_rs) 884 { 885 DoubleMatrix2D p_es = A_er.zMult(x_rs, null); DoubleMatrix1D p_e = DoubleFactory1D.dense.make(Efm); 886 for (int e = 0; e < Efm ; e ++) p_e.set(e , p_es.viewRow(e).getMaxLocation() [0]); // the maximum per state s 887 p_e.assign(DoubleFunctions.div(tcfa_linkCapacity_numCirc.getInt ())).assign(DoubleFunctions.ceil); 888 return p_e; 889 } 890 891 private double eTime (long init) { return 1E-9*(System.nanoTime() - init); } 892 893 private static int [] getIndexes (Collection<? extends NetworkElement> col) { final int [] res = new int [col.size ()]; int cont = 0; for (NetworkElement el : col) res [cont++] = el.getIndex (); return res; } 894 895 896}