12 Commits

Author SHA1 Message Date
Giacomo Bertolazzi
158976bb71 Merge pull request #4 from Berack96/arguments
Arguments
2025-04-16 10:55:30 +02:00
f8f7f72eea Update README.md with additional simulation result images for better visualization and understanding 2025-04-16 10:47:09 +02:00
37e0b57c36 Enhance ConsoleTable initialization; allow custom max column length and adjust border calculation for better formatting in Result statistics 2025-04-16 10:46:40 +02:00
44cf714840 Update README.md to enhance clarity of simulation results; format output for better readability 2025-04-09 08:04:42 +02:00
719c6b353a Add argparse4j dependency; remove Parameters class and update simulation argument handling 2025-04-02 10:44:32 +02:00
4b9c40f894 Remove Rvgs.java class for random variate generation; obsolete code cleanup 2025-04-01 09:31:44 +02:00
78dcac0a56 Enhance simulation options in InteractiveConsole; add confidence index handling and new seed generation; update Plot behavior to dispose on close 2025-03-26 14:54:55 +01:00
57c9dd9733 Update README.md to include detailed analysis of service distribution changes and their impact on queue metrics 2025-03-23 16:20:58 +01:00
3844a46379 Add new images and update README with network modifications; improve ConsoleTable formatting 2025-03-22 09:39:23 +01:00
e48bddf94d Update README.md references; moved example*.jsimg in the correct folder 2025-03-16 20:13:21 +01:00
8f30f07c36 Update README.md formatting and examples; remove outdated image and add new example image 2025-03-16 19:56:36 +01:00
e4df5dab73 Add launch configuration for NetExamples; enhance NetExamples class with main method and improved network creation; refactor Result class for better stats handling 2025-03-16 19:42:33 +01:00
25 changed files with 1419 additions and 1631 deletions

11
.vscode/launch.json vendored
View File

@@ -4,6 +4,13 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "NetExamples",
"request": "launch",
"mainClass": "net.berack.upo.valpre.NetExamples",
"projectName": "valpre"
},
{
"type": "java",
"name": "Run1k Simple",
@@ -23,7 +30,7 @@
"name": "Run Incremental",
"request": "launch",
"mainClass": "net.berack.upo.valpre.Main",
"args": "simulation -net src/test/resources/example2.net -runs 1000 -i \"[Service1:throughput=0.98:0.01],[Service2:utilization=0.98:0.01],[Service2:unavailable=0.98:0.01]\""
"args": "simulation -net src/test/resources/example2.net -runs 1000 -indices \"[Service1:throughput=0.98:0.01],[Service2:utilization=0.98:0.01],[Service2:unavailable=0.98:0.01]\""
},
{
"type": "java",
@@ -52,6 +59,6 @@
"request": "launch",
"mainClass": "net.berack.upo.valpre.Main",
"args": "interactive"
},
}
]
}

View File

