001package com.net2plan.examples.general.offline; 002/******************************************************************************* 003 * Copyright (c) 2017 Pablo Pavon Marino and others. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the 2-clause BSD License 006 * which accompanies this distribution, and is available at 007 * https://opensource.org/licenses/BSD-2-Clause 008 * 009 * Contributors: 010 * Pablo Pavon Marino and others - initial API and implementation 011 *******************************************************************************/ 012 013 014import cern.colt.matrix.tdouble.DoubleFactory2D; 015import cern.colt.matrix.tdouble.DoubleMatrix2D; 016import com.net2plan.interfaces.networkDesign.*; 017import com.net2plan.libraries.WDMUtils; 018import com.net2plan.utils.Constants.OrderingType; 019import com.net2plan.utils.Constants.RoutingType; 020import com.net2plan.utils.*; 021 022import java.util.*; 023 024/** 025 * Algorithm based on an heuristic solving the Routing, Spectrum, Modulation Assignment (RSMA) problem with regenerator placement, 026 * in flexi (elastic) or fixed grid optical WDM networks, with or without fault tolerance and/or latency requisites. 027 * 028 * <p>The input design typically has two layers (IP and WDM layers), according to the typical conventions in {@link com.net2plan.libraries.WDMUtils WDMUtils}. 029 * If the design has one single layer, it is first converted into a two-layer design: WDM layer taking the links (fibers) with no demands, 030 * IP layer taking the traffic demands, without IP links. Any previous routes are removed.</p> 031 * <p>The WDM layer is compatible with {@link com.net2plan.libraries.WDMUtils WDMUtils} Net2Plan 032 * library usual assumptions:</p> 033 * <ul> 034 * <li>Each network node is assumed to be an Optical Add/Drop Multiplexer WDM node</li> 035 * <li>Each network link at WDM layer is assumed to be an optical fiber.</li> 036 * <li>The spectrum in the fibers is assumed to be composed of a number of frequency slots. 037 * In fixed-grid network, each frequency slot would correspond to a wavelength channel. 038 * In flexi-grid networks, it is just a frequency slot, and lightpaths can occupy more than one. In any case, 039 * two lightpaths that use overlapping frequency slots cannot traverse the same fiber, since their signals would mix.</li> 040 * <li>No traffic demands initially exist at the WDM layer. In this algorithms, each lightpath is associated to a WDM demand </li> 041 * <li> Each traffic demand at the IP layer is a need to transmit an amount of Gbps between two nodes. 042 * A demand traffic can be carried using one or more lightpaths.</li> 043 * </ul> 044 * 045 * <p>Each lightpath (primary or backup) produced by the design is returned as a {@code Route} object.</p> 046 * 047 * <p>Each lightpath starts and ends in a transponder. The user is able to define a set of available transpoder types, so 048 * the design can create lightpaths using any combination of them. The information user-defined per transponder is:</p> 049 * <ul> 050 * <li>Line rate in Gbps (typically 10, 40, 100 in fixed-grid cases, and other multiples in flexi-grid networks).</li> 051 * <li>Cost</li> 052 * <li>Number of frequency slots occupied (for a given line rate, this depends on the modulation the transponder uses)</li> 053 * <li>Optical reach in km: Maximum allowed length in km of the lightpaths with this transponder. 054 * Higher distances can be reached using signal regenerators.</li> 055 * <li>Cost of a regenerator for this transponder. Regenerators can be placed at intermdiate nodes of the lightpath route, 056 * regenerate its optical signal, and then permit extending its reach. We consider that regenerators cannot change the 057 * frequency slots occupied by the lightpath (that is, they are not capable of wavelength conversion)</li> 058 * </ul> 059 * 060 * <p>We assume that all the fibers use the same wavelength grid, composed of a user-defined number of frequency slots. 061 * The user can also select a limit in the maximum propagation delay of a lightpath. </p> 062 * <p>The output design consists in the set of lightpaths to establish, in the 1+1 case also with a 1+1 lightpath each. 063 * Each lightpath is characterized by the transponder type used (which sets its line rate and number of occupied slots in the 064 * traversed fibers), the particular set of contiguous frequency slots occupied, and the set of signal regeneration points (if any). 065 * This information is stored in the {@code Route} object using the regular methods in WDMUTils, 066 * and can be retrieved in the same form (e.g. by a report showing the WDM network information). 067 * If a feasible solution is not found (one where all the demands are satisfied with the given constraints), a message is shown.</p>. 068 * 069 * <h2>Failure tolerance</h2> 070 * <p>The user can choose among three possibilities for designing the network:</p> 071 * <ul> 072 * <li>No failure tolerant: The lightpaths established should be enough to carry the traffic of all the demands when no failure 073 * occurs in the network, but any losses are accepted if the network suffers failures in links or nodes.</li> 074 * <li>Tolerant to single-SRG (Shared Risk Group) failures with static lightpaths: All the traffic demands should be satisfied using 075 * lightpaths, so that under any single-SRG failure (SRGs are taken from the input design), the surviving lightpaths are enough 076 * to carry the 100% of the traffic. Note that lightpaths are static, in the sense that they are not rerouted when affected by a 077 * failure (they just also fail), and the design should just overprovision the number of lightpaths to establish with that in mind.</li> 078 * <li>1+1 SRG-disjoint protection: This is another form to provide single-SRG failure tolerance. Each lightpath is backed up by 079 * a SRG-disjoint lightpath. The backup lightpath uses the same type of transponder 080 * as the primary (and thus the same line rate, an occupies the same number of slots), its path is SRG-disjoint, and the particular 081 * set of slots occupied can be different. </li> 082 * </ul> 083 * <h2>Use cases</h2> 084 * <p>This algorithm is quite general, and fits a number of use cases designing WDM networks, for instance:</p> 085 * <ul> 086 * <li>Single line rate, fixed grid networks: Then, one single type of transponder will be available, which occupies one frequency slot</li> 087 * <li>Mixed-Line Rate fixed-grid networks: In this case, several transponders can be available at different line rates and with different optical 088 * reaches. However, all of them occupy one slot (one wavelength channel)</li> 089 * <li>Single line rate, flexi-grid networks using varying-modulation transponders: Several transponders are available (or the same 090 * transponder with varying configurations), all of them with the same line rate, but thanks to the different usable modulations 091 * they can have different optical reaches and/or number of occupied slots.</li> 092 * <li>Multiple line rate, flexi-grid networks using Bandwidth Variable Transponders: Here, it is possible to use different transponders 093 * with different line rates, e.g. to reflect more sophisticated transponders which can have different configurations, varying its line rate, 094 * optical reach, and number of occupied slots.</li> 095 * <li>...</li> 096 * </ul> 097 * <h2>Some details of the algorithm</h2> 098 * <p>The algorithm is based on a heuristic. Initially, at most {@code k} paths are selected for each demand and transponder type. 099 * Then, in each iteration, the algorithm first orders the demands in descending order according to the traffic pending 100 * to be carried (if single-SRG failure tolerance is chosen, this is the average among all the 101 * states -no failure and single SRG failure). Then, all the transponder types and possible routes (or SRG-disjoint 1+1 pairs in the 102 * 1+1 case) are attempted for that demand, using a first-fit approach for the slots. If an RSA is found for more than one 103 * transponder and route, the one chosen is first, the one with best performance metric, and among them, the first transponder 104 * according to the order in which the user put it in the input parameter, and among them the shortest one in km . 105 * The performance metric used is the amount of extra traffic carried if the lightpath is established, divided by the lightpath cost, 106 * summing the transponder cost, and the cost of the signal regenerators if any.</p> 107 * <p>The details of the algorithm will be provided in a publication currently under elaboration.</p> 108 * 109 * @net2plan.keywords WDM 110 * @net2plan.inputParameters 111 * @author Pablo Pavon-Marino 112 */ 113@SuppressWarnings("unchecked") 114public class Offline_ipOverWdm_routingSpectrumAndModulationAssignmentHeuristicNotGrooming implements IAlgorithm 115{ 116 private InputParameter k = new InputParameter ("k", (int) 5 , "Maximum number of admissible paths per input-output node pair" , 1 , Integer.MAX_VALUE); 117 private InputParameter numFrequencySlotsPerFiber = new InputParameter ("numFrequencySlotsPerFiber", (int) 40 , "Number of wavelengths per link" , 1, Integer.MAX_VALUE); 118 private InputParameter transponderTypesInfo = new InputParameter ("transponderTypesInfo", "10 1 1 9600 1" , "Transpoder types separated by \";\" . Each type is characterized by the space-separated values: (i) Line rate in Gbps, (ii) cost of the transponder, (iii) number of slots occupied in each traversed fiber, (iv) optical reach in km (a non-positive number means no reach limit), (v) cost of the optical signal regenerator (regenerators do NOT make wavelength conversion ; if negative, regeneration is not possible)."); 119 private InputParameter ipLayerIndex = new InputParameter ("ipLayerIndex", (int) 1 , "Index of the IP layer (-1 means default layer)"); 120 private InputParameter wdmLayerIndex = new InputParameter ("wdmLayerIndex", (int) 0 , "Index of the WDM layer (-1 means default layer)"); 121 private InputParameter networkRecoveryType = new InputParameter ("networkRecoveryType", "#select# not-fault-tolerant single-srg-tolerant-static-lp 1+1-srg-disjoint-lps" , "Establish if the design should be tolerant or not to single SRG failures (SRGs are as defined in the input NetPlan). First option is that the design should not be fault tolerant, the second means that failed lightpaths are not recovered, but an overprovisioned should be made so enough lightpaths survive to carry all the traffic in every failure. The third means that each lightpath is 1+1 protceted by a SRG-disjoint one, that uses the same transponder"); 122 private InputParameter maxPropagationDelayMs = new InputParameter ("maxPropagationDelayMs", (double) -1 , "Maximum allowed propagation time of a lighptath in miliseconds. If non-positive, no limit is assumed"); 123 124 private NetPlan netPlan; 125 private SortedMap<Pair<Node,Node>,List<List<Link>>> cpl; 126 private SortedMap<Pair<Node,Node>,List<Pair<List<Link>,List<Link>>>> cpl11; 127 private NetworkLayer wdmLayer, ipLayer; 128 private WDMUtils.TransponderTypesInfo tpInfo; 129 private int N, Ewdm, Dip, S, T; 130 private boolean singleSRGToleranceNot11Type; 131 private DoubleMatrix2D frequencySlot2FiberOccupancy_se; 132 private Demand.IntendedRecoveryType recoveryTypeNewLps; 133 134 @Override 135 public String executeAlgorithm(NetPlan netPlan, Map<String, String> algorithmParameters, Map<String, String> net2planParameters) 136 { 137 /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */ 138 InputParameter.initializeAllInputParameterFieldsOfObject(this, algorithmParameters); 139 140 this.netPlan = netPlan; 141 142 /* Create a two-layer IP over WDM design if the input is single layer */ 143 if (netPlan.getNumberOfLayers() == 1) 144 { 145 this.wdmLayer = netPlan.getNetworkLayerDefault(); 146 this.netPlan.setDemandTrafficUnitsName("Gbps"); 147 this.netPlan.setLinkCapacityUnitsName("Frequency slots"); 148 this.ipLayer = netPlan.addLayer("IP" , "IP layer" , "Gbps" , "Gbps" , null , null); 149 for (Demand wdmDemand : netPlan.getDemands(wdmLayer)) 150 netPlan.addDemand(wdmDemand.getIngressNode(), wdmDemand.getEgressNode() , wdmDemand.getOfferedTraffic() , RoutingType.HOP_BY_HOP_ROUTING , wdmDemand.getAttributes() , ipLayer); 151 } 152 else 153 { 154 this.wdmLayer = wdmLayerIndex.getInt () == -1? netPlan.getNetworkLayerDefault() : netPlan.getNetworkLayer(wdmLayerIndex.getInt ()); 155 this.ipLayer = ipLayerIndex.getInt () == -1? netPlan.getNetworkLayerDefault() : netPlan.getNetworkLayer(ipLayerIndex.getInt ()); 156 } 157 158 /* Basic checks */ 159 this.N = netPlan.getNumberOfNodes(); 160 this.Ewdm = netPlan.getNumberOfLinks(wdmLayer); 161 this.Dip = netPlan.getNumberOfDemands(ipLayer); 162 this.S = numFrequencySlotsPerFiber.getInt(); 163 if (N == 0 || Ewdm == 0 || Dip == 0) throw new Net2PlanException("This algorithm requires a topology with links and a demand set"); 164 this.singleSRGToleranceNot11Type = networkRecoveryType.getString().equals("single-srg-tolerant-static-lp"); 165 166 if (singleSRGToleranceNot11Type && (netPlan.getNumberOfSRGs() == 0)) throw new Net2PlanException ("No SRGs are defined, so there is no reason to use the single-SRG failure-tolerant design option"); 167 168 if (networkRecoveryType.getString().equals("not-fault-tolerant") || networkRecoveryType.getString().equals("single-srg-tolerant-static-lp")) 169 recoveryTypeNewLps = Demand.IntendedRecoveryType.NONE; 170 else if (networkRecoveryType.getString().equals("1+1-srg-disjoint-lps")) 171 recoveryTypeNewLps = Demand.IntendedRecoveryType.PROTECTION_REVERT; 172 else throw new Net2PlanException ("Wrong input parameters"); 173 174 /* Store transpoder info */ 175 WDMUtils.setFibersNumFrequencySlots(netPlan, S, wdmLayer); 176 this.tpInfo = new WDMUtils.TransponderTypesInfo(transponderTypesInfo.getString()); 177 this.T = tpInfo.getNumTypes(); 178 179 /* Remove all routes in current netPlan object. Initialize link capacities and attributes, and demand offered traffic */ 180 /* WDM and IP layer are in source routing type */ 181 netPlan.removeAllLinks (ipLayer); 182 netPlan.removeAllDemands (wdmLayer); 183 netPlan.removeAllMulticastDemands(wdmLayer); 184 185 /* Initialize the slot occupancy */ 186 this.frequencySlot2FiberOccupancy_se = DoubleFactory2D.dense.make(S , Ewdm); 187 188 /* Compute the candidate path list of possible paths */ 189 this.cpl = netPlan.computeUnicastCandidatePathList(netPlan.getVectorLinkLengthInKm(wdmLayer) , k.getInt(), tpInfo.getMaxOpticalReachKm() , -1, maxPropagationDelayMs.getDouble(), -1, -1, -1 , null , wdmLayer); 190 this.cpl11 = networkRecoveryType.getString().equals("1+1-srg-disjoint-lps")? NetPlan.computeUnicastCandidate11PathList(cpl,0) : null; 191 192 /* Compute the CPL, adding the routes */ 193 /* 1+1 case: as many routes as 1+1 valid pairs (then, the same sequence of links can be in more than one Route). */ 194 /* rest of the cases: each sequence of links appears at most once */ 195 Map<Link,Double> linkLengthMap = new HashMap<Link,Double> (); for (Link e : netPlan.getLinks(wdmLayer)) linkLengthMap.put(e , e.getLengthInKm()); 196 final int maximumNumberOfPaths = T*k.getInt()*Dip; 197 List<Integer> transponderType_p = new ArrayList<Integer> (maximumNumberOfPaths); 198 List<Double> cost_p = new ArrayList<Double> (maximumNumberOfPaths); 199 List<Double> lineRate_p = new ArrayList<Double> (maximumNumberOfPaths); 200 List<Integer> numSlots_p = new ArrayList<Integer> (maximumNumberOfPaths); 201 List<List<Link>> seqLinks_p = new ArrayList<List<Link>> (maximumNumberOfPaths); 202 List<List<Link>> seqLinks2_p = cpl11 == null? null : new ArrayList<List<Link>> (maximumNumberOfPaths); 203 List<int []> regPositions_p = new ArrayList<int []> (maximumNumberOfPaths); 204 List<int []> regPositions2_p = new ArrayList<int []> (maximumNumberOfPaths); 205 List<Demand> ipDemand_p = new ArrayList<Demand> (maximumNumberOfPaths); 206 Map<Demand,List<Integer>> ipDemand2WDMPathListMap = new HashMap<Demand,List<Integer>> (); 207 for (Demand ipDemand : netPlan.getDemands(ipLayer)) 208 { 209 final Pair<Node,Node> nodePair = Pair.of(ipDemand.getIngressNode() , ipDemand.getEgressNode()); 210 boolean atLeastOnePathOrPathPair = false; 211 List<Integer> pathListThisDemand = new LinkedList<Integer> (); 212 ipDemand2WDMPathListMap.put(ipDemand , pathListThisDemand); 213 for (int t = 0 ; t < T ; t ++) 214 { 215 final boolean isRegenerable = tpInfo.isOpticalRegenerationPossible(t); 216 for (Object sp : cpl11 != null? cpl11.get(nodePair) : cpl.get(nodePair)) 217 { 218 List<Link> firstPath = (cpl11 == null)? ((List<Link>) sp) : ((Pair<List<Link>,List<Link>>) sp).getFirst(); 219 List<Link> secondPath = (cpl11 == null)? null : ((Pair<List<Link>,List<Link>>) sp).getSecond (); 220 if (!isRegenerable && (getLengthInKm(firstPath) > tpInfo.getOpticalReachKm(t))) break; 221 if (secondPath != null) if (!isRegenerable && (getLengthInKm(secondPath) > tpInfo.getOpticalReachKm(t))) break; 222 223 final int [] regPositions1 = isRegenerable? WDMUtils.computeRegeneratorPositions(firstPath , tpInfo.getOpticalReachKm(t)) : new int [firstPath.size()]; 224 final int [] regPositions2 = cpl11 == null? null : isRegenerable? WDMUtils.computeRegeneratorPositions(secondPath , tpInfo.getOpticalReachKm(t)) : new int [secondPath.size()]; 225 final int numRegeneratorsNeeded = !isRegenerable? 0 : (int) IntUtils.sum(regPositions1) + (secondPath == null? 0 : (int) IntUtils.sum(regPositions2)) ; 226 final double costOfLightpathOr11Pair = tpInfo.getCost(t) * (cpl11 != null? 2 : 1) + (tpInfo.getRegeneratorCost(t) * numRegeneratorsNeeded); 227 228 final int pathIndex = cost_p.size(); 229 cost_p.add (costOfLightpathOr11Pair); 230 transponderType_p.add (t); 231 lineRate_p.add(tpInfo.getLineRateGbps(t)); 232 numSlots_p.add(tpInfo.getNumSlots(t)); 233 ipDemand_p.add(ipDemand); 234 seqLinks_p.add(firstPath); 235 regPositions_p.add(regPositions1); 236 pathListThisDemand.add(pathIndex); 237 if (cpl11 != null) { seqLinks2_p.add(secondPath); regPositions2_p.add(regPositions2); } 238 atLeastOnePathOrPathPair = true; 239 } 240 } 241 if (!atLeastOnePathOrPathPair) throw new Net2PlanException ("There are no possible routes (or 1+1 pairs) for a demand (" + ipDemand + "). The topology may be not connected enough, or the optical reach may be too small"); 242 } 243 final int P = transponderType_p.size(); // one per potential sequence of links (or 1+1 pairs of sequences) and transponder 244 245 /* Main algorithm loop. Take one demand at a time, in a HLDA loop (ordered by average blocked traffic). 246 * In each demand, try all possible path-transponder pairs, and take the best according to the performance metric: 247 * avExtraTrafficCarried/transponderCost */ 248 boolean atLeastOneLpAdded = false; 249 Set<Integer> ipDemandIndexesNotToTry = new HashSet<Integer> (); 250 double totalCost = 0; 251 do 252 { 253 double [] b_d = getVectorIPDemandAverageAllStatesBlockedTraffic (); 254 int [] ipDemandIndexes = DoubleUtils.sortIndexes(b_d , OrderingType.DESCENDING); 255 atLeastOneLpAdded = false; 256 for (int ipDemandIndex : ipDemandIndexes) 257 { 258 /* Not to try a demand if already fully satisfied or we tried and could not add a lp to it */ 259 if (ipDemandIndexesNotToTry.contains(ipDemandIndex)) continue; 260 261 final Demand ipDemand = netPlan.getDemand(ipDemandIndex , ipLayer); 262 ipDemand.setRoutingType(RoutingType.SOURCE_ROUTING); 263 264 /* If the demand is already fully satisfied, skip it */ 265 if (isIpDemandFullySatisfied(ipDemand)) { ipDemandIndexesNotToTry.add(ipDemandIndex); continue; } 266 267 /* Try all the possible routes and all the possible transpoder types. Take the solution with the best 268 * performance metric (average extra carried traffic / transponder cost) */ 269 WDMUtils.RSA best_rsa = null; 270 WDMUtils.RSA best_rsa2 = null; 271 double best_performanceMetric = 0; 272 int best_pathIndex = -1; 273 for (int pathIndex : ipDemand2WDMPathListMap.get (ipDemand)) 274 { 275 List<Link> firstPath = seqLinks_p.get(pathIndex); 276 List<Link> secondPath = cpl11 == null? null : seqLinks2_p.get(pathIndex); 277 Pair<Integer,Integer> slotIds = null; 278 int slotId = -1; 279 if (cpl11 == null) 280 slotId = WDMUtils.spectrumAssignment_firstFit(firstPath , frequencySlot2FiberOccupancy_se , numSlots_p.get(pathIndex)); 281 else 282 slotIds = WDMUtils.spectrumAssignment_firstFitTwoRoutes(firstPath, secondPath, frequencySlot2FiberOccupancy_se , numSlots_p.get(pathIndex)); 283 284 /* Check if the path (or 1+1 path pair) is not feasible */ 285 if (cpl11 == null) if (slotId == -1) continue; 286 if (cpl11 != null) if (slotIds == null) continue; 287 288 /* If the performance metric is better than existing, this is the best choice */ 289 final double extraCarriedTraffic = getAverageAllStatesExtraCarriedTrafficAfterPotentialAllocation (ipDemand , lineRate_p.get(pathIndex) , seqLinks_p.get(pathIndex)); 290 final double performanceIndicator = extraCarriedTraffic / cost_p.get(pathIndex); 291 if (performanceIndicator > best_performanceMetric) 292 { 293 best_performanceMetric = performanceIndicator; 294 best_rsa = new WDMUtils.RSA(firstPath , cpl11 != null? slotIds.getFirst() : slotId , numSlots_p.get(pathIndex) , regPositions_p.get(pathIndex)); 295 best_rsa2 = cpl11 == null? null : new WDMUtils.RSA(secondPath , slotIds.getSecond() , numSlots_p.get(pathIndex) , regPositions2_p.get(pathIndex)); 296 best_pathIndex = pathIndex; 297 } 298 } 299 300 301 /* No lp could be added to this demand, try with the next */ 302 if (best_pathIndex == -1) { ipDemandIndexesNotToTry.add(ipDemand.getIndex()); continue; } 303 304 /* Add the lightpath to the design */ 305 atLeastOneLpAdded = true; 306 totalCost += cost_p.get(best_pathIndex); 307 final Demand newWDMDemand = netPlan.addDemand(best_rsa.ingressNode , best_rsa.egressNode , lineRate_p.get(best_pathIndex) , RoutingType.SOURCE_ROUTING , null , wdmLayer); 308 newWDMDemand.setIntendedRecoveryType(recoveryTypeNewLps); 309 final Route lp = WDMUtils.addLightpath(newWDMDemand , best_rsa , lineRate_p.get(best_pathIndex)); 310 final Link ipLink = newWDMDemand.coupleToNewLinkCreated(ipLayer); 311 final double ipTrafficToCarry = Math.min(lineRate_p.get(best_pathIndex) , ipDemand.getBlockedTraffic()); 312 netPlan.addRoute(ipDemand , ipTrafficToCarry , ipTrafficToCarry , Arrays.asList(ipLink), null); 313 WDMUtils.allocateResources(best_rsa , frequencySlot2FiberOccupancy_se , null); 314 if (cpl11 != null) 315 { 316 final Route lpBackup = WDMUtils.addLightpath(newWDMDemand , best_rsa2 , 0); 317 WDMUtils.allocateResources(best_rsa2 , frequencySlot2FiberOccupancy_se , null); 318 lp.addBackupRoute(lpBackup); 319 } 320 break; 321 } 322 323 } while (atLeastOneLpAdded); 324 325 WDMUtils.checkResourceAllocationClashing(netPlan,true,true,wdmLayer); 326 327 String outMessage = "Total cost: " + totalCost + ". Num lps (not including 1+1 backup if any) " + netPlan.getNumberOfRoutes(wdmLayer); 328 //System.out.println (outMessage); 329 return "Ok! " + outMessage; 330 } 331 332 private static double getLengthInKm (Collection<Link> r) { double res = 0; for (Link e : r) res += e.getLengthInKm(); return res; } 333 334 @Override 335 public String getDescription() 336 { 337 return "Algorithm based on an ILP solving the Routing, Spectrum, Modulation Assignment (RSMA) problem with regenerator placement, in flexi (elastic) or fixed grid optical WDM networks, with or without fault tolerance, latency and/or lightpath bidirectionality requisites (see the Javadoc for details)."; 338 } 339 340 @Override 341 public List<Triple<String, String, String>> getParameters() 342 { 343 /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */ 344 return InputParameter.getInformationAllInputParameterFieldsOfObject(this); 345 } 346 347 /* A vector with the blocked traffic for each demand (in the single-SRG failure tolerance, is averaged for each state) */ 348 private double [] getVectorIPDemandAverageAllStatesBlockedTraffic () 349 { 350 double [] res = new double [Dip]; 351 for (Demand ipDemand : netPlan.getDemands(ipLayer)) 352 { 353 res [ipDemand.getIndex()] = ipDemand.getBlockedTraffic(); 354 if (singleSRGToleranceNot11Type) 355 { 356 for (SharedRiskGroup srg : netPlan.getSRGs()) 357 { 358 Set<Route> affectedRoutes = srg.getAffectedRoutes(wdmLayer); 359 double carriedTrafficThisFailure = 0; 360 for (Route ipRoute : ipDemand.getRoutes()) 361 { 362 final Set<Route> wdmRoutes = ipRoute.getSeqLinks().get(0).getCoupledDemand().getRoutes(); 363 for (Route r : wdmRoutes) 364 if (!affectedRoutes.contains(r)) carriedTrafficThisFailure += r.getCarriedTraffic(); 365 } 366 res [ipDemand.getIndex()] += Math.max(0 , ipDemand.getOfferedTraffic() - carriedTrafficThisFailure); 367 } 368 } 369 res [ipDemand.getIndex()] /= (singleSRGToleranceNot11Type? (netPlan.getNumberOfSRGs() + 1) : 1); 370 } 371 return res; 372 } 373 374 /* The average for all the states (no failure, and potentially one per SRG if single-SRG failure tolerance option is chosen), 375 * of all the blocked traffic */ 376 private double getAverageAllStatesExtraCarriedTrafficAfterPotentialAllocation (Demand ipDemand , double lineRateGbps , List<Link> seqLinksIfSingleSRGToleranceIsNeeded) 377 { 378 double extraCarriedTraffic = Math.min(ipDemand.getBlockedTraffic() , lineRateGbps); 379 if (singleSRGToleranceNot11Type) 380 { 381 for (SharedRiskGroup srg : netPlan.getSRGs()) 382 { 383 if (srg.affectsAnyOf(seqLinksIfSingleSRGToleranceIsNeeded)) continue; // no extra carried traffic 384 Set<Route> affectedRoutes = srg.getAffectedRoutes(wdmLayer); 385 double carriedTrafficThisFailure = 0; 386 for (Route ipRoute : ipDemand.getRoutes()) 387 { 388 Set<Route> wdmRoutes = ipRoute.getSeqLinks().get(0).getCoupledDemand().getRoutes(); 389 for (Route r : wdmRoutes) 390 if (!affectedRoutes.contains(r)) carriedTrafficThisFailure += r.getCarriedTraffic(); 391 } 392 extraCarriedTraffic += Math.min(lineRateGbps , Math.max(0 , ipDemand.getOfferedTraffic() - carriedTrafficThisFailure)); 393 } 394 } 395 396 return extraCarriedTraffic / (singleSRGToleranceNot11Type? (netPlan.getNumberOfSRGs() + 1) : 1); 397 } 398 399 /* True if the demand is fully satisfied (in the single-SRG failure case, also in each SRG) */ 400 private boolean isIpDemandFullySatisfied (Demand d) 401 { 402 if (d.getBlockedTraffic() > 1e-3) return false; 403 if (singleSRGToleranceNot11Type) 404 { 405 for (SharedRiskGroup srg : netPlan.getSRGs()) 406 { 407 Set<Route> affectedRoutes = srg.getAffectedRoutes(wdmLayer); 408 double carriedTrafficThisFailure = 0; 409 for (Route ipRoute : d.getRoutes()) 410 { 411 final Set<Route> lps = ipRoute.getSeqLinks().get(0).getCoupledDemand().getRoutes(); 412 for (Route wdmRoute : lps) if (!affectedRoutes.contains(wdmRoute)) carriedTrafficThisFailure += wdmRoute.getCarriedTraffic(); 413 } 414 if (carriedTrafficThisFailure + 1e-3 < d.getOfferedTraffic()) return false; 415 } 416 } 417 return true; 418 } 419 420}