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