001/******************************************************************************* 002 * Copyright (c) 2016 Pablo Pavon Mariño. 003 * All rights reserved. This program and the accompanying materials 004 * are made available under the terms of the GNU Lesser Public License v2.1 005 * which accompanies this distribution, and is available at 006 * http://www.gnu.org/licenses/lgpl.html 007 ******************************************************************************/ 008 009 010 011 012package com.net2plan.examples.ocnbook.reports; 013 014import java.io.Closeable; 015import java.io.File; 016import java.text.DecimalFormat; 017import java.util.ArrayList; 018import java.util.HashSet; 019import java.util.List; 020import java.util.Map; 021import java.util.Set; 022 023import cern.colt.function.tdouble.DoubleDoubleFunction; 024import cern.colt.function.tdouble.DoubleFunction; 025import cern.colt.list.tdouble.DoubleArrayList; 026import cern.colt.list.tint.IntArrayList; 027import cern.colt.matrix.tdouble.DoubleFactory1D; 028import cern.colt.matrix.tdouble.DoubleMatrix1D; 029import cern.colt.matrix.tdouble.DoubleMatrix2D; 030 031import com.net2plan.interfaces.networkDesign.Demand; 032import com.net2plan.interfaces.networkDesign.IReport; 033import com.net2plan.interfaces.networkDesign.Link; 034import com.net2plan.interfaces.networkDesign.MulticastDemand; 035import com.net2plan.interfaces.networkDesign.Net2PlanException; 036import com.net2plan.interfaces.networkDesign.NetPlan; 037import com.net2plan.interfaces.networkDesign.NetworkLayer; 038import com.net2plan.interfaces.networkDesign.Node; 039import com.net2plan.interfaces.networkDesign.SharedRiskGroup; 040import com.net2plan.interfaces.simulation.IEventProcessor; 041import com.net2plan.interfaces.simulation.SimEvent; 042import com.net2plan.libraries.SRGUtils; 043import com.net2plan.utils.ClassLoaderUtils; 044import com.net2plan.utils.InputParameter; 045import com.net2plan.utils.StringUtils; 046import com.net2plan.utils.Triple; 047 048/** 049 * This report receives as an input a network design, the network recovery scheme algorithm, and the network risks (SRGs), and estimates the availability of the 050 * network (including individual availabilities for each demand), using an enumerative process that also provides an estimation of the estimation error. 051 * 052 * @net2plan.keywords Network recovery: protection , Network recovery: restoration 053 * @net2plan.ocnbooksections Section 3.7.3 054 * @net2plan.inputParameters 055 * @author Pablo Pavon-Marino 056 */ 057public class Report_availability implements IReport 058{ 059 private InputParameter provisioningAlgorithm = new InputParameter ("provisioningAlgorithm" , "#eventProcessor#" , "Algorithm to process failure events"); 060 private InputParameter analyzeDoubleFailures = new InputParameter ("analyzeDoubleFailures" , true , "Indicates whether double failures are studied"); 061 private InputParameter defaultMTTFInHours = new InputParameter ("defaultMTTFInHours" , (double) 8748 , "Default value for Mean Time To Fail (hours)" , 0 , false , Double.MAX_VALUE , true); 062 private InputParameter defaultMTTRInHours = new InputParameter ("defaultMTTRInHours" , (double) 12 , "Default value for Mean Time To Repair (hours)" , 0 , false , Double.MAX_VALUE , true); 063 private InputParameter failureModel = new InputParameter ("failureModel" , "#select# perBidirectionalLinkBundle SRGfromNetPlan perNode perLink perDirectionalLinkBundle" , "Failure model selection: SRGfromNetPlan, perNode, perLink, perDirectionalLinkBundle, perBidirectionalLinkBundle"); 064 private InputParameter considerTrafficInOversubscribedLinksAsLost = new InputParameter ("considerTrafficInOversubscribedLinksAsLost" , true , "If true, all the demands whose traffic (even only a fraction of it) traverses an oversubscribed link, are considered that all its treaffic is blocked, as they are supposed to fail to satisfy QoS agreements"); 065 private InputParameter maximumE2ELatencyMs = new InputParameter ("maximumE2ELatencyMs", (double) -1 , "Maximum end-to-end latency of the traffic of any demand (a non-positive value means no limit). All the traffic of demands where a fraction of its traffic can exceed this value, are considered as lost, as they are supposed to fail to satisfy QoS agreements"); 066 067 private ArrayList<DoubleMatrix1D> availabilityClassicNoFailure_ld, availabilityWeightedNoFailure_ld, availabilityClassicNoFailure_lmd, availabilityWeightedNoFailure_lmd; 068 private ArrayList<DoubleMatrix1D> availabilityClassicTotal_ld, availabilityWeightedTotal_ld, availabilityClassicTotal_lmd, availabilityWeightedTotal_lmd; 069 private double pi_excess; 070 071 private IEventProcessor algorithm; 072 073 @Override 074 public String executeReport(NetPlan netPlan, Map<String, String> reportParameters, Map<String, String> net2planParameters) 075 { 076 /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */ 077 InputParameter.initializeAllInputParameterFieldsOfObject(this, reportParameters); 078 079 String algorithmFile = reportParameters.get("provisioningAlgorithm_file"); 080 String algorithmName = reportParameters.get("provisioningAlgorithm_classname"); 081 String algorithmParam = reportParameters.get("provisioningAlgorithm_parameters"); 082 if (algorithmFile.isEmpty() || algorithmName.isEmpty()) throw new Net2PlanException("A provisioning algorithm must be defined"); 083 final double PRECISION_FACTOR_hd = Double.parseDouble(net2planParameters.get("precisionFactor")); 084 final double PRECISION_FACTOR_blocking = PRECISION_FACTOR_hd * PRECISION_FACTOR_hd; 085 086 087 Map<String, String> algorithmParameters = StringUtils.stringToMap(algorithmParam); 088 switch (failureModel.getString ()) 089 { 090 case "SRGfromNetPlan": 091 break; 092 093 case "perNode": 094 SRGUtils.configureSRGs(netPlan, defaultMTTFInHours.getDouble(), defaultMTTRInHours.getDouble(), SRGUtils.SharedRiskModel.PER_NODE, true); 095 break; 096 097 case "perLink": 098 SRGUtils.configureSRGs(netPlan, defaultMTTFInHours.getDouble(), defaultMTTRInHours.getDouble(), SRGUtils.SharedRiskModel.PER_LINK, true); 099 break; 100 101 case "perDirectionalLinkBundle": 102 SRGUtils.configureSRGs(netPlan, defaultMTTFInHours.getDouble(), defaultMTTRInHours.getDouble(), SRGUtils.SharedRiskModel.PER_DIRECTIONAL_LINK_BUNDLE, true); 103 break; 104 105 case "perBidirectionalLinkBundle": 106 SRGUtils.configureSRGs(netPlan, defaultMTTFInHours.getDouble(), defaultMTTRInHours.getDouble(), SRGUtils.SharedRiskModel.PER_BIDIRECTIONAL_LINK_BUNDLE, true); 107 break; 108 109 default: 110 throw new Net2PlanException("Failure model not valid. Please, check algorithm parameters description"); 111 } 112 113 netPlan.setAllNodesFailureState(true); 114 for (NetworkLayer layer : netPlan.getNetworkLayers ()) 115 netPlan.setAllLinksFailureState(true , layer); 116 DoubleMatrix1D A_f = netPlan.getVectorSRGAvailability(); 117 List<SharedRiskGroup> srgs = netPlan.getSRGs(); 118 DoubleMatrix2D F_s = SRGUtils.getMatrixFailureState2SRG(srgs, true, analyzeDoubleFailures.getBoolean()); 119 120 /* Compute state probabilities (pi_s) */ 121 DoubleMatrix1D pi_s = SRGUtils.computeStateProbabilities(F_s , A_f); 122 final double sum_pi_s = pi_s.zSum(); 123 124 final double pi_s0 = pi_s.get(0); System.out.println ("Probability no failure state: " + pi_s0); 125 126 pi_excess = 1 - sum_pi_s; 127 128 /* Initialize statistics variables */ 129 availabilityClassicNoFailure_ld = new ArrayList<DoubleMatrix1D> (); 130 availabilityWeightedNoFailure_ld = new ArrayList<DoubleMatrix1D> (); 131 availabilityClassicNoFailure_lmd = new ArrayList<DoubleMatrix1D> (); 132 availabilityWeightedNoFailure_lmd = new ArrayList<DoubleMatrix1D> (); 133 availabilityClassicTotal_ld = new ArrayList<DoubleMatrix1D> (); 134 availabilityWeightedTotal_ld = new ArrayList<DoubleMatrix1D> (); 135 availabilityClassicTotal_lmd = new ArrayList<DoubleMatrix1D> (); 136 availabilityWeightedTotal_lmd = new ArrayList<DoubleMatrix1D> (); 137 for(int indexLayer = 0 ; indexLayer < netPlan.getNumberOfLayers() ; indexLayer ++) 138 { 139 final NetworkLayer layer = netPlan.getNetworkLayer (indexLayer); 140 final int D = netPlan.getNumberOfDemands(layer); 141 final int MD = netPlan.getNumberOfMulticastDemands(layer); 142 availabilityClassicTotal_ld.add (DoubleFactory1D.dense.make (D,0.0)); 143 availabilityWeightedTotal_ld.add (DoubleFactory1D.dense.make (D,0.0)); 144 availabilityClassicTotal_lmd.add (DoubleFactory1D.dense.make (MD,0.0)); 145 availabilityWeightedTotal_lmd.add (DoubleFactory1D.dense.make (MD,0.0)); 146 } 147 148// List<Link> upAndOversubscribedLinksSetToDown = new LinkedList<Link> (); 149// if (considerTrafficInOversubscribedLinksAsLost.getBoolean()) 150// { 151// for (NetworkLayer layer : netPlan.getNetworkLayers ()) 152// { 153//// System.out.println ("Layer " + layer + ", initial link capacity traffic: " + netPlan.getVectorLinkCapacity(layer)); 154//// System.out.println ("Layer " + layer + ", initial demand carried traffic: " + netPlan.getVectorDemandCarriedTraffic(layer)); 155// for (Link e : netPlan.getLinks (layer)) if (e.isUp() && e.isOversubscribed()) { upAndOversubscribedLinksSetToDown.add (e); } 156//// System.out.println ("Layer: " + layer + ", upAndOversubscribedLinksSetToDown: " + upAndOversubscribedLinksSetToDown); 157// } 158// netPlan.setLinksAndNodesFailureState(null , upAndOversubscribedLinksSetToDown , null , null); 159// } 160// 161// System.out.println ("Links set to down all layers: " + netPlan.getLinksDownAllLayers()); 162 163 /* Statistics for the no-failure state */ 164 for(int indexLayer = 0 ; indexLayer < netPlan.getNumberOfLayers() ; indexLayer ++) 165 { 166 final NetworkLayer layer = netPlan.getNetworkLayer (indexLayer); 167 168 final DoubleMatrix1D h_d = netPlan.getVectorDemandOfferedTraffic(layer); 169 final DoubleMatrix1D blocked_d = netPlan.getVectorDemandBlockedTraffic(layer); 170 if (considerTrafficInOversubscribedLinksAsLost.getBoolean()) for (Demand d : netPlan.getDemands (layer)) if (d.isTraversingOversubscribedLinks()) blocked_d.set (d.getIndex () , d.getOfferedTraffic()); 171 if (maximumE2ELatencyMs.getDouble () > 0) for (Demand d : netPlan.getDemands (layer)) if (d.getWorseCasePropagationTimeInMs() > maximumE2ELatencyMs.getDouble ()) blocked_d.set (d.getIndex () , d.getOfferedTraffic()); 172 173 final DoubleMatrix1D h_md = netPlan.getVectorMulticastDemandOfferedTraffic(layer); 174 final DoubleMatrix1D blocked_md = netPlan.getVectorMulticastDemandBlockedTraffic(layer); 175 if (considerTrafficInOversubscribedLinksAsLost.getBoolean()) for (MulticastDemand d : netPlan.getMulticastDemands (layer)) if (d.isTraversingOversubscribedLinks()) blocked_md.set (d.getIndex () , d.getOfferedTraffic()); 176 if (maximumE2ELatencyMs.getDouble () > 0) for (MulticastDemand d : netPlan.getMulticastDemands(layer)) if (d.getWorseCasePropagationTimeInMs() > maximumE2ELatencyMs.getDouble ()) blocked_md.set (d.getIndex () , d.getOfferedTraffic()); 177 178 // System.out.println ("****** No failure Layer " + layer + ", blocked_d: " + blocked_d); 179 final DoubleMatrix1D availabilityClassic_d = blocked_d.copy ().assign (new DoubleFunction () { public double apply (double x) { return x > PRECISION_FACTOR_blocking? 0 : 1; } } ); 180 final DoubleMatrix1D availabilityWeighted_d = blocked_d.copy ().assign (h_d , new DoubleDoubleFunction () { public double apply (double x , double y) { return y < PRECISION_FACTOR_hd? 1 : 1 - x/y; } } ); 181 final DoubleMatrix1D availabilityClassic_md = blocked_md.copy ().assign (new DoubleFunction () { public double apply (double x) { return x > PRECISION_FACTOR_blocking ? 0 : 1; } } ); 182 final DoubleMatrix1D availabilityWeighted_md = blocked_md.copy ().assign (h_md , new DoubleDoubleFunction () { public double apply (double x , double y) { return y < PRECISION_FACTOR_hd ? 1 : 1 - x/y; } } ); 183 184 availabilityClassicTotal_ld.get(layer.getIndex ()).assign (availabilityClassic_d , new DoubleDoubleFunction () { public double apply (double x , double y) { return x + pi_s0 * y; } } ); 185 availabilityWeightedTotal_ld.get(layer.getIndex ()).assign (availabilityWeighted_d , new DoubleDoubleFunction () { public double apply (double x , double y) { return x + pi_s0 * y; } } ); 186 availabilityClassicTotal_lmd.get(layer.getIndex ()).assign (availabilityClassic_md , new DoubleDoubleFunction () { public double apply (double x , double y) { return x + pi_s0 * y; } } ); 187 availabilityWeightedTotal_lmd.get(layer.getIndex ()).assign (availabilityWeighted_md , new DoubleDoubleFunction () { public double apply (double x , double y) { return x + pi_s0 * y; } } ); 188 189 availabilityClassicNoFailure_ld.add(availabilityClassic_d); 190 availabilityWeightedNoFailure_ld.add(availabilityWeighted_d); 191 availabilityClassicNoFailure_lmd.add(availabilityClassic_md); 192 availabilityWeightedNoFailure_lmd.add(availabilityWeighted_md); 193 } 194// System.out.println ("Before any failure state: availabilityClassicTotal_ld: " + availabilityClassicTotal_ld); 195// System.out.println ("Before any failure state: availabilityClassicNoFailure_ld: " + availabilityClassicNoFailure_ld); 196 197 198 /* the up and oversubscribed links that were set as down, are set to up again */ 199// if (considerTrafficInOversubscribedLinksAsLost.getBoolean()) 200// netPlan.setLinksAndNodesFailureState(upAndOversubscribedLinksSetToDown , null , null , null); 201 202 if (!netPlan.getLinksDownAllLayers().isEmpty() || !netPlan.getNodesDown().isEmpty()) throw new RuntimeException ("Bad"); 203 204 NetPlan auxNetPlan = netPlan.copy (); 205 this.algorithm = ClassLoaderUtils.getInstance(new File(algorithmFile), algorithmName, IEventProcessor.class); 206 this.algorithm.initialize(auxNetPlan , algorithmParameters , reportParameters , net2planParameters); 207 Set<Link> initialLinksDownAllLayers = auxNetPlan.getLinksDownAllLayers(); 208 Set<Node> initialNodesDown = auxNetPlan.getNodesDown(); 209 Set<Link> linksAllLayers = new HashSet<Link> (); for (NetworkLayer layer : auxNetPlan.getNetworkLayers()) linksAllLayers.addAll (auxNetPlan.getLinks (layer)); 210 211 for (int failureState = 1 ; failureState < F_s.rows () ; failureState ++) // first failure state (no failure) was already considered 212 { 213 if (!auxNetPlan.getLinksDownAllLayers().equals (initialLinksDownAllLayers) || !auxNetPlan.getNodesDown().equals(initialNodesDown)) throw new RuntimeException ("Bad"); 214 215 IntArrayList srgs_thisState = new IntArrayList (); F_s.viewRow (failureState).getNonZeros (srgs_thisState , new DoubleArrayList ()); 216 final double pi_s_thisState = pi_s.get (failureState); 217 218 Set<Link> linksToSetAsDown = new HashSet<Link> (); 219 Set<Node> nodesToSetAsDown = new HashSet<Node> (); 220 for (SharedRiskGroup srg : auxNetPlan.getSRGs()) 221 { 222 if (F_s.get(failureState , srg.getIndex ()) != 1) continue; 223 nodesToSetAsDown.addAll (srg.getNodes ()); 224 linksToSetAsDown.addAll (srg.getLinks ()); 225 } 226 227 /* Make the algorithm process the event of nodes and links down */ 228 SimEvent.NodesAndLinksChangeFailureState failureInfo = new SimEvent.NodesAndLinksChangeFailureState(null , nodesToSetAsDown , null , linksToSetAsDown); 229 try 230 { 231 /* Apply the reaction algorithm */ 232 algorithm.processEvent(auxNetPlan, new SimEvent(0, SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , failureInfo)); 233 } 234 catch (Throwable e) 235 { 236 try { ((Closeable) algorithm.getClass().getClassLoader()).close(); } 237 catch (Throwable e1) { } 238 239 throw (e); 240 } 241 242 try { ((Closeable) algorithm.getClass().getClassLoader()).close(); } 243 catch (Throwable e1) { } 244 245 for(NetworkLayer layer : auxNetPlan.getNetworkLayers ()) 246 { 247 final DoubleMatrix1D h_d = auxNetPlan.getVectorDemandOfferedTraffic(layer); 248 final DoubleMatrix1D blocked_d = auxNetPlan.getVectorDemandBlockedTraffic(layer); 249 if (considerTrafficInOversubscribedLinksAsLost.getBoolean()) for (Demand d : auxNetPlan.getDemands (layer)) if (d.isTraversingOversubscribedLinks()) blocked_d.set (d.getIndex () , d.getOfferedTraffic()); 250 if (maximumE2ELatencyMs.getDouble () > 0) for (Demand d : auxNetPlan.getDemands (layer)) if (d.getWorseCasePropagationTimeInMs() > maximumE2ELatencyMs.getDouble ()) blocked_d.set (d.getIndex () , d.getOfferedTraffic()); 251 final DoubleMatrix1D h_md = auxNetPlan.getVectorMulticastDemandOfferedTraffic(layer); 252 final DoubleMatrix1D blocked_md = auxNetPlan.getVectorMulticastDemandBlockedTraffic(layer); 253 if (considerTrafficInOversubscribedLinksAsLost.getBoolean()) for (MulticastDemand d : auxNetPlan.getMulticastDemands (layer)) if (d.isTraversingOversubscribedLinks()) blocked_md.set (d.getIndex () , d.getOfferedTraffic()); 254 if (maximumE2ELatencyMs.getDouble () > 0) for (MulticastDemand d : auxNetPlan.getMulticastDemands(layer)) if (d.getWorseCasePropagationTimeInMs() > maximumE2ELatencyMs.getDouble ()) blocked_md.set (d.getIndex () , d.getOfferedTraffic()); 255 final DoubleMatrix1D availabilityClassic_d = blocked_d.copy ().assign (new DoubleFunction () { public double apply (double x) { return x > PRECISION_FACTOR_blocking? 0 : 1; } } ); 256 final DoubleMatrix1D availabilityWeighted_d = blocked_d.copy ().assign (h_d , new DoubleDoubleFunction () { public double apply (double x , double y) { return y < PRECISION_FACTOR_hd? 1 : 1 - x/y; } } ); 257 final DoubleMatrix1D availabilityClassic_md = blocked_md.copy ().assign (new DoubleFunction () { public double apply (double x) { return x > PRECISION_FACTOR_blocking? 0 : 1; } } ); 258 final DoubleMatrix1D availabilityWeighted_md = blocked_md.copy ().assign (h_md , new DoubleDoubleFunction () { public double apply (double x , double y) { return y < PRECISION_FACTOR_hd? 1 : 1 - x/y; } } ); 259 260// System.out.println ("****** Failure: " + failureState + ", Layer " + layer + ", blocked_d: " + blocked_d); 261 262 availabilityClassicTotal_ld.get(layer.getIndex ()).assign (availabilityClassic_d , new DoubleDoubleFunction () { public double apply (double x , double y) { return x + pi_s_thisState * y; } } ); 263 availabilityWeightedTotal_ld.get(layer.getIndex ()).assign (availabilityWeighted_d , new DoubleDoubleFunction () { public double apply (double x , double y) { return x + pi_s_thisState * y; } } ); 264 availabilityClassicTotal_lmd.get(layer.getIndex ()).assign (availabilityClassic_md , new DoubleDoubleFunction () { public double apply (double x , double y) { return x + pi_s_thisState * y; } } ); 265 availabilityWeightedTotal_lmd.get(layer.getIndex ()).assign (availabilityWeighted_md , new DoubleDoubleFunction () { public double apply (double x , double y) { return x + pi_s_thisState * y; } } ); 266 267// System.out.println ("Failure " + failureState + ", availabilityClassicTotal_ld: " + availabilityClassicTotal_ld); 268 } 269 270// System.out.println ("4. failure state: " + failureState + ", auxNetPlan.getLinksDownAllLayers(): " + auxNetPlan.getLinksDownAllLayers() + ", auxNetPlan.getNodesDown(): " + auxNetPlan.getNodesDown() + ", linksToSetDown: " + linksToSetAsDown); 271 272 failureInfo = new SimEvent.NodesAndLinksChangeFailureState(auxNetPlan.getNodes() , null , linksAllLayers , null); 273 algorithm.processEvent(auxNetPlan, new SimEvent(0, SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , failureInfo)); 274 275// System.out.println ("5. failure state: " + failureState + ", auxNetPlan.getLinksDownAllLayers(): " + auxNetPlan.getLinksDownAllLayers() + ", auxNetPlan.getNodesDown(): " + auxNetPlan.getNodesDown() + ", linksToSetDown: " + linksToSetAsDown); 276 } 277 278 return printReport(netPlan , reportParameters); 279 } 280 281 @Override 282 public String getDescription() 283 { 284 return "This report receives as an input a network design, the network recovery scheme algorithm, and the network risks (SRGs), and estimates the availability of the network (including individual availabilities for each demand), using an enumerative process that also provides an estimation of the estimation error. "; 285 } 286 287 @Override 288 public List<Triple<String, String, String>> getParameters() 289 { 290 /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */ 291 return InputParameter.getInformationAllInputParameterFieldsOfObject(this); 292 } 293 294 @Override 295 public String getTitle() 296 { 297 return "Availability report"; 298 } 299 300 301 private String printReport(NetPlan np , Map<String,String> reportParameters) 302 { 303 StringBuilder out = new StringBuilder(); 304 DecimalFormat df_6 = new DecimalFormat("#.######"); 305 out.append("<html><body>"); 306 out.append("<head><title>Availability report</title></head>"); 307 out.append("<h1>Introduction</h1>"); 308 out.append("<p>This report computes several availability measures for the different unicast and multicast demands in the different layers of the network." + 309 "The network is supposed to be subject to the failures defined by the SRGs, and the possible network states considered are: </p>"); 310 out.append ("<ul>"); 311 out.append ("<li>No failure occurs in the network</li>"); 312 out.append ("<li>Single SRG failure: A single SRG fails, while the rest of failures associated to the other SRGs do not occur</li>"); 313 out.append ("<li>Double SRG failure (optional): Two SRGs simultaneously fail, while the rest of failures associated to the other SRGs do not occur</li>"); 314 out.append ("</ul>"); 315 out.append("<p>A numerical method is used that (i) enumerates the possible failure states considered and the probability of occurrence, (ii) computes the network reaction" + 316 "to that failure state using a used-defined algorithm, (iii) builds up the availability results for each demand from that.</p>"); 317 out.append("<p>Then, the method is able to produce an estimation of the availability of each unicast and multicast demand (and from them network-wide availability measures) under the given failures, and" + 318 " assuming that the network reacts according to an arbitrary protection/restoration provided algorithm.</p>"); 319 out.append("<p>Two types of availability metrics are provided:</p>"); 320 out.append ("<ul>"); 321 out.append ("<li>Availability of a demand/network: Fraction of time in which the demand/network is carrying the 100% of the offered traffic</li>"); 322 out.append ("<li>Traffic survivability of a demand/network: Fraction of the offered traffic that the network carries</li>"); 323 out.append ("</ul>"); 324 out.append("<p>Traffic survivability is always equals or higher than analogous availability value. For instance, if during some failure states that mean a 1% of the time, a demad is " + 325 "carrying just a 50% of the traffic, the network availability is 99% (99% of the time everythign works perfectly well), but traffic survivability is " + 326 "0.99*1 + 0.01*0.5 = 99.5%</p>"); 327 out.append("<p>In each metric, we provide a pessimistic and optimistic estimation. The pessimistic estimation, considers that in the triple, quadruple etc. " + 328 "failure states, all the traffic is lost. In the optimistic case, we assume that in such cases, all the traffic is carried. </p>"); 329 330 out.append("<p>For more information of this method:</p>"); 331 out.append("<p>P. Pavón Mariño, \"Optimization of computer networks. Modeling and algorithms. A hands-on approach\", Wiley 2016</p>"); 332 out.append("<h1>Global information</h1>"); 333 out.append("<h2>Input Parameters</h2>"); 334 out.append("<table border='1'>"); 335 out.append("<tr><th><b>Name</b></th><th><b>Value</b></th><th><b>Description</b></th>"); 336 for (Triple<String, String, String> paramDef : getParameters()) 337 { 338 String name = paramDef.getFirst(); 339 String description = paramDef.getThird(); 340 String value = reportParameters.get(name); 341 out.append("<tr><td>").append(name).append("</td><td>").append(value).append("</td><td>").append(description).append("</td></tr>"); 342 } 343 out.append("<tr><td>--Estimated error in availability calculations: </td><td>" + pi_excess + "</td><td>Probabilities of triple failure, quadruple etc. of non enumerated network states</td></tr>"); 344 out.append("</table>"); 345 346 out.append("<h1>PER LAYER INFORMATION SUMMARY</h1>"); 347 for (NetworkLayer layer : np.getNetworkLayers ()) 348 { 349 double val; 350 351 out.append("<h2>Layer " + layer.getName () + ", index = " + layer.getIndex () + ", id = " + layer.getId () + "</h2>"); 352 final DoubleMatrix1D h_d = np.getVectorDemandOfferedTraffic(layer); 353 final DoubleMatrix1D h_md = np.getVectorMulticastDemandOfferedTraffic(layer); 354 final DoubleMatrix1D avNoFailure_d = this.availabilityClassicNoFailure_ld.get(layer.getIndex ()); 355 final DoubleMatrix1D survNoFailure_d = this.availabilityWeightedNoFailure_ld.get(layer.getIndex ()); 356 final DoubleMatrix1D avNoFailure_md = this.availabilityClassicNoFailure_lmd.get(layer.getIndex ()); 357 final DoubleMatrix1D survNoFailure_md = this.availabilityWeightedNoFailure_lmd.get(layer.getIndex ()); 358 final DoubleMatrix1D avTotal_d = this.availabilityClassicTotal_ld.get(layer.getIndex ()); 359 final DoubleMatrix1D survTotal_d = this.availabilityWeightedTotal_ld.get(layer.getIndex ()); 360 final DoubleMatrix1D avTotal_md = this.availabilityClassicTotal_lmd.get(layer.getIndex ()); 361 final DoubleMatrix1D survTotal_md = this.availabilityWeightedTotal_lmd.get(layer.getIndex ()); 362 363 out.append ("<ul>"); 364 final double H = h_d.zSum(); 365 val = h_d.size () == 0? 0 : H; out.append ("<li>UNICAST TRAFFIC: (Deterministic) Total offered traffic: " + df_6.format (val) + "</li>"); 366 if (np.getNumberOfDemands (layer) != 0) 367 { 368 val = survNoFailure_d.size () == 0? 0 : 1 - (survNoFailure_d.zDotProduct(h_d) / H); out.append ("<li>UNICAST TRAFFIC: (Deterministic) Blocked traffic when no failure occurs: " + df_6.format (val) + "</li>"); 369 val = avTotal_d.size () == 0? 0 : avTotal_d.zDotProduct(h_d) / H; out.append ("<li>UNICAST TRAFFIC: (Estimated) Network availability: " + df_6.format(val) + " - " + df_6.format(val + pi_excess) + "</li>"); 370 val = survTotal_d.size () == 0? 0 : survTotal_d.zDotProduct(h_d) / H; out.append ("<li>UNICAST TRAFFIC: (Estimated) Network traffic survivability: " + df_6.format(val) + " - " + df_6.format(val + pi_excess) + "</li>"); 371 val = avTotal_d.size () == 0? 0 : avTotal_d.getMinLocation() [0]; out.append ("<li>UNICAST TRAFFIC: (Estimated) Worse availability among demands: " + df_6.format(val) + " - " + df_6.format(val + pi_excess) + "</li>"); 372 val = survTotal_d.size () == 0? 0 : survTotal_d.getMinLocation() [0]; out.append ("<li>UNICAST TRAFFIC: (Estimated) Worse traffic survivability among demands: " + df_6.format(val) + " - " + df_6.format(val + pi_excess) + "</li>"); 373 } 374 final double MH = h_md.zSum(); 375 val = h_md.size () == 0? 0 : MH; out.append ("<li>MULTICAST TRAFFIC: (Deterministic) Total offered traffic: " + df_6.format (val) + "</li>"); 376 if (np.getNumberOfMulticastDemands(layer) != 0) 377 { 378 val = survNoFailure_md.size () == 0? 0 : 1-(survNoFailure_md.zDotProduct(h_md) / MH); out.append ("<li>MULTICAST TRAFFIC: (Deterministic) Blocked traffic when no failure occurs: " + df_6.format (val) + "</li>"); 379 val = avTotal_md.size () == 0? 0 : avTotal_md.zDotProduct(h_md) / MH; out.append ("<li>MULTICAST TRAFFIC: (Estimated) Network availability: " + df_6.format(val) + " - " + df_6.format(val + pi_excess) + "</li>"); 380 val = survTotal_md.size () == 0? 0 : survTotal_md.zDotProduct(h_md) /MH; out.append ("<li>MULTICAST TRAFFIC: (Estimated) Network traffic survivability: " + df_6.format(val) + " - " + df_6.format(val + pi_excess) + "</li>"); 381 val = avTotal_md.size () == 0? 0 : avTotal_md.getMinLocation() [0]; out.append ("<li>MULTICAST TRAFFIC: (Estimated) Worse availability among demands: " + df_6.format(val) + " - " + df_6.format(val + pi_excess) + "</li>"); 382 val = survTotal_md.size () == 0? 0 : survTotal_md.getMinLocation() [0]; out.append ("<li>MULTICAST TRAFFIC: (Estimated) Worse traffic survivability among demands: " + df_6.format(val) + " - " + df_6.format(val + pi_excess) + "</li>"); 383 } 384 } 385 386 387 out.append("<h1>PER LAYER INFORMATION DETAILED INFORMATION</h1>"); 388 for (NetworkLayer layer : np.getNetworkLayers ()) 389 { 390 out.append("<h2>Layer " + layer.getName () + ", index = " + layer.getIndex () + ", id = " + layer.getId () + "</h2>"); 391 final DoubleMatrix1D avTotal_d = this.availabilityClassicTotal_ld.get(layer.getIndex ()); 392 final DoubleMatrix1D survTotal_d = this.availabilityWeightedTotal_ld.get(layer.getIndex ()); 393 final DoubleMatrix1D avTotal_md = this.availabilityClassicTotal_lmd.get(layer.getIndex ()); 394 final DoubleMatrix1D survTotal_md = this.availabilityWeightedTotal_lmd.get(layer.getIndex ()); 395 396 if (np.getNumberOfDemands(layer) != 0) 397 { 398 out.append("<table border='1'>"); 399 out.append("<tr><th><b>Demand</b></th><th><b>Origin node</b></th><th><b>Destination node</b></th><th><b>Availability</b></th><th><b>Traffic survivability</b></th></tr>"); 400 for (Demand d : np.getDemands (layer)) 401 out.append("<tr><td> " + d.getIndex () + " id (" + d.getId () + ")" + "</td><td>" + d.getIngressNode ().getIndex () + " (" + d.getIngressNode ().getName () + ") </td><td> " + d.getEgressNode().getIndex () + " (" + d.getEgressNode().getName () + ")</td><td>" + avTotal_d.get(d.getIndex()) +" ... " + (avTotal_d.get(d.getIndex()) + pi_excess) + "</td><td>" + survTotal_d.get(d.getIndex()) + " ... " + (survTotal_d.get(d.getIndex()) + pi_excess) + "</td></tr>"); 402 out.append("</table>"); 403 404 out.append("<p></p><p></p>"); 405 } 406 if (np.getNumberOfMulticastDemands(layer) != 0) 407 { 408 out.append("<table border='1'>"); 409 out.append("<tr><th><b>Multicast demand</b></th><th><b>Origin node</b></th><th><b>Destination nodes</b></th><th><b>Availability</b></th><th><b>Traffic survivability</b></th></tr>"); 410 for (MulticastDemand d : np.getMulticastDemands (layer)) 411 { 412 String egressNodesInfo = ""; for (Node n : d.getEgressNodes()) egressNodesInfo += n.getIndex () + "(" + n.getName () + ") "; 413 out.append("<tr><td> " + d.getIndex () + " id (" + d.getId () + ")" + "</td><td>" + d.getIngressNode ().getIndex () + " (" + d.getIngressNode ().getName () + ") </td><td> " + egressNodesInfo + "</td><td>" + avTotal_md.get(d.getIndex()) + " ... " + (avTotal_md.get(d.getIndex()) + pi_excess) + "</td><td>" + survTotal_md.get(d.getIndex()) + " ... " + (survTotal_md.get(d.getIndex()) + pi_excess) + "</td></tr>"); 414 } 415 out.append("</table>"); 416 } 417 } 418 419 return out.toString(); 420 } 421 422 423 424}