@@ -5,14 +5,11 @@ Il simulatore è iniziato con il lavoro trovato sul libro di testo [Discrete-Eve
Il risultato è la creazione in una libreria per la simulazione di eventi discreti nella quale si può scegliera la topologia e la quantità di nodi nella rete da simulare.
Questa libreria è stata confrontata con il tool [JMT](https://jmt.sourceforge.net/Download.html) e le reti usate per fare il confronto si possono trovare sotto [le risorse del main](https://github.com/Berack96/upo-valpre/tree/main/src/main/resources).
> [!IMPORTANT]
> Il JAR risultante che si trova nelle [Releases](https://github.com/Berack96/upo-valpre/releases).\
> La versione di Java usata è la 23 (precisamente la [23.0.1](https://www.oracle.com/java/technologies/javase/jdk23-archive-downloads.html)).
---
### Comandi Jar
## Comandi Jar
Il JAR viene invocato tramite il classico comando java: `java -jar upo-valpre.jar` al quale si aggiungono vari argomenti successivi in base a cosa si vuole fare:
@@ -34,8 +31,7 @@ Esistono vari tipi di argomenti per scegliere come fare la simulazione:
Mostra (con un ambiente grafico) una finestra nella quale si può scegliere quale nodo vedere e ogni statistica associata ad esso. Di seguito un'immagine di esempio:\
![1738603552417](image/README/1738603552417.png)
---
### Classi Interne
## Classi Interne
Esistono molteplici classi interne che vengono usate per supportare la simulazione e/o mostrare i risultati. In generale le classi dentro il percorso [net.berack.upo.valpre](src/main/java/net/berack/upo/valpre) sono usate per l'utilizzo del jar e quindi non sono essenziali per la simulazione.
I percorsi che invece sono direttamente responsabili per la simulazione sono:
@@ -54,34 +50,64 @@ I percorsi che invece sono direttamente responsabili per la simulazione sono:
- **ConsoleTable** utile per mostrare i risultati in console sottoforma di tabella
- **CsvResult** utile per la lettura/scrittura dei risultati in formato csv
---
### Esempi
## Esempi
Nel jar sono presenti già 2 reti per fare degli esperimenti e/o testare se il tool funziona correttamente. Per poter vedere una run usando questi esempi basta far partire il tool in modalità interattiva e scegliere di caricare gli esempi.\
`java -jar upo-valpre.jar interactive`
`java -jar upo-valpre.jar interactive`\
Questa libreria è stata confrontata con il tool [JMT](https://jmt.sourceforge.net/Download.html); le reti usate per fare il confronto si possono trovare sotto [le risorse del test](src/test/resources) e in esse ci sono anche i risultati ottenuti dalle run.\
Inoltre in alcune istanze state modificate le due reti di esempio in modo da mostrare cosa succede con l'aumento del numero di clienti nel sistema e cambiando la distribuzione di servizio di un nodo. Ogni valore ottenuto ha un sample di 1000 simulazioni. I risultati possono essere presi dal seguente [link](https://docs.google.com/spreadsheets/d/1yM1fvlpc2mIIpRe8M7_ry8m3DC3ZxNA204mM60O2hoQ/edit?usp=sharing)\
Le distribuzioni usate hanno tutte la stessa media μ:
- Normale(μ, 0.6)
- Uniforme(μ - (μ\*0.1), μ + (μ\*0.1))
- Esponenziale(1/μ)
- Erlang(5, 5/μ)
- Iperesponenziale(p=\[0.5, 0.5\], e=\[1/(μ\*0.5), 1/(μ\*1.5)\])
##### Primo esempio
### Primo esempio
![1741862746304](image/README/1741862746304.png)\
Il primo è `example1`; è una rete composta da una fonte di clienti (Source) che arrivano con tasso esponenziale (λ=0.222 e quindi media 4.5) e un centro di servizio (Queue) con tasso di servizio distribuito come una normale (μ=3.2, σ=0.6).\
Se si effettua una simulazione si vedranno i risultati sulla console in questo modo:
Se si effettua una simulazione si vedranno i risultati sulla console in questo modo:\
![1741860064265](image/README/1741860064265.png)
Il tool JMT con la stessa rete produce i seguenti risultati che sono molto simili a quelli prodotti dalla libreria:\
Queue Response Time = 7.3022 con un range [7.1456, 7.4589]\
Queue Throughput = 0.2226 con un range [0.2182, 0.2271]\
Queue Utilization = 0.7111 con un range [0.6959, 0.7262]
O se si utilizza la parte grafica si possono vedere i risultati della Queue con l'incertezza:\
![1744786768084](image/README/1744786768084.png)
##### Secondo esempio
Il tool JMT con la stessa rete produce i seguenti risultati che sono molto simili a quelli prodotti dalla libreria:
```
Response Time (Queue) 7.3022 con range [7.1456, 7.4589]
Throughput (Queue) 0.2226 con range [0.2182, 0.2271]
Utilization (Queue) 0.7111 con range [0.6959, 0.7262]
```
Successivamente ho cambiato la distribuzione di servizio usata dal nodo "Queue".\
Come si può notare l'utilizzo e il throughput rimangono pressochè invariati tra le varie distribuzioni, ma convergono con l'aumentare dei clienti.\
I valori che cambiano sono il **numero medio della coda**, il **tempo medio di attesa** e, di conseguenza, anche il **tempo medio di risposta**.\
![1742150755381](image/README/1742150755381.png)\
Di seguito si può vedere il cambiamento del tempo medio di attesa, il numero medio della coda e l'utilizzazione al variare del numero di clienti nel sistema.\
![1742556358341](image/README/1742556358341.png)
### Secondo esempio
![1741863043733](image/README/1741863043733.png)\
Il secondo esempio è `example2`; è una rete composta da una fonte di clienti (Source) che arrivano con tasso esponenziale (λ=1.5 e quindi media 0.666), un centro di servizio (Service1) con tasso di servizio distribuito come una esponenziale (λ=2.0 e quindi media 0.5) e un altro centro di servizio (Service2) con tasso di servizio distribuito come una esponenziale (λ=3.5 e quindi media 0.2857) e con un tempo di indisponibilità che viene attivato con probabilità 10% e distribuito con una eseponenziale (λ=10.0 e quindi media 0.1)\
Se si effettua una simulazione si vedranno i risultati sulla console in questo modo:
Se si effettua una simulazione si vedranno i risultati sulla console in questo modo:\
![1741862486547](image/README/1741862486547.png)
Il tool JMT con la stessa rete produce i seguenti risultati che sono molto simili a quelli prodotti dalla libreria:\
Service1 Response Time ~ 1.9866\
Busy2 Response Time ~ 0.2825\
Queue2 Response Time ~ 0.2279\
Service1 Utilization ~ 0.7488\
Calibration Number of Customers ~ 0.0150\
Busy2 Number of Customers ~ 0.4279\
Throughput ~ 1.5000
O se si utilizza la parte grafica si possono vedere i risultati del Service2 con l'incertezza:\
![1744786814771](image/README/1744786814771.png)
Il tool JMT con la stessa rete produce i seguenti risultati che sono molto simili a quelli prodotti dalla libreria:
```
Response Time (Service1) 2.0115 con range [1.9671, 2.0559]
Response Time (Busy2) 0.2858 con range [0.2816, 0.2899]
Response Time (Queue2) 0.2318 con range [0.2250, 0.2387]
Utilization (Service1) 0.7472 con range [0.7410, 0.7534]
Number of Customers (Busy2) 0.4285 con range [0.4248, 0.4322]
Number of Customers (Calibration) 0.0149 con range [0.0148, 0.0151]
Throughput del Sistema 1.5094 con range [1.5005, 1.5183]
```
Successivamente ho cambiato la distribuzione di servizio usata dal nodo "Service2".\
Anche in questo caso l'utilizzo e il throughput rimangono pressochè invariati e convergono con l'aumentare dei clienti nel sistema, ma cambiano il **numero medio della coda** e il **tempo medio di attesa**.![1744793029362](image/README/1744793029362.png)\
Una particolarità di questa rete è il basso valore atteso per il tempo di servizio. Questo, in concomitanza con il resample in caso di valori negativi, fa si di aumentare la media della Distribuzione Normale. Nei grafici seguenti è stata inclusa la Normale solo nell'ultimo per mostrare la differenza rispetto le altre distribuzioni.\
![1742632017987](image/README/1742632017987.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -41,5 +41,10 @@
<artifactId>jfreechart</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>net.sourceforge.argparse4j</groupId>
<artifactId>argparse4j</artifactId>
<version>0.9.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,16 +1,15 @@
package net.berack.upo.valpre;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import com.esotericsoftware.kryo.KryoException;
import net.berack.upo.valpre.rand.Distribution;
import net.berack.upo.valpre.rand.Rng;
import net.berack.upo.valpre.sim.Net;
import net.berack.upo.valpre.sim.ServerNode;
@@ -137,16 +136,17 @@ public class InteractiveConsole {
/**
* Run the simulation with the net.
*/
private void simpleRuns() throws InterruptedException, ExecutionException, IOException {
var choice = choose("Choose what to do:", "100 Run", "1K Runs", "1K Runs + Plot");
private void simpleRuns() throws Exception {
var choice = choose("Choose what to do:", "100 Run", "1K Runs", "Run max 10K with confidence", "Back");
var seed = Rng.newSeed();
var csv = "run" + seed + ".csv";
switch (choice) {
case 1 -> new SimulationBuilder(net).setMaxRuns(100).setParallel(true).run();
case 2 -> new SimulationBuilder(net).setMaxRuns(1000).setParallel(true).run();
case 1 -> new SimulationBuilder(net).setSeed(seed).setMaxRuns(100).setParallel(true).setCsv(csv).run();
case 2 -> new SimulationBuilder(net).setSeed(seed).setMaxRuns(1000).setParallel(true).setCsv(csv).run();
case 3 -> {
var randName = "rand" + System.currentTimeMillis() + ".csv";
new SimulationBuilder(net).setMaxRuns(1000).setParallel(true).setCsv(randName).run();
new Plot(randName).show();
new File(randName).delete();
var indices = ask("Confidence indices with format [node:stat=confidence:relativeError];[..]\n");
new SimulationBuilder(net).setSeed(seed).setMaxRuns(10000).parseConfidenceIndices(indices).setCsv(csv)
.run();
}
default -> {
}

View File

@@ -2,95 +2,93 @@ package net.berack.upo.valpre;
import java.io.File;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.Namespace;
public class Main {
public static void main(String[] args) {
if (args.length == 0)
exit("No program specified!");
private final static String NAME;
/**
* The name of the program, used for the help message.
*/
static {
var name = "valpre";
try {
var program = args[0];
var subArgs = Arrays.copyOfRange(args, 1, args.length);
switch (program) {
var uri = Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();
name = new File(uri).getName();
} catch (URISyntaxException e) {
}
NAME = name;
}
/**
* The main method of the program. It parses the arguments and runs the
* simulation or the plotter.
*
* @param args the arguments to parse
*/
public static void main(String[] args) {
try {
var param = Main.getParameters(args);
var command = param.getString("command");
switch (command) {
case "simulation" -> {
var param = Main.getParameters(program, subArgs);
new SimulationBuilder(param.get("net"))
.setCsv(param.get("csv"))
.setMaxRuns(param.getOrDefault("runs", Integer::parseInt, 100))
.setSeed(param.getOrDefault("seed", Long::parseLong, 0L))
.setParallel(param.get("p") != null)
.parseEndCriteria(param.get("end"))
.parseConfidenceIndices(param.get("i"))
new SimulationBuilder(param.getString("net"))
.setCsv(param.getString("csv"))
.setMaxRuns(param.getInt("runs"))
.setSeed(param.getLong("seed"))
.setParallel(param.getBoolean("p"))
.parseEndCriteria(param.getString("end"))
.parseConfidenceIndices(param.getString("indices"))
.run();
}
case "plot" -> {
var param = Main.getParameters(program, subArgs);
var csv = param.get("csv");
var csv = param.getString("csv");
var plot = new Plot(csv);
plot.show();
}
case "interactive" -> new InteractiveConsole().run();
default -> exit("Invalid program!");
default -> throw new RuntimeException("Invalid program!"); // Should never happen
}
} catch (Exception e) {
exit(e.getMessage());
}
}
/**
* Get the parameters from the arguments.
*
* @param program the program to run
* @param args the arguments to parse
* @return the parameters
*/
private static Parameters getParameters(String program, String[] args) {
var arguments = new HashMap<String, Boolean>();
arguments.put("p", false);
arguments.put("seed", true);
arguments.put("runs", true);
arguments.put("net", true);
arguments.put("end", true);
arguments.put("csv", true);
arguments.put("i", true);
var descriptions = new HashMap<String, String>();
descriptions.put("p", "Add this if you want the simulation to use threads (one each run).");
descriptions.put("seed", "The seed of the simulation.");
descriptions.put("runs", "How many runs the simulator should run.");
descriptions.put("end", "When the simulation should end. Format is \"[ClassName:param1,..,paramN];[..]\"");
descriptions.put("net", "The file net to use. Use example1.net or example2.net for the provided ones.");
descriptions.put("i", "The confidence indices to use for the simulation. If active then p is ignored."
+ " Format is \"[node:stat=confidence:relativeError];[..]\"");
var csvDesc = switch (program) {
case "simulation" -> "The filename for saving every run statistics.";
case "plot" -> "The filename that contains the previous saved runs.";
default -> "";
};
descriptions.put("csv", csvDesc);
return Parameters.getArgsOrHelper(args, "-", arguments, descriptions);
}
/**
* Exit the program with an error message.
*/
public static void exit(String message) {
try {
var uri = Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();
var name = new File(uri).getName();
System.err.println(message);
System.out.println("Usage: java -jar " + name + ".jar [simulation|plot|interactive] [args]");
System.out.println("simulation args: -net <net> [-csv <csv>] [-runs <runs>] [-seed <seed>]"
+ "[-p] [-end <end>] [-i <indices>]");
System.out.println("plot args: -csv <csv>");
System.out.println("interactive: no args needed");
System.err.println(e.getMessage());
System.exit(1);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
/**
* Parses the arguments of the program. It uses the argparse4j library to parse
* the arguments and return a Namespace object with the parsed arguments.
*
* @param args the arguments to parse
* @return a Namespace object with the parsed arguments
*/
private static Namespace getParameters(String[] args) {
var parser = ArgumentParsers.newFor(NAME).build()
.defaultHelp(true)
.description("Build a network simulation and/or plot the results of a simulation.");
var subparser = parser.addSubparsers().title("commands").description("valid commands").help("subcommand help");
var sim = subparser.addParser("simulation").help("Run a simulation of the network.");
sim.addArgument("-net").help("The file net to use.").required(true);
sim.addArgument("-csv").help("The filename for saving every run statistics.");
sim.addArgument("-runs").type(Integer.class).help("How many runs the simulator should run.").setDefault(100);
sim.addArgument("-seed").type(Long.class).help("The seed of the simulation.").setDefault(0L);
sim.addArgument("-p").action(Arguments.storeTrue()).help("Parallel (one thread each run).").setDefault(false);
sim.addArgument("-end").help("When the simulation should end. Format:\n\"[ClassName:param1,..,paramN];[..]\"");
sim.addArgument("-indices").help("The confidence indices to use for the simulation. If active -p is ignored."
+ " Format:\n\"[node:stat=confidence:relativeError];[..]\"");
var plot = subparser.addParser("plot").help("Plot the results of a simulation.");
plot.addArgument("-csv").help("The filename for the csv file to plot.").required(true);
var _ = subparser.addParser("interactive").help("Run the interactive console.");
// Interactive console does not need any arguments
var namespace = parser.parseArgsOrFail(args);
namespace.getAttrs().put("command", args[0]);
return namespace;
}
}

View File

@@ -1,8 +1,14 @@
package net.berack.upo.valpre;
import java.util.List;
import java.util.function.BiFunction;
import net.berack.upo.valpre.rand.Distribution;
import net.berack.upo.valpre.sim.Net;
import net.berack.upo.valpre.sim.ServerNode;
import net.berack.upo.valpre.sim.SimulationMultiple;
import net.berack.upo.valpre.sim.stats.CsvResult;
import net.berack.upo.valpre.sim.stats.Result;
/**
* This class provides two example networks.
@@ -10,37 +16,111 @@ import net.berack.upo.valpre.sim.ServerNode;
* The second network is composed of a terminal node and two queue nodes.
*/
public final class NetExamples {
/**
* Main method to test the networks.
* The first network will have the distribution changed but the mean will be the
* same. The second network will have the distribution changed but the mean will
* be the same. The results will be saved to a csv file.
*
* @param args not needed
* @throws Exception if the simulation fails or the file is not saved
*/
public static void main(String[] args) throws Exception {
var seed = 123456789L;
runNet(seed, 3.2, 1, "net1.csv", (spawn, dist) -> {
var name = dist.getClass().getSimpleName() + "_" + spawn;
return NetExamples.getNet1(spawn, name, dist);
});
runNet(seed, 1 / 3.5, 2, "net2.csv", (spawn, dist) -> {
var name = dist.getClass().getSimpleName() + "_" + spawn;
return NetExamples.getNet2(spawn, name, dist);
});
}
/**
* Method to test whatever network you input.
* The network will have the distribution changed but the mean will be the same.
* The bifunction requested is to get the network you want to test passing the
* spawn and the distribution with the same mean.
* The network will be tested with spawn totals of 1, 2, 5, 7, 10, 25, 50, 75,
* 100, 250, 500, 750, 1000, 1500, 2000.
* The results will be saved to a csv passed as argument.
*
* @param seed the seed for the simulation
* @param avg the mean of the distribution
* @param nodeToWatch the node to watch
* @param csv the file to save the results
* @param getNet the bifunction to get the network
* @throws Exception if the simulation fails or the file is not saved
*/
public static void runNet(long seed, double avg, int nodeToWatch, String csv,
BiFunction<Integer, Distribution, Net> getNet) throws Exception {
var build = new Result.Builder().seed(seed);
var spawnTotals = new int[] { 1, 2, 5, 7, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 1500, 2000 };
var normal = new Distribution.NormalBoxMuller(avg, 0.6);
var exponential = new Distribution.Exponential(1 / avg);
var erlang = new Distribution.Erlang(5, 5 / avg);
var uniform = new Distribution.Uniform(avg - (avg * 0.1), avg + (avg * 0.1));
var hyper = new Distribution.HyperExponential(
new double[] { 1 / (avg * 0.5), 1 / (avg * 1.5) },
new double[] { 0.5f, 0.5f });
for (var spawn : spawnTotals) {
System.out.println("Spawn: " + spawn);
var nets = new Net[] {
getNet.apply(spawn, normal),
getNet.apply(spawn, exponential),
getNet.apply(spawn, erlang),
getNet.apply(spawn, uniform),
getNet.apply(spawn, hyper),
};
for (var net : nets) {
var summary = new SimulationMultiple(net).runParallel(build.seed, 1000);
var name = net.getNode(nodeToWatch).name;
var stat = summary.getSummaryOf(name).average;
build.addNode(name, stat);
}
}
var result = build.build();
new CsvResult(csv).saveResults(List.of(result));
System.out.println("Results saved to " + csv);
}
/**
* Return the first example network.
* The net is composed of a terminal node and a queue node.
* The terminal node generates 10000 jobs with an exponential distribution 4.5.
* The queue node has a capacity of 1 and a service time of 3.2 with a standard
* deviation of 0.6.
* The terminal node is connected to the queue node with a probability of 1.0.
*
* @return the first example network
*/
public static Net getNet1() {
var exp0_22 = new Distribution.Exponential(1.0 / 4.5);
var norm3_2 = new Distribution.NormalBoxMuller(3.2, 0.6);
var spawn = 10000;
return getNet1(spawn, exp0_22, norm3_2);
return getNet1(10000, "Queue", norm3_2);
}
/**
* Return the first example network.
* The net is composed of a terminal node and a queue node.
* The terminal node is connected to the queue node.
* The terminal node generates N jobs with an exponential distribution 4.5.
*
* @param spawn the number of jobs to generate
* @param source the distribution of the source node
* @param queue the distribution of the queue node
* @param spawn the number of jobs to generate
* @param name the name of the queue node
* @param queue the distribution of the queue node
* @return the first example network
*/
public static Net getNet1(int spawn, Distribution source, Distribution queue) {
public static Net getNet1(int spawn, String name, Distribution queue) {
var source = new Distribution.Exponential(1.0 / 4.5);
var net1 = new Net();
net1.addNode(ServerNode.Builder.terminal("Source", spawn, source));
net1.addNode(ServerNode.Builder.queue("Queue", 1, queue));
net1.addNode(ServerNode.Builder.queue(name, 1, queue));
net1.addConnection(0, 1, 1.0);
return net1;
}
@@ -59,13 +139,8 @@ public final class NetExamples {
* @return the second example network
*/
public static Net getNet2() {
var exp1_5 = new Distribution.Exponential(1.5);
var exp2 = new Distribution.Exponential(2.0);
var exp3_5 = new Distribution.Exponential(3.5);
var exp10 = new Distribution.Exponential(10.0);
var unExp = new Distribution.UnavailableTime(0.1, exp10);
var spawn = 10000;
return getNet2(spawn, exp1_5, exp2, exp3_5, unExp);
return getNet2(10000, "Service2", exp3_5);
}
/**
@@ -75,18 +150,20 @@ public final class NetExamples {
* The first queue node is connected to the second queue node.
*
* @param spawn the number of jobs to generate
* @param source the distribution of the source node
* @param service1 the distribution of the first queue node
* @param name the name of the second queue node
* @param service2 the distribution of the second queue node
* @param unExp the distribution of the unavailable time
* @return the second example network
*/
public static Net getNet2(int spawn, Distribution source, Distribution service1, Distribution service2,
Distribution unExp) {
public static Net getNet2(int spawn, String name, Distribution service2) {
var exp1_5 = new Distribution.Exponential(1.5);
var exp2 = new Distribution.Exponential(2.0);
var exp10 = new Distribution.Exponential(10.0);
var unExp = new Distribution.UnavailableTime(0.1, exp10);
var net3 = new Net();
net3.addNode(ServerNode.Builder.terminal("Source", spawn, source));
net3.addNode(ServerNode.Builder.queue("Service1", 1, service1));
net3.addNode(ServerNode.Builder.queue("Service2", 1, service2, unExp));
net3.addNode(ServerNode.Builder.terminal("Source", spawn, exp1_5));
net3.addNode(ServerNode.Builder.queue("Service", 1, exp2));
net3.addNode(ServerNode.Builder.queue(name, 1, service2, unExp));
net3.addConnection(0, 1, 1.0);
net3.addConnection(1, 2, 1.0);
return net3;

View File

@@ -1,194 +0,0 @@
package net.berack.upo.valpre;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* Class that helps with parsing the parameters passed as input in the console.
*/
public class Parameters {
private final Map<String, Boolean> arguments;
private final String prefix;
private Map<String, String> parameters;
/**
* Constructs a new Parameters object with the specified prefix and arguments.
* The arguments can be with value, in that case in the map the boolean should
* be true, otherwise it is only an argument that is a flag
*
* @param prefix the prefix to be used
* @param arguments a map of arguments where the key is a string and if the
* boolean is true then the argument expect a value
* @throws IllegalArgumentException if the arguments map is null or empty
*/
public Parameters(String prefix, Map<String, Boolean> arguments) {
if (arguments == null || arguments.size() == 0)
throw new IllegalArgumentException();
this.arguments = arguments;
this.prefix = prefix;
}
/**
* Get the size of the parameters.
*
* @return the size of the parameters
*/
public int size() {
return this.parameters.size();
}
/**
* Get the value of the argument passed as input.
*
* @param key the key of the argument
* @return the value of the argument
*/
public String get(String key) {
if (this.parameters == null)
return null;
return this.parameters.get(key);
}
/**
* Get the value from the arguments or the default value if it is not present.
*
* @param key The key to get the value from.
* @param parse The function to parse the value.
* @param value The default value if the key is not present.
* @return The value from the arguments or the default value if it is not
* present.
*/
public <T> T getOrDefault(String key, Function<String, T> parse, T value) {
var arg = this.get(key);
return arg != null ? parse.apply(arg) : value;
}
/**
* Return a string with the standard <arggument> <description> spaced enough
*
* @param eventualDescription the description for the argument, if not present
* the argument will be shown anyway/
* @return a string of arguments
*/
public String helper(Map<String, String> eventualDescription) {
var size = 0;
var parameters = new HashMap<String, String>();
for (var param : this.arguments.entrySet()) {
var string = this.prefix + param.getKey();
if (param.getValue())
string += " <value>";
parameters.put(param.getKey(), string);
size = Math.max(size, string.length());
}
size += 2; // spacing
var builder = new StringBuilder();
for (var param : parameters.entrySet()) {
var key = param.getKey();
var args = param.getValue();
builder.append(" ");
builder.append(args);
var desc = eventualDescription.get(key);
if (desc != null) {
builder.append(" ".repeat(size - args.length()));
builder.append(desc);
}
builder.append("\n");
}
return builder.toString();
}
/**
* Parse the arguments passed and build a map of Argument --> Value that can
* be used to retrieve the information. In the case that the arguments are not
* in the correct format then an exception is thrown.
* To get the arguments use the {@link #get(String)} method.
*
* @param args the arguments in input
* @throws IllegalArgumentException if the arguments are not formatted correctly
* or if there is an unknown argument or there
* are not arguments in the input
*/
public void parse(String[] args) {
if (args == null || args.length == 0)
throw new IllegalArgumentException("No arguments passed");
var result = new HashMap<String, String>();
for (var i = 0; i < args.length; i += 1) {
var current = args[i];
var next = i + 1 < args.length ? args[i + 1] : null;
var updateI = this.parseSingle(current, next, result);
if (updateI)
i += 1;
}
this.parameters = result;
}
/**
* Parse one single argument and put it into the map.
*
* @param current the current argument
* @param next the next argument if present
* @param result the map where to insert the value
* @throws IllegalArgumentException if the arguments are not formatted correctly
* or if there is an unknown argument
* @return true if the next argument is used
*/
private boolean parseSingle(String current, String next, Map<String, String> result) {
if (!current.startsWith(this.prefix))
throw new IllegalArgumentException("Missing prefix [" + current + "]");
current = current.substring(this.prefix.length());
var value = this.arguments.get(current);
if (value != null) {
result.put(current, value ? next : "");
return value;
}
var finalSize = result.size() + current.length();
for (var letter : current.split(""))
if (this.arguments.get(letter) != null)
result.put(current, "");
if (finalSize != result.size())
throw new IllegalArgumentException("Unknown argument [" + current + "]");
return false;
}
/**
* Parse the arguments passed and returns a map of Argument --> Value that can
* be used to retrieve the information. In the case that the arguments are not
* in the correct format then an exception is thrown and the helper is printed.
* If the arguments passed are 0 then the helper is printed.
*
* @param args the arguments in input
* @param prefix the prefix to be used
* @param arguments a map of arguments where the key is a string and if the
* boolean is true then the argument expect a value
* @param descriptions a map of descriptions for the arguments
* @throws IllegalArgumentException if the arguments are not formatted correctly
* or if there is an unknown argument
* @return a map of the values
*/
public static Parameters getArgsOrHelper(String[] args, String prefix, Map<String, Boolean> arguments,
Map<String, String> descriptions) {
var param = new Parameters(prefix, arguments);
try {
param.parse(args);
return param;
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
System.out.println(param.helper(descriptions));
throw new IllegalArgumentException("Invalid arguments");
}
}
}

View File

@@ -44,7 +44,7 @@ public class Plot {
var results = new CsvResult(csv).loadResults();
this.summary = new Result.Summary(results);
var nodes = this.summary.getNodes().toArray(new String[0]);
var nodes = this.summary.getNodes();
this.panelBarChart = new ChartPanel(null);
this.nodeComboBox = new JComboBox<>(nodes);
@@ -113,7 +113,7 @@ public class Plot {
var frame = new JFrame("Graph of the Simulation");
frame.add(rootPane);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
});
}

View File

@@ -131,4 +131,13 @@ public class Rng {
var t = multiplier * (seed % Q) - R * (seed / Q);
return t > 0 ? t : (t + modulus);
}
/**
* This creates a new seed based on the current time.
*
* @return a new seed
*/
public static long newSeed() {
return System.currentTimeMillis() % MODULUS;
}
}

View File

@@ -1,209 +0,0 @@
package net.berack.upo.valpre.rand;
/* --------------------------------------------------------------------------
* This is a Java library for generating random variates from six discrete
* distributions
*
* Generator Range (x) Mean Variance
*
* bernoulli(p) x = 0,1 p p*(1-p)
* binomial(n, p) x = 0,...,n n*p n*p*(1-p)
* equilikely(a, b) x = a,...,b (a+b)/2 ((b-a+1)*(b-a+1)-1)/12
* Geometric(p) x = 0,... p/(1-p) p/((1-p)*(1-p))
* pascal(n, p) x = 0,... n*p/(1-p) n*p/((1-p)*(1-p))
* poisson(m) x = 0,... m m
*
* and seven continuous distributions
*
* uniform(a, b) a < x < b (a + b)/2 (b - a)*(b - a)/12
* exponential(m) x > 0 m m*m
* erlang(n, b) x > 0 n*b n*b*b
* normal(m, s) all x m s*s
* logNormal(a, b) x > 0 see below
* chiSquare(n) x > 0 n 2*n
* student(n) all x 0 (n > 1) n/(n - 2) (n > 2)
*
* For the a Lognormal(a, b) random variable, the mean and variance are
*
* mean = exp(a + 0.5*b*b)
* variance = (exp(b*b) - 1) * exp(2*a + b*b)
*
* Name : Rvgs.java (Random Variate GeneratorS)
* Authors : Steve Park & Dave Geyer
* Translated by : Richard Dutton & Jun Wang
* Language : Java
* Latest Revision : 7-1-04
* --------------------------------------------------------------------------
*/
public class Rvgs {
private final Rng rng;
// public Rvgs() {
// this.rngs = new Rngs(Rng.DEFAULT);
// }
public Rvgs(Rng rng) {
if (rng == null)
throw new NullPointerException();
this.rng = rng;
}
/**
* Returns 1 with probability p or 0 with probability 1 - p.
* NOTE: use 0.0 < p < 1.0
*/
public long bernoulli(double p) {
return ((this.rng.random() < (1.0 - p)) ? 0 : 1);
}
/**
* Returns a binomial distributed integer between 0 and n inclusive.
* NOTE: use n > 0 and 0.0 < p < 1.0
*/
public long binomial(long n, double p) {
long i, x = 0;
for (i = 0; i < n; i++)
x += bernoulli(p);
return (x);
}
/**
* Returns an equilikely distributed integer between a and b inclusive.
* NOTE: use a < b
*/
public long equilikely(long a, long b) {
return (a + (long) ((b - a + 1) * this.rng.random()));
}
/**
* Returns a geometric distributed non-negative integer.
* NOTE: use 0.0 < p < 1.0
*/
public long geometric(double p) {
return ((long) (Math.log(1.0 - this.rng.random()) / Math.log(p)));
}
/**
* Returns a Pascal distributed non-negative integer.
* NOTE: use n > 0 and 0.0 < p < 1.0
*/
public long pascal(long n, double p) {
long i, x = 0;
for (i = 0; i < n; i++)
x += geometric(p);
return (x);
}
/**
* Returns a Poisson distributed non-negative integer.
* NOTE: use m > 0
*/
public long poisson(double m) {
double t = 0.0;
long x = 0;
while (t < m) {
t += exponential(1.0);
x++;
}
return (x - 1);
}
/**
* Returns a uniformly distributed real number between a and b.
* NOTE: use a < b
*/
public double uniform(double a, double b) {
return (a + (b - a) * this.rng.random());
}
/**
* Returns an exponentially distributed positive real number.
* NOTE: use m > 0.0
*/
public double exponential(double m) {
return (-m * Math.log(1.0 - this.rng.random()));
}
/**
* Returns an Erlang distributed positive real number.
* NOTE: use n > 0 and b > 0.0
*/
public double erlang(long n, double b) {
long i;
double x = 0.0;
for (i = 0; i < n; i++)
x += exponential(b);
return (x);
}
/**
* Returns a normal (Gaussian) distributed real number.
* NOTE: use s > 0.0
*
* Uses a very accurate approximation of the normal idf due to Odeh & Evans,
* J. Applied Statistics, 1974, vol 23, pp 96-97.
*/
public double normal(double m, double s) {
final double p0 = 0.322232431088;
final double q0 = 0.099348462606;
final double p1 = 1.0;
final double q1 = 0.588581570495;
final double p2 = 0.342242088547;
final double q2 = 0.531103462366;
final double p3 = 0.204231210245e-1;
final double q3 = 0.103537752850;
final double p4 = 0.453642210148e-4;
final double q4 = 0.385607006340e-2;
double u, t, p, q, z;
u = this.rng.random();
if (u < 0.5)
t = Math.sqrt(-2.0 * Math.log(u));
else
t = Math.sqrt(-2.0 * Math.log(1.0 - u));
p = p0 + t * (p1 + t * (p2 + t * (p3 + t * p4)));
q = q0 + t * (q1 + t * (q2 + t * (q3 + t * q4)));
if (u < 0.5)
z = (p / q) - t;
else
z = t - (p / q);
return (m + s * z);
}
/**
* Returns a lognormal distributed positive real number.
* NOTE: use b > 0.0
*/
public double logNormal(double a, double b) {
return (Math.exp(a + b * normal(0.0, 1.0)));
}
/**
* Returns a chi-square distributed positive real number.
* NOTE: use n > 0
*/
public double chiSquare(long n) {
long i;
double z, x = 0.0;
for (i = 0; i < n; i++) {
z = normal(0.0, 1.0);
x += z * z;
}
return (x);
}
/**
* Returns a student-t distributed real number.
* NOTE: use n > 0
*/
public double student(long n) {
return (normal(0.0, 1.0) / Math.sqrt(chiSquare(n) / n));
}
}

View File

@@ -146,5 +146,4 @@ public class SimulationMultiple {
stream.println(); // remove last printed line
return results;
}
}

View File

@@ -21,13 +21,27 @@ public class ConsoleTable {
* @throws NullPointerException if the array is null
*/
public ConsoleTable(String... header) {
var max = 0;
this(-1, header);
}
/**
* Create a new table with the header passed as input.
* The table will have as many columns as the length of the header array.
* Each column will have the same size and will be the max length of all the
* headers string or the maxLen passed as input.
*
* @param maxLen the max length of the columns
* @param header an array of strings
* @throws NullPointerException if the array is null
*/
public ConsoleTable(int maxLen, String... header) {
var max = Math.max(0, maxLen);
for (var name : header)
max = Math.max(max, name.length());
this.columns = header.length;
this.maxLen = max + 2;
this.border = ("+" + "".repeat(maxLen)).repeat(header.length) + "+\n";
this.border = ("+" + "".repeat(this.maxLen)).repeat(header.length) + "+\n";
this.builder.append(border);
this.addRow(header);
}
@@ -45,11 +59,11 @@ public class ConsoleTable {
for (var val : values) {
var diff = maxLen - val.length();
var first = (int) Math.ceil(diff / 2.0);
var first = Math.max((int) Math.ceil(diff / 2.0), 0);
builder.append('║');
builder.append(" ".repeat(first));
builder.append(val);
builder.append(" ".repeat(diff - first));
builder.append(" ".repeat(Math.max(diff - first, 0)));
}
builder.append("\n");

View File

@@ -1,6 +1,7 @@
package net.berack.upo.valpre.sim.stats;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -36,6 +37,11 @@ public class Result implements Iterable<Entry<String, NodeStats>> {
this.stats = stats;
}
/**
* Gets the stats of a node.
*
* @return the stats of a node
*/
public NodeStats getStat(String node) {
for (var i = 0; i < this.nodes.length; i++)
if (this.nodes[i].equals(node))
@@ -45,7 +51,7 @@ public class Result implements Iterable<Entry<String, NodeStats>> {
@Override
public String toString() {
return buildPrintable(this.seed, this.simulationTime, this.timeElapsedMS, this.nodes, this.stats);
return getResultString(this.seed, this.simulationTime, this.timeElapsedMS, this.nodes, this.stats);
}
@Override
@@ -80,9 +86,8 @@ public class Result implements Iterable<Entry<String, NodeStats>> {
* @param stats the stats of each node
* @return a string representation of the result
*/
private static String buildPrintable(long seed, double simTime, double timeMS, String[] nodes, NodeStats[] stats) {
public static String getResultString(long seed, double simTime, double timeMS, String[] nodes, NodeStats[] stats) {
var size = (int) Math.ceil(Math.max(Math.log10(simTime), 1));
var iFormat = "%" + size + ".0f";
var fFormat = "%" + (size + 4) + ".3f";
var builder = new StringBuilder();
@@ -90,9 +95,35 @@ public class Result implements Iterable<Entry<String, NodeStats>> {
builder.append(String.format("Seed: \t%d\n", seed));
builder.append(String.format("Simulation: \t" + fFormat + "\n", simTime));
builder.append(String.format("Elapsed: \t" + fFormat + "ms\n", timeMS));
builder.append(getResultString(nodes, stats));
return builder.toString();
}
var table = new ConsoleTable("Node", "Departures", "Avg Queue", "Avg Wait", "Avg Response", "Throughput",
"Utilization %", "Unavailable %", "Last Event");
/**
* Create a string representation of the result. It only display the stats of
* each node in a table format.
*
* @param nodes the names of the nodes
* @param stats the stats of each node
* @return a string representation of the result
* @throws AssertionError if the nodes and stats do not match
*/
public static String getResultString(String[] nodes, NodeStats[] stats) {
assert nodes.length == stats.length;
var size = (int) Math.ceil(Math.max(Math.log10(stats[0].lastEventTime), 1));
var iFormat = "%" + size + ".0f";
var fFormat = "%" + (size + 4) + ".3f";
var builder = new StringBuilder();
var maxNameLen = 0;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
maxNameLen = Math.max(node.length(), maxNameLen);
}
var table = new ConsoleTable(maxNameLen, "Node", "Departures", "Avg Queue", "Avg Wait", "Avg Response",
"Throughput", "Utilization %", "Unavailable %", "Last Event");
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
@@ -206,12 +237,24 @@ public class Result implements Iterable<Entry<String, NodeStats>> {
}
/**
* Gets the nodes of the summary.
* Gets a copy of the nodes of the summary.
*
* @return the nodes of the summary
*/
public List<String> getNodes() {
return List.of(this.nodes);
public String[] getNodes() {
return Arrays.copyOf(this.nodes, this.nodes.length);
}
/**
* Gets the statistics of the nodes of the summary.
*
* @return the statistics of the nodes of the summary
*/
public NodeStats[] getStats() {
var stats = new NodeStats[this.nodes.length];
for (var i = 0; i < this.nodes.length; i++)
stats[i] = this.stats[i].average;
return stats;
}
/**
@@ -239,11 +282,8 @@ public class Result implements Iterable<Entry<String, NodeStats>> {
@Override
public String toString() {
var stats = new NodeStats[this.nodes.length];
for (var i = 0; i < this.nodes.length; i++)
stats[i] = this.stats[i].average;
return buildPrintable(this.seed, this.avgSimulationTime, this.avgTimeElapsedMS, this.nodes, stats);
return getResultString(this.seed, this.avgSimulationTime, this.avgTimeElapsedMS, this.nodes,
this.getStats());
}
}

View File

@@ -55,4 +55,23 @@ public class TestRandom {
assertTrue("Standard Dev must be less than [" + expected + "] -> [" + stdDev + "]", stdDev < expected);
}
@Test
public void testMean() {
var rng = new Rng();
var normal = new Distribution.NormalBoxMuller(1 / 3.5, 0.6);
var mean = 0.0;
for (var i = 0; i < 100000; i++) {
var sample = Distribution.getPositiveSample(normal, rng);
mean = (mean * (i + 1) + sample) / (i + 2);
}
assertEquals(0.6, mean, 0.01);
for (var i = 0; i < 100000; i++) {
var sample = Math.max(0, normal.sample(rng));
mean = (mean * (i + 1) + sample) / (i + 2);
}
assertEquals(0.41, mean, 0.01);
}
}

View File

@@ -144,8 +144,8 @@ public class TestInteractions {
// Test the interactive console LOAD EXAMPLE 2
net = runInteraction("4", "2", "2", "7");
assertEquals("Source[servers:1, queue:100, spawn:10000, Exponential(1.5)] -> Service1(1.0)\n"
+ "Service1[servers:1, queue:100, spawn:0, Exponential(2.0)] -> Service2(1.0)\n"
assertEquals("Source[servers:1, queue:100, spawn:10000, Exponential(1.5)] -> Service(1.0)\n"
+ "Service[servers:1, queue:100, spawn:0, Exponential(2.0)] -> Service2(1.0)\n"
+ "Service2[servers:1, queue:100, spawn:0, Exponential(3.5), u:UnavailableTime(0.1, Exponential(10.0))] -\n",
net.toString());
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<archive xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="example3.jsimg" timestamp="Thu Mar 13 12:37:25 CET 2025" xsi:noNamespaceSchemaLocation="Archive.xsd">
<sim disableStatisticStop="false" logDecimalSeparator="," logDelimiter=";" logPath="C:\Users\giaco\JMT" logReplaceMode="0" maxEvents="-1" maxSamples="100000000" name="example3.jsimg" polling="1.0" xsi:noNamespaceSchemaLocation="SIMmodeldefinition.xsd">
<archive xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="example2.jsimg" timestamp="Wed Apr 02 14:09:03 CEST 2025" xsi:noNamespaceSchemaLocation="Archive.xsd">
<sim disableStatisticStop="false" logDecimalSeparator="," logDelimiter=";" logPath="C:\Users\giaco\JMT" logReplaceMode="0" maxEvents="-1" maxSamples="100000000" name="example2.jsimg" polling="1.0" xsi:noNamespaceSchemaLocation="SIMmodeldefinition.xsd">
<userClass name="Class1" priority="0" referenceSource="Source 1" softDeadline="0.0" type="open"/>
<userClass customers="1" name="Class2" priority="0" referenceSource="IdleServer2" softDeadline="0.0" type="closed"/>
<node name="Service1">
@@ -853,13 +853,13 @@
</parameter>
</section>
</node>
<measure alpha="0.02" name="System Throughput" nodeType="" precision="0.01" referenceNode="" referenceUserClass="" type="System Throughput" verbose="false"/>
<measure alpha="0.02" name="Class1_System Throughput" nodeType="" precision="0.01" referenceNode="" referenceUserClass="Class1" type="System Throughput" verbose="false"/>
<measure alpha="0.02" name="Service1_Class1_Utilization" nodeType="station" precision="0.01" referenceNode="Service1" referenceUserClass="Class1" type="Utilization" verbose="false"/>
<measure alpha="0.02" name="Calibration_Class2_Number of Customers" nodeType="station" precision="0.01" referenceNode="Calibration" referenceUserClass="Class2" type="Number of Customers" verbose="false"/>
<measure alpha="0.02" name="Busy2_Class1_Number of Customers" nodeType="station" precision="0.01" referenceNode="Busy2" referenceUserClass="Class1" type="Number of Customers" verbose="false"/>
<measure alpha="0.02" name="Busy2_Number of Customers" nodeType="station" precision="0.01" referenceNode="Busy2" referenceUserClass="" type="Number of Customers" verbose="false"/>
<measure alpha="0.02" name="Calibration_Number of Customers" nodeType="station" precision="0.01" referenceNode="Calibration" referenceUserClass="" type="Number of Customers" verbose="false"/>
<measure alpha="0.01" name="Service1_Class1_Response Time" nodeType="station" precision="0.03" referenceNode="Service1" referenceUserClass="Class1" type="Response Time" verbose="false"/>
<measure alpha="0.01" name="Queue2_Response Time" nodeType="station" precision="0.03" referenceNode="Queue2" referenceUserClass="" type="Response Time" verbose="false"/>
<measure alpha="0.01" name="Busy2_Response Time" nodeType="station" precision="0.03" referenceNode="Busy2" referenceUserClass="" type="Response Time" verbose="false"/>
<measure alpha="0.01" name="Queue2_Response Time" nodeType="station" precision="0.03" referenceNode="Queue2" referenceUserClass="" type="Response Time" verbose="false"/>
<connection source="Service1" target="Queue2"/>
<connection source="Queue2" target="StartService2"/>
<connection source="Busy2" target="Service2"/>
@@ -923,78 +923,75 @@
<position angle="0.0" rotate="true" x="505.0" y="328.0"/>
</station>
</jmodel>
<results elapsedTime="36465" logDecimalSeparator="," logDelimiter=";" pollingInterval="1.0" xsi:noNamespaceSchemaLocation="Results.xsd">
<measure alpha="0.98" analyzedSamples="163840" discardedSamples="20" finalValue="4.5232841623024065" name="System Throughput" nodeType="" precision="0.01" referenceClass="" referenceStation="" state="1" type="16">
<sample lastIntervalAvgValue="4.504801490858249" lowerBound="4.458882972372562" meanValue="4.529318694858492" simulationTime="21776.09828070597" upperBound="4.602015440763236"/>
<sample lastIntervalAvgValue="4.5282972183892385" lowerBound="4.482148935563637" meanValue="4.5232841623024065" simulationTime="36299.65908694518" upperBound="4.56518142536432"/>
<results elapsedTime="22985" logDecimalSeparator="," logDelimiter=";" pollingInterval="1.0" xsi:noNamespaceSchemaLocation="Results.xsd">
<measure alpha="0.98" analyzedSamples="163840" discardedSamples="60" finalValue="1.501221406545825" name="Class1_System Throughput" nodeType="" precision="0.01" referenceClass="Class1" referenceStation="" state="1" type="16">
<sample lastIntervalAvgValue="1.5106622983340463" lowerBound="1.468486049955798" meanValue="1.50631035481992" simulationTime="13876.695025167392" upperBound="1.546134682461421"/>
<sample lastIntervalAvgValue="1.4986167692697017" lowerBound="1.4786226101201805" meanValue="1.5021490600601366" simulationTime="64253.81714744975" upperBound="1.5264362760056998"/>
<sample lastIntervalAvgValue="1.5036451787298382" lowerBound="1.4886800249805132" meanValue="1.501221406545825" simulationTime="109105.4889075181" upperBound="1.5139758930959133"/>
</measure>
<measure alpha="0.98" analyzedSamples="163840" discardedSamples="645" finalValue="0.7488388343771116" name="Service1_Class1_Utilization" nodeType="station" precision="0.01" referenceClass="Class1" referenceStation="Service1" state="1" type="6">
<sample lastIntervalAvgValue="0.7535064165853067" lowerBound="0.7347511898562679" meanValue="0.7554442760158694" simulationTime="21775.473427065597" upperBound="0.7761373621754709"/>
<sample lastIntervalAvgValue="0.7445105711875073" lowerBound="0.7407212322280543" meanValue="0.7498037610368465" simulationTime="70354.5805071057" upperBound="0.7588862898456388"/>
<sample lastIntervalAvgValue="0.7586119497689925" lowerBound="0.7431437478710194" meanValue="0.7488388343771116" simulationTime="87689.27209134017" upperBound="0.7545339208832038"/>
<measure alpha="0.98" analyzedSamples="327680" discardedSamples="65" finalValue="0.7471951139971086" name="Service1_Class1_Utilization" nodeType="station" precision="0.01" referenceClass="Class1" referenceStation="Service1" state="1" type="6">
<sample lastIntervalAvgValue="0.7580797914843828" lowerBound="0.7284349220101368" meanValue="0.758341372366939" simulationTime="13876.28919854346" upperBound="0.7882478227237412"/>
<sample lastIntervalAvgValue="0.7437399633757887" lowerBound="0.7338157319545954" meanValue="0.7479059359761921" simulationTime="64255.194361328504" upperBound="0.7619961399977889"/>
<sample lastIntervalAvgValue="0.7481274953188917" lowerBound="0.7385472374512729" meanValue="0.7465206013494042" simulationTime="112954.31879089898" upperBound="0.7544939652475355"/>
<sample lastIntervalAvgValue="0.7484087729914563" lowerBound="0.7385472374512729" meanValue="0.7465206013494042" simulationTime="161441.3383818988" upperBound="0.7544939652475355"/>
<sample lastIntervalAvgValue="0.7449583611117644" lowerBound="0.7410310642295588" meanValue="0.7471951139971086" simulationTime="174394.58870580947" upperBound="0.7533591637646584"/>
</measure>
<measure alpha="0.98" analyzedSamples="491520" discardedSamples="0" finalValue="0.01502196751515807" name="Calibration_Class2_Number of Customers" nodeType="station" precision="0.01" referenceClass="Class2" referenceStation="Calibration" state="1" type="0">
<sample lastIntervalAvgValue="0.015451188703979256" lowerBound="0.0138424705098969" meanValue="0.016187964221642762" simulationTime="21766.73812642876" upperBound="0.018533457933388627"/>
<sample lastIntervalAvgValue="0.015316511373736548" lowerBound="0.014374715697260619" meanValue="0.015190946165135149" simulationTime="70348.82214008998" upperBound="0.016007176633009677"/>
<sample lastIntervalAvgValue="0.014810176107958328" lowerBound="0.014499838877632499" meanValue="0.015141505665220153" simulationTime="116227.31778632166" upperBound="0.015783172452807807"/>
<sample lastIntervalAvgValue="0.015015931438824447" lowerBound="0.014499838877632499" meanValue="0.015141505665220153" simulationTime="161897.14230721688" upperBound="0.015783172452807807"/>
<sample lastIntervalAvgValue="0.015097088641949937" lowerBound="0.014672164221681517" meanValue="0.015083679994612001" simulationTime="207688.88837590834" upperBound="0.015495195767542486"/>
<sample lastIntervalAvgValue="0.014829921937192552" lowerBound="0.014672164221681517" meanValue="0.015083679994612001" simulationTime="254149.67477199846" upperBound="0.015495195767542486"/>
<sample lastIntervalAvgValue="0.014911973968486553" lowerBound="0.014672164221681517" meanValue="0.015083679994612001" simulationTime="300536.84517320833" upperBound="0.015495195767542486"/>
<sample lastIntervalAvgValue="0.014699223664444459" lowerBound="0.014672164221681517" meanValue="0.015083679994612001" simulationTime="346691.52494638273" upperBound="0.015495195767542486"/>
<sample lastIntervalAvgValue="0.014988018919497652" lowerBound="0.014672164221681517" meanValue="0.015083679994612001" simulationTime="392753.7815057624" upperBound="0.015495195767542486"/>
<sample lastIntervalAvgValue="0.015390467280069639" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="439015.40235724894" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.014723468291279457" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="486023.41708038445" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.014990332429956269" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="532345.2338903961" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.01512892277644804" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="577743.0321701578" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.015375427409931423" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="622253.6586889254" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.015155014689754675" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="668163.390439792" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.014967893805991304" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="713612.4515839645" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.015093515945500144" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="758075.1986095438" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.015240038896880059" lowerBound="0.014692057017720115" meanValue="0.014950192945317558" simulationTime="803122.8063282591" upperBound="0.015208328872915"/>
<sample lastIntervalAvgValue="0.01494197253142771" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="846994.9182424243" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015316224307781281" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="892371.1869919545" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015287557414606176" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="937841.2147936824" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.014828449374704704" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="979320.4534554591" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015367428881752852" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1021517.3855445393" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015373844504018285" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1066479.3541446298" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015144042405280125" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1113069.7105294534" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015033483433153087" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1158935.8798971626" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.01488156398436712" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1205086.0006715988" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015054286820852658" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1250896.7860750651" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015051541315634832" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1296770.221482743" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.014784450606072117" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1343326.8851068765" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.014812454176986678" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1389252.9730239573" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015088702324276122" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1434795.9813835449" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.014886542332539013" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1480835.7958693986" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.014979218892753306" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1526224.9871218654" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.014506037996704546" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1569533.926212085" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.014851578281992977" lowerBound="0.01487607320311706" meanValue="0.015039710794825883" simulationTime="1611240.7532581263" upperBound="0.015203348386534707"/>
<sample lastIntervalAvgValue="0.015113421688025146" lowerBound="0.014903824682028551" meanValue="0.01502196751515807" simulationTime="1638481.7111367544" upperBound="0.015140110348287588"/>
<measure alpha="0.98" analyzedSamples="491520" discardedSamples="20" finalValue="0.4285284158768284" name="Busy2_Number of Customers" nodeType="station" precision="0.01" referenceClass="" referenceStation="Busy2" state="1" type="0">
<sample lastIntervalAvgValue="0.4327278274081417" lowerBound="0.4209685663151158" meanValue="0.43604958177996045" simulationTime="13876.695025167392" upperBound="0.4511305972448051"/>
<sample lastIntervalAvgValue="0.4277717437256055" lowerBound="0.4246046190172446" meanValue="0.4316330740668569" simulationTime="64255.194361328504" upperBound="0.4386615291164692"/>
<sample lastIntervalAvgValue="0.4275252965369865" lowerBound="0.42421446359628734" meanValue="0.428573485460139" simulationTime="112953.74188414749" upperBound="0.4329325073239907"/>
<sample lastIntervalAvgValue="0.4283866284569466" lowerBound="0.42421446359628734" meanValue="0.428573485460139" simulationTime="161441.69294713807" upperBound="0.4329325073239907"/>
<sample lastIntervalAvgValue="0.4302070978372558" lowerBound="0.42484998277284614" meanValue="0.4285284158768284" simulationTime="203719.94497095025" upperBound="0.43220684898081063"/>
</measure>
<measure alpha="0.98" analyzedSamples="327680" discardedSamples="280" finalValue="0.42790781788223825" name="Busy2_Class1_Number of Customers" nodeType="station" precision="0.01" referenceClass="Class1" referenceStation="Busy2" state="1" type="0">
<sample lastIntervalAvgValue="0.4270037257849655" lowerBound="0.419757623740597" meanValue="0.43104459763105024" simulationTime="21776.09828070597" upperBound="0.4423315715215035"/>
<sample lastIntervalAvgValue="0.4276599741209307" lowerBound="0.4223922092995258" meanValue="0.42701287609912386" simulationTime="70354.67479538477" upperBound="0.4316335428987219"/>
<sample lastIntervalAvgValue="0.4268697539498743" lowerBound="0.4223922092995258" meanValue="0.42701287609912386" simulationTime="116227.22182050864" upperBound="0.4316335428987219"/>
<sample lastIntervalAvgValue="0.4314156316385907" lowerBound="0.42440678200176163" meanValue="0.42790781788223825" simulationTime="135859.83926632564" upperBound="0.4314088537627149"/>
<measure alpha="0.98" analyzedSamples="327680" discardedSamples="160" finalValue="0.014924666640854697" name="Calibration_Number of Customers" nodeType="station" precision="0.01" referenceClass="" referenceStation="Calibration" state="1" type="0">
<sample lastIntervalAvgValue="0.014296267465728714" lowerBound="0.011322752016847876" meanValue="0.014850303903029771" simulationTime="13874.061196402345" upperBound="0.018377855789211667"/>
<sample lastIntervalAvgValue="0.014868345345791742" lowerBound="0.013988219806503858" meanValue="0.014827742149762239" simulationTime="64253.42721042049" upperBound="0.015667264493020618"/>
<sample lastIntervalAvgValue="0.014812215932949374" lowerBound="0.014092261369804996" meanValue="0.014674223347077174" simulationTime="112953.02447111536" upperBound="0.015256185324349353"/>
<sample lastIntervalAvgValue="0.014559361071869054" lowerBound="0.014247388150725647" meanValue="0.014709234534974254" simulationTime="161433.99304923858" upperBound="0.015171080919222861"/>
<sample lastIntervalAvgValue="0.014995041507434526" lowerBound="0.014247388150725647" meanValue="0.014709234534974254" simulationTime="208953.24224685304" upperBound="0.015171080919222861"/>
<sample lastIntervalAvgValue="0.014949846023837393" lowerBound="0.014247388150725647" meanValue="0.014709234534974254" simulationTime="257841.91701157822" upperBound="0.015171080919222861"/>
<sample lastIntervalAvgValue="0.015408671090531872" lowerBound="0.014497445222088935" meanValue="0.01488811143629382" simulationTime="307232.2999839692" upperBound="0.015278777650498704"/>
<sample lastIntervalAvgValue="0.014666101118067975" lowerBound="0.014497445222088935" meanValue="0.01488811143629382" simulationTime="356122.65243281063" upperBound="0.015278777650498704"/>
<sample lastIntervalAvgValue="0.014751113494851873" lowerBound="0.014497445222088935" meanValue="0.01488811143629382" simulationTime="404635.01388552965" upperBound="0.015278777650498704"/>
<sample lastIntervalAvgValue="0.014672454292437586" lowerBound="0.014497445222088935" meanValue="0.01488811143629382" simulationTime="453685.40696788987" upperBound="0.015278777650498704"/>
<sample lastIntervalAvgValue="0.015094578158137126" lowerBound="0.014497445222088935" meanValue="0.01488811143629382" simulationTime="502604.4424242108" upperBound="0.015278777650498704"/>
<sample lastIntervalAvgValue="0.0147073503392127" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="551597.2510570573" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.014849138821895225" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="600424.9280403093" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.015292616237036798" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="649308.6124621176" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.014377886778078027" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="698192.541974876" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.01497014247619875" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="746741.2640130178" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.014858699882670481" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="795533.0825674769" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.01517207994251526" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="844151.4035294583" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.014861073878907496" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="892762.1492607896" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.015266432294084805" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="941109.1109068348" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.014682845962729731" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="989071.5846569396" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.014978189055859124" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="1037509.0030904149" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.015254413177080007" lowerBound="0.014627249197317147" meanValue="0.014870847342668999" simulationTime="1086040.183054915" upperBound="0.01511444548802085"/>
<sample lastIntervalAvgValue="0.014605848518467818" lowerBound="0.014782350210118329" meanValue="0.014924666640854697" simulationTime="1096716.662202565" upperBound="0.015066983071591065"/>
</measure>
<measure alpha="0.99" analyzedSamples="409600" discardedSamples="0" finalValue="1.986564381173249" name="Service1_Class1_Response Time" nodeType="station" precision="0.03" referenceClass="Class1" referenceStation="Service1" state="1" type="2">
<sample lastIntervalAvgValue="2.0599179672889827" lowerBound="1.8264644916233692" meanValue="2.099179305259092" simulationTime="21775.473427065597" upperBound="2.371894118894815"/>
<sample lastIntervalAvgValue="1.96682860504446" lowerBound="1.9213379061986726" meanValue="2.006465003671471" simulationTime="70354.5805071057" upperBound="2.0915921011442693"/>
<sample lastIntervalAvgValue="2.031093718502449" lowerBound="1.9213379061986726" meanValue="2.006465003671471" simulationTime="116228.33156832606" upperBound="2.0915921011442693"/>
<sample lastIntervalAvgValue="1.9061317473170853" lowerBound="1.9199753971000892" meanValue="1.9869801546284203" simulationTime="161903.31510042533" upperBound="2.0539849121567513"/>
<sample lastIntervalAvgValue="1.9192841262686469" lowerBound="1.9199753971000892" meanValue="1.9869801546284203" simulationTime="207689.00729111172" upperBound="2.0539849121567513"/>
<sample lastIntervalAvgValue="2.042724611382815" lowerBound="1.9199753971000892" meanValue="1.9869801546284203" simulationTime="254151.00098901935" upperBound="2.0539849121567513"/>
<sample lastIntervalAvgValue="2.0996528378344155" lowerBound="1.9315234682839908" meanValue="1.986564381173249" simulationTime="272849.5832034668" upperBound="2.041605294062507"/>
<measure alpha="0.99" analyzedSamples="778240" discardedSamples="3005" finalValue="2.0114910663794854" name="Service1_Class1_Response Time" nodeType="station" precision="0.03" referenceClass="Class1" referenceStation="Service1" state="1" type="2">
<sample lastIntervalAvgValue="1.94831588313056" lowerBound="1.569602317070396" meanValue="1.8932003606330974" simulationTime="13876.28919854346" upperBound="2.2167984041957984"/>
<sample lastIntervalAvgValue="1.96702004144991" lowerBound="1.8378967552023229" meanValue="2.0265293538191256" simulationTime="64255.194361328504" upperBound="2.215161952435928"/>
<sample lastIntervalAvgValue="1.9583792326739768" lowerBound="1.8419491796060967" meanValue="1.9467177321899223" simulationTime="112954.31879089898" upperBound="2.051486284773748"/>
<sample lastIntervalAvgValue="1.9920863680624197" lowerBound="1.8815084714201606" meanValue="1.9586531713516644" simulationTime="161441.3383818988" upperBound="2.0357978712831684"/>
<sample lastIntervalAvgValue="2.08577509641053" lowerBound="1.8815084714201606" meanValue="1.9586531713516644" simulationTime="208959.31741758634" upperBound="2.0357978712831684"/>
<sample lastIntervalAvgValue="2.013680282601994" lowerBound="1.8815084714201606" meanValue="1.9586531713516644" simulationTime="257854.98823458815" upperBound="2.0357978712831684"/>
<sample lastIntervalAvgValue="1.9655282858960066" lowerBound="1.9488991331825811" meanValue="2.011806401261866" simulationTime="307242.539402015" upperBound="2.0747136693411505"/>
<sample lastIntervalAvgValue="2.0760998968280298" lowerBound="1.9488991331825811" meanValue="2.011806401261866" simulationTime="356127.94247851" upperBound="2.0747136693411505"/>
<sample lastIntervalAvgValue="2.033177821938796" lowerBound="1.9488991331825811" meanValue="2.011806401261866" simulationTime="404638.22271664144" upperBound="2.0747136693411505"/>
<sample lastIntervalAvgValue="1.999037798158856" lowerBound="1.9488991331825811" meanValue="2.011806401261866" simulationTime="453687.12732063007" upperBound="2.0747136693411505"/>
<sample lastIntervalAvgValue="1.9448319477916651" lowerBound="1.9488991331825811" meanValue="2.011806401261866" simulationTime="502604.22743246035" upperBound="2.0747136693411505"/>
<sample lastIntervalAvgValue="2.1072909204942096" lowerBound="1.9670740207786732" meanValue="2.0114910663794854" simulationTime="520010.72527265665" upperBound="2.0559081119802975"/>
</measure>
<measure alpha="0.99" analyzedSamples="163840" discardedSamples="0" finalValue="0.22788167369085163" name="Queue2_Response Time" nodeType="station" precision="0.03" referenceClass="" referenceStation="Queue2" state="1" type="2">
<sample lastIntervalAvgValue="0.2212951698650024" lowerBound="0.2027105687474914" meanValue="0.2242909119463804" simulationTime="21776.00795157667" upperBound="0.2458712551452694"/>
<sample lastIntervalAvgValue="0.2278950422330009" lowerBound="0.2153447485921806" meanValue="0.2245708961594881" simulationTime="70354.5805071057" upperBound="0.2337970437267956"/>
<sample lastIntervalAvgValue="0.22956698889225155" lowerBound="0.22151463053572565" meanValue="0.22788167369085163" simulationTime="109254.34303629368" upperBound="0.23424871684597762"/>
<measure alpha="0.99" analyzedSamples="51200" discardedSamples="20" finalValue="0.2857712799507223" name="Busy2_Response Time" nodeType="station" precision="0.03" referenceClass="" referenceStation="Busy2" state="1" type="2">
<sample lastIntervalAvgValue="0.28644908123102863" lowerBound="0.2722201556987353" meanValue="0.28601168477942707" simulationTime="13876.695025167392" upperBound="0.2998032138601188"/>
<sample lastIntervalAvgValue="0.28510476832868925" lowerBound="0.2816272949130171" meanValue="0.2857712799507223" simulationTime="33841.364358874554" upperBound="0.28991526498842757"/>
</measure>
<measure alpha="0.99" analyzedSamples="35840" discardedSamples="65" finalValue="0.28347770862779204" name="Busy2_Response Time" nodeType="station" precision="0.03" referenceClass="" referenceStation="Busy2" state="1" type="2">
<sample lastIntervalAvgValue="0.28436573286403344" lowerBound="0.2760999612224342" meanValue="0.2875318764129495" simulationTime="21776.09828070597" upperBound="0.29896379160346487"/>
<sample lastIntervalAvgValue="0.2821039263923575" lowerBound="0.2784439934828284" meanValue="0.28347770862779204" simulationTime="23986.594552011404" upperBound="0.2885114237727557"/>
<measure alpha="0.99" analyzedSamples="225280" discardedSamples="565" finalValue="0.23183614777687678" name="Queue2_Response Time" nodeType="station" precision="0.03" referenceClass="" referenceStation="Queue2" state="1" type="2">
<sample lastIntervalAvgValue="0.23921408959189303" lowerBound="0.19954877885417566" meanValue="0.2302254387533936" simulationTime="13876.695025167392" upperBound="0.26090209865261155"/>
<sample lastIntervalAvgValue="0.22855069519234839" lowerBound="0.21936484900427225" meanValue="0.23297066183042345" simulationTime="64255.194361328504" upperBound="0.24657647465657465"/>
<sample lastIntervalAvgValue="0.23258007884898674" lowerBound="0.22085652239964554" meanValue="0.23127995842533797" simulationTime="112953.74188414749" upperBound="0.2417033944510304"/>
<sample lastIntervalAvgValue="0.2332468297868342" lowerBound="0.22496715167829837" meanValue="0.23183614777687678" simulationTime="150286.67327611792" upperBound="0.2387051438754552"/>
</measure>
</results>
</archive>