Net creation #2
23
.vscode/launch.json
vendored
23
.vscode/launch.json
vendored
@@ -9,56 +9,49 @@
|
||||
"name": "Run1k Simple",
|
||||
"request": "launch",
|
||||
"mainClass": "net.berack.upo.valpre.Main",
|
||||
"args": "simulation -net example1.net -runs 1000 -p"
|
||||
"args": "simulation -net src/test/resources/example1.net -runs 1000 -p"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Run1k Complex",
|
||||
"request": "launch",
|
||||
"mainClass": "net.berack.upo.valpre.Main",
|
||||
"args": "simulation -net example2.net -runs 1000 -p"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Run1k Complex EXP",
|
||||
"request": "launch",
|
||||
"mainClass": "net.berack.upo.valpre.Main",
|
||||
"args": "simulation -net example3.net -runs 1000 -p"
|
||||
"args": "simulation -net src/test/resources/example2.net -runs 1000 -p"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Run Incremental",
|
||||
"request": "launch",
|
||||
"mainClass": "net.berack.upo.valpre.Main",
|
||||
"args": "simulation -net example3.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 -i \"[Service1:throughput=0.98:0.01],[Service2:utilization=0.98:0.01],[Service2:unavailable=0.98:0.01]\""
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Run10",
|
||||
"request": "launch",
|
||||
"mainClass": "net.berack.upo.valpre.Main",
|
||||
"args": "simulation -net example1.net -runs 10 -seed 2007539552"
|
||||
"args": "simulation -net src/test/resources/example1.net -runs 10 -seed 2007539552"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Plot Simple",
|
||||
"request": "launch",
|
||||
"mainClass": "net.berack.upo.valpre.Main",
|
||||
"args": "plot -csv example1.csv"
|
||||
"args": "plot -csv src/test/resources/example1.csv"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Plot Complex",
|
||||
"request": "launch",
|
||||
"mainClass": "net.berack.upo.valpre.Main",
|
||||
"args": "plot -csv example2.csv"
|
||||
"args": "plot -csv src/test/resources/example2.csv"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Build Net",
|
||||
"name": "Interactive Net Builder",
|
||||
"request": "launch",
|
||||
"mainClass": "net.berack.upo.valpre.Main",
|
||||
"args": "net"
|
||||
"args": "interactive"
|
||||
},
|
||||
]
|
||||
}
|
||||
25
README.md
25
README.md
@@ -16,7 +16,7 @@ Questa libreria è stata confrontata con il tool [JMT](https://jmt.sourceforge.n
|
||||
|
||||
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:
|
||||
|
||||
* `java -jar upo-valpre.jar net`\
|
||||
* `java -jar upo-valpre.jar interactive`\
|
||||
Usato per avviare una sessione interattiva per la creazione di una rete. Da usare se la rete è relativamente breve da descrivere, altrimenti è più comodo usare il codice della libreria per la generazione della rete.\
|
||||
Una volta scelta la rete è necessario salvarla in un file per la successiva simulazione e analisi.
|
||||
* `java -jar upo-valpre.jar simulation -net <file> [other]`\
|
||||
@@ -34,10 +34,6 @@ 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:\
|
||||

|
||||
|
||||
Esistono dei file prefatti per vedere eventuali simulazioni che, nel caso vengano passati come parametri, automaticamente vengono usati:
|
||||
* `example1.net`, `example2.net` e `example3.net` per `simulation -net`
|
||||
* `example1.csv`, `example2.csv` e `example3.csv` per `plot -csv`
|
||||
|
||||
---
|
||||
### Classi Interne
|
||||
|
||||
@@ -61,14 +57,13 @@ I percorsi che invece sono direttamente responsabili per la simulazione sono:
|
||||
---
|
||||
### Esempi
|
||||
|
||||
Nel jar sono presenti già 3 reti per fare degli esperimenti e/o testare se il tool funziona correttamente. Per tutti e tre gli esempi i comandi usati sono i seguenti, dove viene sostituito un numero al posto dell'asterisco:
|
||||
- `java -jar .\upo-valpre.jar simulation -net example*.net -runs 100` per fare una simulazione di 100 run e vedere i risultati aggregati.
|
||||
- `java -jar .\upo-valpre.jar plot -csv example*.csv` per mostrare un'aggregazione con più dettagli di una simulazione di 1000 run.
|
||||
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`
|
||||
|
||||
##### Primo esempio
|
||||
\
|
||||
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 con il comando precedente si vedranno i risultati sulla console in questo modo:
|
||||
Se si effettua una simulazione si vedranno i risultati sulla console in questo modo:
|
||||

|
||||
|
||||
Il tool JMT con la stessa rete produce i seguenti risultati che sono molto simili a quelli prodotti dalla libreria:\
|
||||
@@ -78,15 +73,10 @@ Queue Utilization = 0.7111 con un range [0.6959, 0.7262]
|
||||
|
||||
##### Secondo esempio
|
||||
\
|
||||
Il secondo è `example2`; è una rete composta da una fonte di clienti (Source) che arrivano con tasso esponenziale (λ=0.222 e quindi media 4.5), un centro di servizio (Queue) con tasso di servizio distribuito come una normale (μ=3.2, σ=0.6) e un altro centro di servizio (Queue Wait) con tasso di servizio distribuito come una normale (μ=3.2, σ=0.6) e con un tempo di indisponibilità che viene attivato con probabilità 20% e distribuito con una normale (μ=4.2, σ=0.6)\
|
||||
Se si effettua una simulazione con il comando precedente si vedranno i risultati sulla console in questo modo:
|
||||

|
||||
|
||||
##### Terzo esempio
|
||||
\
|
||||
Il terzo è `example3`; è uguale al secondo esempio ma nel quale cambiano i nomi dei nodi e le loro distribuzioni: è 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 con il comando precedente si vedranno i risultati sulla console in questo modo:
|
||||
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:
|
||||

|
||||
|
||||
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\
|
||||
@@ -95,4 +85,3 @@ Service1 Utilization ~ 0.7488\
|
||||
Calibration Number of Customers ~ 0.0150\
|
||||
Busy2 Number of Customers ~ 0.4279\
|
||||
Throughput ~ 1.5000
|
||||
|
||||
|
||||
24
pom.xml
24
pom.xml
@@ -13,30 +13,6 @@
|
||||
<maven.compiler.target>23</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Compilazione Java con Maven -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>23</source>
|
||||
<target>23</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Maven plugin per eseguire l'applicazione JavaFX -->
|
||||
<plugin>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-maven-plugin</artifactId>
|
||||
<version>0.0.8</version>
|
||||
<configuration>
|
||||
<mainClass>net.berack.upo.valpre.Main</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
||||
267
src/main/java/net/berack/upo/valpre/InteractiveConsole.java
Normal file
267
src/main/java/net/berack/upo/valpre/InteractiveConsole.java
Normal file
@@ -0,0 +1,267 @@
|
||||
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.sim.Net;
|
||||
import net.berack.upo.valpre.sim.ServerNode;
|
||||
|
||||
/**
|
||||
* Interactive net builder. This class allows the user to build a net by adding
|
||||
* nodes and connections. The user can also save the net to a file.
|
||||
*/
|
||||
public class InteractiveConsole {
|
||||
|
||||
private Net net = new Net();
|
||||
private final PrintStream out;
|
||||
private final Scanner scanner;
|
||||
|
||||
/**
|
||||
* Create a new interactive net builder. Uses System.in and System.out.
|
||||
*/
|
||||
public InteractiveConsole() {
|
||||
this(System.out, System.in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new interactive net builder.
|
||||
*
|
||||
* @param out the output stream
|
||||
* @param in the input stream
|
||||
*/
|
||||
public InteractiveConsole(PrintStream out, InputStream in) {
|
||||
this.out = out;
|
||||
this.scanner = new Scanner(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the interactive net builder.
|
||||
*/
|
||||
public Net run() {
|
||||
while (true) {
|
||||
try {
|
||||
var choice = choose(this.net + "\nChoose the next step to do:",
|
||||
"Add a node", "Add a connection", "Save the net", "Load net", "Clear", "Run", "Exit");
|
||||
switch (choice) {
|
||||
case 1 -> this.buildNode();
|
||||
case 2 -> this.buildConnection();
|
||||
case 3 -> this.net.save(ask("Enter the filename: "));
|
||||
case 4 -> this.loadNet();
|
||||
case 5 -> this.net = new Net();
|
||||
case 6 -> this.simpleRuns();
|
||||
default -> {
|
||||
this.scanner.close();
|
||||
return this.net;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a node as a source, terminal, queue, or queue with unavailable time.
|
||||
*/
|
||||
private void buildNode() {
|
||||
var choice = choose("Choose the type of node to create:", "Source", "Terminal", "Queue",
|
||||
"Queue with unavailable time");
|
||||
var name = ask("Node name: ");
|
||||
var distribution = askDistribution("Service distribution");
|
||||
|
||||
var node = switch (choice) {
|
||||
case 1 -> ServerNode.Builder.source(name, distribution);
|
||||
case 2 -> {
|
||||
var limit = ask("Arrivals limit (0 for Int.Max): ", Integer::parseInt);
|
||||
if (limit <= 0)
|
||||
limit = Integer.MAX_VALUE;
|
||||
yield ServerNode.Builder.terminal(name, limit, distribution);
|
||||
}
|
||||
case 3 -> {
|
||||
var servers = ask("Number of servers: ", Integer::parseInt);
|
||||
yield ServerNode.Builder.queue(name, servers, distribution, null);
|
||||
}
|
||||
case 4 -> {
|
||||
var servers = ask("Number of servers: ", Integer::parseInt);
|
||||
var unavailable = askDistribution("Unavailable distribution");
|
||||
yield ServerNode.Builder.queue(name, servers, distribution, unavailable);
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
|
||||
if (node != null)
|
||||
this.net.addNode(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a connection.
|
||||
*/
|
||||
private void buildConnection() {
|
||||
var source = ask("Enter the source node: ");
|
||||
var target = ask("Enter the target node: ");
|
||||
var weight = ask("Enter the weight: ", Double::parseDouble);
|
||||
var sourceNode = this.net.getNode(source);
|
||||
var targetNode = this.net.getNode(target);
|
||||
this.net.addConnection(sourceNode, targetNode, weight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a net from a file or from examples.
|
||||
*/
|
||||
private void loadNet() throws KryoException, IOException {
|
||||
var choice = choose("Choose the type of net to load:", "From file", "From examples");
|
||||
this.net = switch (choice) {
|
||||
case 1 -> Net.load(ask("Enter the filename: "));
|
||||
case 2 -> {
|
||||
var choice2 = choose("Choose the example to load:",
|
||||
"Example 1: Source -> Queue",
|
||||
"Example 2: Source -> Queue -> Queue");
|
||||
yield switch (choice2) {
|
||||
case 1 -> NetExamples.getNet1();
|
||||
case 2 -> NetExamples.getNet2();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
switch (choice) {
|
||||
case 1 -> new SimulationBuilder(net).setMaxRuns(100).setParallel(true).run();
|
||||
case 2 -> new SimulationBuilder(net).setMaxRuns(1000).setParallel(true).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();
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user for a distribution.
|
||||
*
|
||||
* @return the distribution
|
||||
*/
|
||||
private Distribution askDistribution(String ask) {
|
||||
var choice = choose(ask + ":", "Exponential", "Uniform", "Erlang",
|
||||
"UnavailableTime", "Normal", "NormalBoxMuller", "None");
|
||||
|
||||
return switch (choice) {
|
||||
case 1 -> {
|
||||
var lambda = ask("Lambda: ", Double::parseDouble);
|
||||
yield new Distribution.Exponential(lambda);
|
||||
}
|
||||
case 2 -> {
|
||||
var min = ask("Min: ", Double::parseDouble);
|
||||
var max = ask("Max: ", Double::parseDouble);
|
||||
yield new Distribution.Uniform(min, max);
|
||||
}
|
||||
case 3 -> {
|
||||
var k = ask("K: ", Integer::parseInt);
|
||||
var lambda = ask("Lambda: ", Double::parseDouble);
|
||||
yield new Distribution.Erlang(k, lambda);
|
||||
}
|
||||
case 4 -> {
|
||||
var probability = ask("Probability: ", Double::parseDouble);
|
||||
var unavailable = askDistribution("Unavailable distribution");
|
||||
yield new Distribution.UnavailableTime(probability, unavailable);
|
||||
}
|
||||
case 5 -> {
|
||||
var mean = ask("Mean: ", Double::parseDouble);
|
||||
var stdDev = ask("Standard deviation: ", Double::parseDouble);
|
||||
yield new Distribution.Normal(mean, stdDev);
|
||||
}
|
||||
case 6 -> {
|
||||
var mean = ask("Mean: ", Double::parseDouble);
|
||||
var stdDev = ask("Standard deviation: ", Double::parseDouble);
|
||||
yield new Distribution.NormalBoxMuller(mean, stdDev);
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user a question.
|
||||
*
|
||||
* @param ask the question to ask
|
||||
* @return the answer
|
||||
*/
|
||||
private String ask(String ask) {
|
||||
return ask(ask, Function.identity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user a question.
|
||||
*
|
||||
* @param ask the question to ask
|
||||
* @param parser the parser to use
|
||||
* @param defaultValue the default value
|
||||
* @return the answer
|
||||
*/
|
||||
private <T> T ask(String ask, Function<String, T> parser) {
|
||||
var totalRows = ask.chars().filter(ch -> ch == '\n').count();
|
||||
|
||||
var ask2 = "\033[" + totalRows + "A" + ask;
|
||||
var first = true;
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
this.out.print(first ? ask : ask2);
|
||||
var line = this.scanner.nextLine();
|
||||
first = false;
|
||||
|
||||
try {
|
||||
var value = parser.apply(line);
|
||||
return value;
|
||||
} catch (Exception e) {
|
||||
this.out.print("\033[A\033[K"); // clear the line
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null; // normally when the scanner is closed
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user to choose an option.
|
||||
*
|
||||
* @param ask the question to ask
|
||||
* @param options the options to choose from
|
||||
* @return the choice
|
||||
*/
|
||||
private int choose(String ask, String... options) {
|
||||
var builder = new StringBuilder();
|
||||
builder.append(ask).append("\n");
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
builder.append(i + 1).append(". ").append(options[i]).append("\n");
|
||||
}
|
||||
builder.append("> ");
|
||||
|
||||
var string = builder.toString();
|
||||
var choice = 0;
|
||||
choice = ask(string, val -> {
|
||||
var x = Integer.parseInt(val);
|
||||
if (x < 1 || x > options.length)
|
||||
throw new NumberFormatException(); // retry the question
|
||||
return x;
|
||||
});
|
||||
|
||||
return choice;
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,7 @@ public class Main {
|
||||
var plot = new Plot(csv);
|
||||
plot.show();
|
||||
}
|
||||
case "net" -> {
|
||||
var net = new NetBuilderInteractive();
|
||||
net.run();
|
||||
}
|
||||
case "interactive" -> new InteractiveConsole().run();
|
||||
default -> exit("Invalid program!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -86,11 +83,11 @@ public class Main {
|
||||
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|net] [args]");
|
||||
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("net args: none");
|
||||
System.out.println("interactive: no args needed");
|
||||
System.exit(1);
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
package net.berack.upo.valpre;
|
||||
|
||||
import java.util.function.Function;
|
||||
import net.berack.upo.valpre.rand.Distribution;
|
||||
import net.berack.upo.valpre.sim.Net;
|
||||
import net.berack.upo.valpre.sim.ServerNode;
|
||||
|
||||
public class NetBuilderInteractive {
|
||||
|
||||
private final Net net = new Net();
|
||||
|
||||
/**
|
||||
* Run the interactive net builder.
|
||||
*
|
||||
* @param args the arguments
|
||||
*/
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
var choice = choose("Choose the next step to do:",
|
||||
"Add a node", "Add a connection", "Print Nodes", "Save the net", "Exit");
|
||||
switch (choice) {
|
||||
case 1 -> {
|
||||
var node = this.buildNode();
|
||||
this.net.addNode(node);
|
||||
}
|
||||
case 2 -> {
|
||||
var source = ask("Enter the source node: ");
|
||||
var target = ask("Enter the target node: ");
|
||||
var weight = ask("Enter the weight: ", Double::parseDouble, 0.0);
|
||||
var sourceNode = this.net.getNode(source);
|
||||
var targetNode = this.net.getNode(target);
|
||||
this.net.addConnection(sourceNode, targetNode, weight);
|
||||
}
|
||||
case 3 -> this.printNodes();
|
||||
case 4 -> this.net.save(ask("Enter the filename: "));
|
||||
case 5 -> System.exit(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the nodes in the net.
|
||||
*/
|
||||
private void printNodes() {
|
||||
var builder = new StringBuilder();
|
||||
builder.append("Nodes:\n");
|
||||
for (var i = 0; i < this.net.size(); i++) {
|
||||
var name = this.net.getNode(i).name;
|
||||
builder.append(name).append(" -> ");
|
||||
|
||||
for (var connection : this.net.getChildren(i)) {
|
||||
var child = this.net.getNode(connection.index);
|
||||
builder.append(child.name).append("(").append(connection.weight).append("), ");
|
||||
}
|
||||
|
||||
builder.delete(builder.length() - 2, builder.length());
|
||||
builder.append("\n");
|
||||
}
|
||||
System.out.print(builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a node.
|
||||
*
|
||||
* @return the node
|
||||
*/
|
||||
private ServerNode buildNode() {
|
||||
var choice = choose("Choose the type of node to create:", "Source", "Queue");
|
||||
var name = ask("Node name: ");
|
||||
var distribution = askDistribution("Service distribution");
|
||||
|
||||
return switch (choice) {
|
||||
case 1 -> {
|
||||
var limit = ask("Arrivals limit (0 for Int.Max): ", Integer::parseInt, 1);
|
||||
if (limit <= 0)
|
||||
limit = Integer.MAX_VALUE;
|
||||
yield ServerNode.Builder.sourceLimited(name, limit, distribution);
|
||||
}
|
||||
case 2 -> {
|
||||
var servers = ask("Number of servers: ", Integer::parseInt, 1);
|
||||
var unavailable = askDistribution("Unavailable distribution");
|
||||
yield ServerNode.Builder.queue(name, servers, distribution, unavailable);
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user for a distribution.
|
||||
*
|
||||
* @return the distribution
|
||||
*/
|
||||
public static Distribution askDistribution(String ask) {
|
||||
var choice = choose(ask + ":", "Exponential", "Uniform", "Erlang",
|
||||
"UnavailableTime", "Normal", "NormalBoxMuller", "None");
|
||||
|
||||
return switch (choice) {
|
||||
case 1 -> {
|
||||
var lambda = ask("Lambda: ", Double::parseDouble, 1.0);
|
||||
yield new Distribution.Exponential(lambda);
|
||||
}
|
||||
case 2 -> {
|
||||
var min = ask("Min: ", Double::parseDouble, 0.0);
|
||||
var max = ask("Max: ", Double::parseDouble, 1.0);
|
||||
yield new Distribution.Uniform(min, max);
|
||||
}
|
||||
case 3 -> {
|
||||
var k = ask("K: ", Integer::parseInt, 1);
|
||||
var lambda = ask("Lambda: ", Double::parseDouble, 1.0);
|
||||
yield new Distribution.Erlang(k, lambda);
|
||||
}
|
||||
case 4 -> {
|
||||
var probability = ask("Probability: ", Double::parseDouble, 0.0);
|
||||
var unavailable = askDistribution("Unavailable distribution");
|
||||
yield new Distribution.UnavailableTime(probability, unavailable);
|
||||
}
|
||||
case 5 -> {
|
||||
var mean = ask("Mean: ", Double::parseDouble, 0.0);
|
||||
var stdDev = ask("Standard deviation: ", Double::parseDouble, 1.0);
|
||||
yield new Distribution.Normal(mean, stdDev);
|
||||
}
|
||||
case 6 -> {
|
||||
var mean = ask("Mean: ", Double::parseDouble, 0.0);
|
||||
var stdDev = ask("Standard deviation: ", Double::parseDouble, 1.0);
|
||||
yield new Distribution.NormalBoxMuller(mean, stdDev);
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user a question.
|
||||
*
|
||||
* @param ask the question to ask
|
||||
* @return the answer
|
||||
*/
|
||||
private static String ask(String ask) {
|
||||
return ask(ask, Function.identity(), "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user a question.
|
||||
*
|
||||
* @param ask the question to ask
|
||||
* @param parser the parser to use
|
||||
* @param defaultValue the default value
|
||||
* @return the answer
|
||||
*/
|
||||
private static <T> T ask(String ask, Function<String, T> parser, T defaultValue) {
|
||||
System.out.print(ask);
|
||||
try {
|
||||
var line = System.console().readLine();
|
||||
return parser.apply(line);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Invalid input: " + e.getMessage());
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the user to choose an option.
|
||||
*
|
||||
* @param ask the question to ask
|
||||
* @param options the options to choose from
|
||||
* @return the choice
|
||||
*/
|
||||
private static int choose(String ask, String... options) {
|
||||
var builder = new StringBuilder();
|
||||
builder.append(ask).append("\n");
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
builder.append(i + 1).append(". ").append(options[i]).append("\n");
|
||||
}
|
||||
builder.append("> ");
|
||||
|
||||
var string = builder.toString();
|
||||
var choice = 0;
|
||||
while (choice < 1 || choice > options.length)
|
||||
choice = ask(string, Integer::parseInt, 0);
|
||||
|
||||
return choice;
|
||||
}
|
||||
}
|
||||
94
src/main/java/net/berack/upo/valpre/NetExamples.java
Normal file
94
src/main/java/net/berack/upo/valpre/NetExamples.java
Normal file
@@ -0,0 +1,94 @@
|
||||
package net.berack.upo.valpre;
|
||||
|
||||
import net.berack.upo.valpre.rand.Distribution;
|
||||
import net.berack.upo.valpre.sim.Net;
|
||||
import net.berack.upo.valpre.sim.ServerNode;
|
||||
|
||||
/**
|
||||
* This class provides two example networks.
|
||||
* The first network is composed of a terminal node and a queue node.
|
||||
* The second network is composed of a terminal node and two queue nodes.
|
||||
*/
|
||||
public final class NetExamples {
|
||||
/**
|
||||
* 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 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.
|
||||
*
|
||||
* @param spawn the number of jobs to generate
|
||||
* @param source the distribution of the source node
|
||||
* @param queue the distribution of the queue node
|
||||
* @return the first example network
|
||||
*/
|
||||
public static Net getNet1(int spawn, Distribution source, Distribution queue) {
|
||||
var net1 = new Net();
|
||||
net1.addNode(ServerNode.Builder.terminal("Source", spawn, source));
|
||||
net1.addNode(ServerNode.Builder.queue("Queue", 1, queue));
|
||||
net1.addConnection(0, 1, 1.0);
|
||||
return net1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the second example network.
|
||||
* The net is composed of a terminal node and two queue nodes.
|
||||
* The terminal node generates 10000 jobs with an exponential distribution 1.5.
|
||||
* The first queue node has a capacity of 1 and a service time of 2.0.
|
||||
* The second queue node has a capacity of 1 and a service time of 3.5.
|
||||
* The second queue node has an unavailable time of 0.1 with an exponential
|
||||
* distribution of 10.0.
|
||||
* The terminal node is connected to the first queue node.
|
||||
* The first queue node is connected to the second queue node.
|
||||
*
|
||||
* @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 the second example network.
|
||||
* The net is composed of a terminal node and two queue nodes.
|
||||
* The terminal node is connected to the first queue node.
|
||||
* 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 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) {
|
||||
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.addConnection(0, 1, 1.0);
|
||||
net3.addConnection(1, 2, 1.0);
|
||||
return net3;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
package net.berack.upo.valpre;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
@@ -194,23 +191,4 @@ public class Parameters {
|
||||
throw new IllegalArgumentException("Invalid arguments");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file or the example file if it is present.
|
||||
*
|
||||
* @param file the file to get
|
||||
* @return the file or the example file
|
||||
* @throws FileNotFoundException if the file is not found
|
||||
*/
|
||||
public static InputStream getFileOrExample(String file) throws FileNotFoundException {
|
||||
if (file == null)
|
||||
return null;
|
||||
|
||||
if (file.startsWith("example")) {
|
||||
var resource = Parameters.class.getClassLoader().getResourceAsStream(file);
|
||||
if (resource != null)
|
||||
return resource;
|
||||
}
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,7 @@ public class Plot {
|
||||
* @throws IOException if anything happens while reading the file
|
||||
*/
|
||||
public Plot(String csv) throws IOException {
|
||||
var stream = Parameters.getFileOrExample(csv);
|
||||
if (stream == null)
|
||||
throw new IllegalArgumentException("CSV file needed!");
|
||||
var results = CsvResult.loadResults(stream);
|
||||
stream.close();
|
||||
|
||||
var results = new CsvResult(csv).loadResults();
|
||||
this.summary = new Result.Summary(results);
|
||||
|
||||
var nodes = this.summary.getNodes().toArray(new String[0]);
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.berack.upo.valpre;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import com.esotericsoftware.kryo.KryoException;
|
||||
|
||||
@@ -13,6 +14,7 @@ import net.berack.upo.valpre.sim.EndCriteria.MaxTime;
|
||||
import net.berack.upo.valpre.sim.Net;
|
||||
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 is responsible for running the simulation. It parses the arguments
|
||||
@@ -35,10 +37,8 @@ public class SimulationBuilder {
|
||||
*/
|
||||
public SimulationBuilder(String netFile) throws IOException {
|
||||
try {
|
||||
var file = Parameters.getFileOrExample(netFile);
|
||||
this.net = Net.load(file);
|
||||
this.net = Net.load(netFile);
|
||||
this.confidences = new ConfidenceIndices(this.net);
|
||||
file.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IllegalArgumentException("Net file needed!");
|
||||
} catch (KryoException e) {
|
||||
@@ -230,23 +230,38 @@ public class SimulationBuilder {
|
||||
* @throws ExecutionException If the simulation has an error.
|
||||
* @throws IOException If the CSV file has a problem.
|
||||
*/
|
||||
public void run() throws InterruptedException, ExecutionException, IOException {
|
||||
public Result.Summary run() throws InterruptedException, ExecutionException, IOException {
|
||||
return this.run(System.out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the simulation with the given parameters.
|
||||
* At the end it prints the results and saves them to a CSV file if requested.
|
||||
*
|
||||
* @param out the output stream to print the results
|
||||
* @throws InterruptedException If the simulation is interrupted.
|
||||
* @throws ExecutionException If the simulation has an error.
|
||||
* @throws IOException If the CSV file has a problem.
|
||||
*/
|
||||
public Result.Summary run(PrintStream out) throws InterruptedException, ExecutionException, IOException {
|
||||
var nano = System.nanoTime();
|
||||
var sim = new SimulationMultiple(this.net);
|
||||
var summary = switch (this.type) {
|
||||
case Incremental -> sim.runIncremental(this.seed, this.runs, this.confidences, this.endCriteria);
|
||||
case Incremental -> sim.runIncremental(this.seed, this.runs, out, this.confidences, this.endCriteria);
|
||||
case Parallel -> sim.runParallel(this.seed, this.runs, this.endCriteria);
|
||||
case Normal -> sim.run(this.seed, this.runs, this.endCriteria);
|
||||
};
|
||||
nano = System.nanoTime() - nano;
|
||||
|
||||
System.out.print(summary);
|
||||
System.out.println("Final time " + nano / 1e6 + "ms");
|
||||
out.print(summary);
|
||||
out.println("Final time " + nano / 1e6 + "ms");
|
||||
|
||||
if (csv != null) {
|
||||
new CsvResult(this.csv).saveResults(summary.getRuns());
|
||||
System.out.println("Data saved to " + this.csv);
|
||||
out.println("Data saved to " + this.csv);
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,36 @@ public interface Distribution {
|
||||
return sample;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the distribution.
|
||||
* In case the distribution is null, an empty string is returned.
|
||||
*
|
||||
* @param distribution The distribution to represent.
|
||||
* @return A string representation of the distribution.
|
||||
* @throws IllegalArgumentException if the field cannot be accessed
|
||||
* @throws IllegalAccessException if the field cannot be accessed
|
||||
*/
|
||||
public static String toString(Distribution distribution) throws IllegalArgumentException, IllegalAccessException {
|
||||
if (distribution == null)
|
||||
return "";
|
||||
|
||||
var builder = new StringBuilder();
|
||||
var dist = distribution.getClass();
|
||||
|
||||
builder.append(dist.getSimpleName()).append('(');
|
||||
for (var param : dist.getFields()) {
|
||||
var paramValue = param.get(distribution);
|
||||
var str = paramValue instanceof Distribution
|
||||
? toString((Distribution) paramValue)
|
||||
: paramValue;
|
||||
|
||||
builder.append(str).append(", ");
|
||||
}
|
||||
|
||||
builder.delete(builder.length() - 2, builder.length()).append(')');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an exponential distribution.
|
||||
*/
|
||||
|
||||
@@ -23,11 +23,7 @@ public class Event implements Comparable<Event> {
|
||||
|
||||
@Override
|
||||
public int compareTo(Event other) {
|
||||
if (this.time < other.time)
|
||||
return -1;
|
||||
if (this.time == other.time)
|
||||
return 0;
|
||||
return 1;
|
||||
return Double.compare(this.time, other.time);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,7 +75,6 @@ public final class Net implements Iterable<ServerNode> {
|
||||
* @param weight The probability of the child node.
|
||||
* @throws IndexOutOfBoundsException if one of the two nodes are not in the net
|
||||
* @throws IllegalArgumentException if the weight is negative or zero
|
||||
* @throws IllegalArgumentException if the child is a source node
|
||||
*/
|
||||
public void addConnection(int parent, int child, double weight) {
|
||||
if (weight <= 0)
|
||||
@@ -85,9 +84,6 @@ public final class Net implements Iterable<ServerNode> {
|
||||
if (parent < 0 || child < 0 || parent > max || child > max)
|
||||
throw new IndexOutOfBoundsException("One of the nodes does not exist");
|
||||
|
||||
if (this.servers.get(child).spawnArrivals > 0)
|
||||
throw new IllegalArgumentException("Can't connect to a source node");
|
||||
|
||||
var list = this.connections.get(parent);
|
||||
list.removeIf(conn -> conn.index == child);
|
||||
list.add(new Connection(child, weight));
|
||||
@@ -170,14 +166,13 @@ public final class Net implements Iterable<ServerNode> {
|
||||
for (var conn : list)
|
||||
sum += conn.weight;
|
||||
|
||||
var newOne = new Connection[list.size()];
|
||||
for (var i = 0; i < list.size(); i++) {
|
||||
var conn = list.get(i);
|
||||
var newOne = new ArrayList<Connection>();
|
||||
for (var conn : list) {
|
||||
var newWeight = conn.weight / sum;
|
||||
newOne[i] = new Connection(conn.index, newWeight);
|
||||
newOne.add(new Connection(conn.index, newWeight));
|
||||
}
|
||||
|
||||
this.connections.set(node, List.of(newOne));
|
||||
this.connections.set(node, newOne);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,6 +244,56 @@ public final class Net implements Iterable<ServerNode> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of the net passed as input.
|
||||
* The new net will have the same nodes and connections.
|
||||
*
|
||||
* @param net the net to copy
|
||||
* @return a new Net object
|
||||
*/
|
||||
public static Net copyOf(Net net) {
|
||||
var newNet = new Net();
|
||||
|
||||
for (var index = 0; index < net.size(); index++) {
|
||||
var node = net.servers.get(index);
|
||||
var conn = net.connections.get(index);
|
||||
conn = new ArrayList<>(conn);
|
||||
|
||||
newNet.indices.put(node, index);
|
||||
newNet.servers.add(node);
|
||||
newNet.connections.add(conn);
|
||||
}
|
||||
|
||||
return newNet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
var builder = new StringBuilder();
|
||||
try {
|
||||
for (var node : this.servers) {
|
||||
builder.append(node)
|
||||
.append(" -> ");
|
||||
|
||||
for (var child : this.getChildren(this.indices.get(node))) {
|
||||
var childNode = this.servers.get(child.index);
|
||||
builder.append(childNode.name)
|
||||
.append("(")
|
||||
.append(child.weight)
|
||||
.append("), ");
|
||||
}
|
||||
|
||||
builder.delete(builder.length() - 2, builder.length())
|
||||
.append("\n");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A Static inner class used to represent the connection of a node
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,7 @@ public class ServerNode {
|
||||
/**
|
||||
* Creates a generic node with the given name and distribution.
|
||||
* The servers number must be 1 or higher; if lower will be put to 1.
|
||||
* The spawn number must be 0 or higher; if lower will be put to 0.
|
||||
* The spawn number must be 0 or higher; if lower will be put to -1 (infinite).
|
||||
* The queue number must be equal or higher than the servers number; if lower
|
||||
* will be put to the servers number.
|
||||
* The service distribution can't be null, otherwise an exception is thrown.
|
||||
@@ -37,7 +37,7 @@ public class ServerNode {
|
||||
if (servers <= 0)
|
||||
servers = 1;
|
||||
if (spawn < 0)
|
||||
spawn = 0;
|
||||
spawn = -1;
|
||||
if (queue < servers)
|
||||
queue = servers;
|
||||
|
||||
@@ -71,6 +71,28 @@ public class ServerNode {
|
||||
return Distribution.getPositiveSample(this.unavailable, rng);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
var build = new StringBuilder()
|
||||
.append(this.name)
|
||||
.append("[servers:")
|
||||
.append(this.maxServers)
|
||||
.append(", queue:")
|
||||
.append(this.maxQueue)
|
||||
.append(", spawn:")
|
||||
.append(this.spawnArrivals)
|
||||
.append(", ")
|
||||
.append(Distribution.toString(this.service));
|
||||
if (this.unavailable != null)
|
||||
build.append(", u:").append(Distribution.toString(this.unavailable));
|
||||
return build.append(']').toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ServerNode))
|
||||
@@ -183,26 +205,27 @@ public class ServerNode {
|
||||
|
||||
/**
|
||||
* Creates a source node with the given name and distribution.
|
||||
* It swpawns infinite arrivals (Integer.MAX_VALUE).
|
||||
* It swpawns infinite arrivals (-1).
|
||||
*
|
||||
* @param name The name of the node.
|
||||
* @param distribution The distribution of the inter-arrival times.
|
||||
* @return The created source node.
|
||||
*/
|
||||
public static ServerNode source(String name, Distribution distribution) {
|
||||
return new Builder(name, distribution).spawn(Integer.MAX_VALUE).build();
|
||||
return new Builder(name, distribution).spawn(-1).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a source node with the given name, distribution, and number of
|
||||
* Creates a terminal node with the given name, distribution, and number of
|
||||
* arrivals to spawn.
|
||||
* Once it has finished spawning the arrivals, it will not spawn anymore.
|
||||
*
|
||||
* @param name The name of the node.
|
||||
* @param service The distribution of the inter-arrival times.
|
||||
* @param spawnArrivals The number of arrivals to spawn.
|
||||
* @return The created source node.
|
||||
*/
|
||||
public static ServerNode sourceLimited(String name, int spawnArrivals, Distribution service) {
|
||||
public static ServerNode terminal(String name, int spawnArrivals, Distribution service) {
|
||||
return new Builder(name, service).spawn(spawnArrivals).build();
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ public class ServerNodeState {
|
||||
* @return True if the node should spawn an arrival, false otherwise.
|
||||
*/
|
||||
public boolean shouldSpawnArrival() {
|
||||
return this.node.spawnArrivals > this.stats.numArrivals;
|
||||
return this.node.spawnArrivals < 0 || this.node.spawnArrivals > this.stats.numArrivals;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,6 +158,23 @@ public class ServerNodeState {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random child based on the weights of the children and the random number
|
||||
* generator passed as input
|
||||
*
|
||||
* @param rng the random number generator
|
||||
* @return the index of the child or -1 if no child is selected
|
||||
*/
|
||||
public int getRandomChild(Rng rng) {
|
||||
var random = rng.random();
|
||||
for (var child : this.children) {
|
||||
random -= child.weight;
|
||||
if (random <= 0)
|
||||
return child.index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an arrival event to a child node based on the node and the time passed
|
||||
* as input
|
||||
@@ -168,12 +185,7 @@ public class ServerNodeState {
|
||||
* otherwise
|
||||
*/
|
||||
public Event spawnArrivalToChild(double time, Rng rng) {
|
||||
var random = rng.random();
|
||||
for (var child : this.children) {
|
||||
random -= child.weight;
|
||||
if (random <= 0)
|
||||
return Event.newArrival(child.index, time);
|
||||
}
|
||||
return null;
|
||||
var child = this.getRandomChild(rng);
|
||||
return child > -1 ? Event.newArrival(child, time) : null;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.berack.upo.valpre.sim;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
@@ -98,8 +97,13 @@ public final class Simulation {
|
||||
case DEPARTURE -> {
|
||||
state.updateDeparture(time);
|
||||
|
||||
// Spawn unavailability if has unavailable time
|
||||
this.addToFel(state.spawnUnavailableIfPossible(time, this.rng));
|
||||
|
||||
// Spawn departure if has requests and server is available
|
||||
this.addToFel(state.spawnDepartureIfPossible(time, this.rng));
|
||||
|
||||
// Spawn arrival to self if is source node
|
||||
this.addToFel(state.spawnArrivalIfPossilbe(time));
|
||||
|
||||
// Spawn arrival to child node if queue is not full otherwise drop
|
||||
@@ -151,7 +155,7 @@ public final class Simulation {
|
||||
* @return a list of future events.
|
||||
*/
|
||||
public List<Event> getFutureEventList() {
|
||||
return new ArrayList<>(this.fel);
|
||||
return List.copyOf(this.fel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.berack.upo.valpre.sim;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -99,16 +100,21 @@ public class SimulationMultiple {
|
||||
* Run the simulation multiple times with the given seed and end criteria. The
|
||||
* simulation runs will stop when the relative error of the confidence index is
|
||||
* less than the given value.
|
||||
* The results are printed on the console.
|
||||
* The results are printed on the PrintStream.
|
||||
*
|
||||
* @param seed The seed to use for the random number generator.
|
||||
* @param criterias The criteria to determine when to end the simulation. If
|
||||
* null then the simulation will run until there are no more
|
||||
* events.
|
||||
* @param seed The seed to use for the random number generator.
|
||||
* @param runs The maximum number of runs to perform.
|
||||
* @param stream The PrintStream to print the results.
|
||||
* @param confidences The confidence indices to use to determine when to stop
|
||||
* the simulation.
|
||||
* @param criterias The criteria to determine when to end the simulation. If
|
||||
* null then the simulation will run until there are no more
|
||||
* events.
|
||||
* @return The statistics the network.
|
||||
* @throws IllegalArgumentException If the confidence is not set.
|
||||
*/
|
||||
public Result.Summary runIncremental(long seed, int runs, ConfidenceIndices confidences, EndCriteria... criterias) {
|
||||
public Result.Summary runIncremental(long seed, int runs, PrintStream stream, ConfidenceIndices confidences,
|
||||
EndCriteria... criterias) {
|
||||
if (confidences == null)
|
||||
throw new IllegalArgumentException("Confidence must be not null");
|
||||
|
||||
@@ -133,11 +139,11 @@ public class SimulationMultiple {
|
||||
var oneSting = String.join("], [", errString);
|
||||
|
||||
output.append('[').append(oneSting).append("]");
|
||||
System.out.print(output);
|
||||
stream.print(output);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(); // remove last printed line
|
||||
stream.println(); // remove last printed line
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
187
src/test/java/net/berack/upo/valpre/sim/TestInteractions.java
Normal file
187
src/test/java/net/berack/upo/valpre/sim/TestInteractions.java
Normal file
@@ -0,0 +1,187 @@
|
||||
package net.berack.upo.valpre.sim;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import net.berack.upo.valpre.InteractiveConsole;
|
||||
import net.berack.upo.valpre.rand.Distribution;
|
||||
|
||||
public class TestInteractions {
|
||||
|
||||
@Test
|
||||
public void distributionToString() throws Exception {
|
||||
var exp = new Distribution.Exponential(1.0);
|
||||
assertEquals("Exponential(1.0)", Distribution.toString(exp));
|
||||
|
||||
var uniform = new Distribution.Uniform(0.0, 1.0);
|
||||
assertEquals("Uniform(0.0, 1.0)", Distribution.toString(uniform));
|
||||
|
||||
var erlang = new Distribution.Erlang(2, 1.0);
|
||||
assertEquals("Erlang(2, 1.0)", Distribution.toString(erlang));
|
||||
|
||||
var normal = new Distribution.Normal(3.2, 0.6);
|
||||
assertEquals("Normal(3.2, 0.6)", Distribution.toString(normal));
|
||||
|
||||
var normalBoxMuller = new Distribution.NormalBoxMuller(3.2, 0.6);
|
||||
assertEquals("NormalBoxMuller(3.2, 0.6)", Distribution.toString(normalBoxMuller));
|
||||
|
||||
var unavailable = new Distribution.UnavailableTime(0.1, exp);
|
||||
assertEquals("UnavailableTime(0.1, Exponential(1.0))", Distribution.toString(unavailable));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nodeToString() {
|
||||
var exp = new Distribution.Exponential(1.0);
|
||||
var normal = new Distribution.Normal(3.2, 0.6);
|
||||
var unavailable = new Distribution.UnavailableTime(0.1, exp);
|
||||
|
||||
var node = new ServerNode.Builder("Source", exp).build();
|
||||
assertEquals("Source[servers:1, queue:100, spawn:0, Exponential(1.0)]", node.toString());
|
||||
|
||||
node = new ServerNode.Builder("Queue", normal).build();
|
||||
assertEquals("Queue[servers:1, queue:100, spawn:0, Normal(3.2, 0.6)]", node.toString());
|
||||
|
||||
node = new ServerNode.Builder("Queue", normal).queue(10).servers(5).spawn(100).build();
|
||||
assertEquals("Queue[servers:5, queue:10, spawn:100, Normal(3.2, 0.6)]", node.toString());
|
||||
|
||||
node = new ServerNode.Builder("Queue", normal).queue(10).servers(5).spawn(100).unavailable(unavailable).build();
|
||||
assertEquals(
|
||||
"Queue[servers:5, queue:10, spawn:100, Normal(3.2, 0.6), u:UnavailableTime(0.1, Exponential(1.0))]",
|
||||
node.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void netToString() {
|
||||
var net = new Net();
|
||||
assertEquals("", net.toString());
|
||||
|
||||
var node1 = new ServerNode.Builder("Source", new Distribution.Exponential(1)).build();
|
||||
net.addNode(node1);
|
||||
assertEquals(node1 + " -\n", net.toString());
|
||||
|
||||
var node2 = new ServerNode.Builder("Server", new Distribution.Normal(3.2, 0.6)).build();
|
||||
net.addNode(node2);
|
||||
assertEquals(node1 + " -\n" + node2 + " -\n", net.toString());
|
||||
|
||||
net.addConnection(0, 1, 1.0);
|
||||
assertEquals(node1 + " -> Server(1.0)\n" + node2 + " -\n", net.toString());
|
||||
|
||||
var node3 = new ServerNode.Builder("Server2", new Distribution.Normal(4.1, 0.1)).build();
|
||||
net.addNode(node3);
|
||||
assertEquals(node1 + " -> Server(1.0)\n" + node2 + " -\n" + node3 + " -\n", net.toString());
|
||||
|
||||
net.addConnection(0, 2, 1.0);
|
||||
net.normalizeWeights();
|
||||
assertEquals(node1 + " -> Server(0.5), Server2(0.5)\n" + node2 + " -\n" + node3 + " -\n", net.toString());
|
||||
|
||||
net.addConnection(1, 2, 1.0);
|
||||
assertEquals(node1 + " -> Server(0.5), Server2(0.5)\n"
|
||||
+ node2 + " -> Server2(1.0)\n"
|
||||
+ node3 + " -\n",
|
||||
net.toString());
|
||||
|
||||
var const0 = new Distribution.Uniform(0, 0);
|
||||
var unavailable = new Distribution.UnavailableTime(0.1, new Distribution.Exponential(1));
|
||||
var other = ServerNode.Builder.queue("Other", 1, const0, unavailable);
|
||||
net.addNode(other);
|
||||
assertEquals(node1 + " -> Server(0.5), Server2(0.5)\n"
|
||||
+ node2 + " -> Server2(1.0)\n"
|
||||
+ node3 + " -\n"
|
||||
+ other + " -\n",
|
||||
net.toString());
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void netBuilderInteractive() {
|
||||
|
||||
// Test the interactive console EXIT
|
||||
var net = runInteraction("7");
|
||||
assertEquals("", net.toString());
|
||||
|
||||
// Test the interactive console ADD NODE
|
||||
net = runInteraction("1", "1", "Source", "1", "1.0", "7");
|
||||
assertEquals("Source[servers:1, queue:100, spawn:-1, Exponential(1.0)] -\n", net.toString());
|
||||
|
||||
// Test the interactive console ADD SECOND NODE
|
||||
net = runInteraction("1", "2", "Terminal", "1", "2.0", "500",
|
||||
"1", "3", "Queue", "5", "3.2", "0.6", "1",
|
||||
"7");
|
||||
assertEquals("Terminal[servers:1, queue:100, spawn:500, Exponential(2.0)] -\n"
|
||||
+ "Queue[servers:1, queue:100, spawn:0, Normal(3.2, 0.6)] -\n", net.toString());
|
||||
|
||||
// Test the interactive console ADD CONNECTION
|
||||
net = runInteraction("1", "1", "Source", "1", "2.0",
|
||||
"1", "3", "Queue", "5", "3.2", "0.6", "1",
|
||||
"2", "Source", "Queue", "1.0",
|
||||
"7");
|
||||
assertEquals("Source[servers:1, queue:100, spawn:-1, Exponential(2.0)] -> Queue(1.0)\n"
|
||||
+ "Queue[servers:1, queue:100, spawn:0, Normal(3.2, 0.6)] -\n", net.toString());
|
||||
|
||||
// Test the interactive console CLEAR
|
||||
net = runInteraction("1", "1", "Source", "1", "2.0",
|
||||
"1", "3", "Queue", "5", "3.2", "0.6", "1",
|
||||
"2", "Source", "Queue", "1.0",
|
||||
"2", "Queue", "Queue", "1.0",
|
||||
"5", "7");
|
||||
assertEquals("", net.toString());
|
||||
|
||||
// Test the interactive console LOAD
|
||||
net = runInteraction("4", "1", "src/test/resources/example1.net", "7");
|
||||
assertEquals("Source[servers:1, queue:100, spawn:10000, Exponential(0.2222222222222222)] -> Queue(1.0)\n"
|
||||
+ "Queue[servers:1, queue:100, spawn:0, NormalBoxMuller(3.2, 0.6)] -\n",
|
||||
net.toString());
|
||||
|
||||
// Test the interactive console LOAD EXAMPLE 1
|
||||
net = runInteraction("4", "2", "1", "7");
|
||||
assertEquals("Source[servers:1, queue:100, spawn:10000, Exponential(0.2222222222222222)] -> Queue(1.0)\n"
|
||||
+ "Queue[servers:1, queue:100, spawn:0, NormalBoxMuller(3.2, 0.6)] -\n",
|
||||
net.toString());
|
||||
|
||||
// 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"
|
||||
+ "Service2[servers:1, queue:100, spawn:0, Exponential(3.5), u:UnavailableTime(0.1, Exponential(10.0))] -\n",
|
||||
net.toString());
|
||||
}
|
||||
|
||||
private static Net runInteraction(String... commands) {
|
||||
var out = new PrintStream(OutputStream.nullOutputStream());
|
||||
var inputs = String.join("\n", commands);
|
||||
var bytes = inputs.getBytes();
|
||||
var in = new ByteArrayInputStream(bytes);
|
||||
return new InteractiveConsole(out, in).run();
|
||||
}
|
||||
|
||||
/*
|
||||
* An interaction example is like this:
|
||||
* 1. Add a node
|
||||
* - Choose the type of node to create:
|
||||
* - 1. Source
|
||||
* - 2. Queue
|
||||
* - 3. Queue with unavailable time
|
||||
* - Node name: Name
|
||||
* - Arrivals limit (0 for Int.Max) / Number of servers: 1
|
||||
* - Choose the type of service distribution:
|
||||
* - - 1. Exponential
|
||||
* - - 2. Uniform
|
||||
* - - 3. Erlang
|
||||
* - - 4. UnavailableTime
|
||||
* - - 5. Normal
|
||||
* - - 6. NormalBoxMuller
|
||||
* - - 7. None
|
||||
* 2. Add a connection
|
||||
* - Enter the source node: Source
|
||||
* - Enter the target node: Queue
|
||||
* - Enter the weight: 1.0
|
||||
* 3. Save the net
|
||||
* 4. Load net
|
||||
* 5. Clear
|
||||
* 6. Exit
|
||||
*/
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashSet;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
@@ -11,61 +13,26 @@ import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
import com.esotericsoftware.kryo.KryoException;
|
||||
|
||||
import net.berack.upo.valpre.NetExamples;
|
||||
import net.berack.upo.valpre.SimulationBuilder;
|
||||
import net.berack.upo.valpre.rand.Distribution;
|
||||
import net.berack.upo.valpre.rand.Rng;
|
||||
import net.berack.upo.valpre.sim.stats.CsvResult;
|
||||
import net.berack.upo.valpre.sim.stats.NodeStats;
|
||||
|
||||
public class TestSaveExamplesNet {
|
||||
|
||||
private static final Distribution exp0_22 = new Distribution.Exponential(1.0 / 4.5);
|
||||
private static final Distribution exp2 = new Distribution.Exponential(2.0);
|
||||
private static final Distribution exp1_5 = new Distribution.Exponential(1.5);
|
||||
private static final Distribution exp3_5 = new Distribution.Exponential(3.5);
|
||||
private static final Distribution exp10 = new Distribution.Exponential(10.0);
|
||||
|
||||
private static final Distribution norm3_2 = new Distribution.NormalBoxMuller(3.2, 0.6);
|
||||
private static final Distribution norm4_2 = new Distribution.NormalBoxMuller(4.2, 0.6);
|
||||
|
||||
private static final Distribution unNorm = new Distribution.UnavailableTime(0.2, norm4_2);
|
||||
private static final Distribution unExp = new Distribution.UnavailableTime(0.1, exp10);
|
||||
|
||||
private static final int spawn = 10000;
|
||||
private static final String path = "src/main/resources/example%d.%s";
|
||||
private static final String path = "src/test/resources/example%d.%s";
|
||||
private static final String netFile1 = path.formatted(1, "net");
|
||||
private static final String netFile2 = path.formatted(2, "net");
|
||||
private static final String netFile3 = path.formatted(3, "net");
|
||||
private static final String csv1 = path.formatted(1, "csv");
|
||||
private static final String csv2 = path.formatted(2, "csv");
|
||||
private static final String csv3 = path.formatted(3, "csv");
|
||||
|
||||
private static final Net net1 = new Net();
|
||||
private static final Net net2 = new Net();
|
||||
private static final Net net3 = new Net();
|
||||
static {
|
||||
net1.addNode(ServerNode.Builder.sourceLimited("Source", spawn, exp0_22));
|
||||
net1.addNode(ServerNode.Builder.queue("Queue", 1, norm3_2));
|
||||
net1.addConnection(0, 1, 1.0);
|
||||
|
||||
net2.addNode(ServerNode.Builder.sourceLimited("Source", spawn, exp0_22));
|
||||
net2.addNode(ServerNode.Builder.queue("Queue", 1, norm3_2));
|
||||
net2.addNode(ServerNode.Builder.queue("Queue Wait", 1, norm3_2, unNorm));
|
||||
net2.addConnection(0, 1, 1.0);
|
||||
net2.addConnection(1, 2, 1.0);
|
||||
|
||||
net3.addNode(ServerNode.Builder.sourceLimited("Source", spawn, exp1_5));
|
||||
net3.addNode(ServerNode.Builder.queue("Service1", 1, exp2));
|
||||
net3.addNode(ServerNode.Builder.queue("Service2", 1, exp3_5, unExp));
|
||||
net3.addConnection(0, 1, 1.0);
|
||||
net3.addConnection(1, 2, 1.0);
|
||||
}
|
||||
private static final Net net1 = NetExamples.getNet1();
|
||||
private static final Net net2 = NetExamples.getNet2();
|
||||
|
||||
@BeforeAll
|
||||
public void saveAll() throws IOException {
|
||||
net1.save(netFile1);
|
||||
net2.save(netFile2);
|
||||
net3.save(netFile3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,20 +52,6 @@ public class TestSaveExamplesNet {
|
||||
public void loadExample2() throws KryoException, IOException {
|
||||
var sim = new Simulation(Net.load(netFile2), new Rng());
|
||||
var res = sim.run();
|
||||
var time = 45417.0;
|
||||
var maxErr = time / 1000.0;
|
||||
|
||||
assertEquals(Rng.DEFAULT, res.seed);
|
||||
assertEquals(time, res.simulationTime, maxErr);
|
||||
testNode(res.getStat("Source"), 10000, time, 1.0, 4.5, 0.0, 0.0);
|
||||
testNode(res.getStat("Queue"), 10000, time, 2.6, 7.2, 4.0, 0.0);
|
||||
testNode(res.getStat("Queue Wait"), 10000, time, 5.8, 22.3, 19.1, 8497.7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadExample3() throws KryoException, IOException {
|
||||
var sim = new Simulation(Net.load(netFile3), new Rng());
|
||||
var res = sim.run();
|
||||
var time = 6736.0;
|
||||
var maxErr = time / 1000.0;
|
||||
|
||||
@@ -153,33 +106,26 @@ public class TestSaveExamplesNet {
|
||||
@Test
|
||||
@AfterAll
|
||||
public void multiSimulation1() throws Exception {
|
||||
new SimulationBuilder(net1)
|
||||
.setCsv(csv1)
|
||||
.setMaxRuns(1000)
|
||||
.setSeed(2007539552L)
|
||||
.setParallel(true)
|
||||
.run();
|
||||
try (var newOut = new PrintStream(OutputStream.nullOutputStream())) {
|
||||
new SimulationBuilder(net1)
|
||||
.setCsv(csv1)
|
||||
.setMaxRuns(1000)
|
||||
.setSeed(2007539552L)
|
||||
.setParallel(true)
|
||||
.run(newOut);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@AfterAll
|
||||
public void multiSimulation2() throws Exception {
|
||||
new SimulationBuilder(net2)
|
||||
.setCsv(csv2)
|
||||
.setMaxRuns(1000)
|
||||
.setSeed(2007539552L)
|
||||
.setParallel(true)
|
||||
.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
@AfterAll
|
||||
public void multiSimulation3() throws Exception {
|
||||
new SimulationBuilder(net3)
|
||||
.setCsv(csv3)
|
||||
.setMaxRuns(1000)
|
||||
.setSeed(2007539552L)
|
||||
.setParallel(true)
|
||||
.run();
|
||||
try (var newOut = new PrintStream(OutputStream.nullOutputStream())) {
|
||||
new SimulationBuilder(net2)
|
||||
.setCsv(csv2)
|
||||
.setMaxRuns(1000)
|
||||
.setSeed(2007539552L)
|
||||
.setParallel(true)
|
||||
.run(newOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
@@ -23,7 +24,7 @@ public class TestSimulation {
|
||||
private static final ServerNode node0;
|
||||
private static final ServerNode node1;
|
||||
static {
|
||||
node0 = ServerNode.Builder.sourceLimited("First", 0, const1);
|
||||
node0 = ServerNode.Builder.terminal("First", 0, const1);
|
||||
node1 = ServerNode.Builder.queue("Second", 1, const1);
|
||||
|
||||
simpleNet = new Net();
|
||||
@@ -56,10 +57,10 @@ public class TestSimulation {
|
||||
node = ServerNode.Builder.source("Source", const1);
|
||||
assertEquals("Source", node.name);
|
||||
assertEquals(1, node.maxServers);
|
||||
assertEquals(Integer.MAX_VALUE, node.spawnArrivals);
|
||||
assertEquals(-1, node.spawnArrivals);
|
||||
assertEquals(1.0, node.getServiceTime(null), DELTA);
|
||||
|
||||
node = ServerNode.Builder.sourceLimited("Source", 50, const1);
|
||||
node = ServerNode.Builder.terminal("Source", 50, const1);
|
||||
assertEquals("Source", node.name);
|
||||
assertEquals(1, node.maxServers);
|
||||
assertEquals(50, node.spawnArrivals);
|
||||
@@ -196,7 +197,7 @@ public class TestSimulation {
|
||||
@Test
|
||||
public void nodeStatsUpdates() {
|
||||
var net = new Net();
|
||||
net.addNode(ServerNode.Builder.sourceLimited("Source", 50, const1));
|
||||
net.addNode(ServerNode.Builder.terminal("Source", 50, const1));
|
||||
net.addNode(node1);
|
||||
net.addConnection(0, 1, 1.0);
|
||||
|
||||
@@ -393,13 +394,23 @@ public class TestSimulation {
|
||||
|
||||
@Test
|
||||
public void simulation() {
|
||||
var start = System.nanoTime();
|
||||
assertThrows(NullPointerException.class, () -> new Simulation(null, rigged));
|
||||
assertThrows(NullPointerException.class, () -> new Simulation(simpleNet, null));
|
||||
|
||||
var sim = new Simulation(simpleNet, rigged);
|
||||
assertTrue(sim.hasEnded());
|
||||
assertEquals(0, sim.getEventsProcessed());
|
||||
assertEquals(0.0, sim.getTime(), DELTA);
|
||||
var fel = sim.getFutureEventList();
|
||||
assertEquals(0, fel.size());
|
||||
|
||||
var start = System.nanoTime();
|
||||
sim = new Simulation(simpleNet, rigged);
|
||||
// knowing that it takes time to allocate the object
|
||||
// we can use the average time
|
||||
var endAllocation = System.nanoTime();
|
||||
var time = (endAllocation + start) / 2;
|
||||
var diff = 0.5e-6 * (endAllocation - start); // getting the error margin in ms
|
||||
var diff = 1e-6 * (endAllocation - start); // getting the error margin in ms
|
||||
|
||||
assertTrue(sim.hasEnded());
|
||||
assertEquals(0, sim.getEventsProcessed());
|
||||
@@ -410,7 +421,7 @@ public class TestSimulation {
|
||||
assertEquals(0, sim.getNodeState(node0.name).numServerUnavailable);
|
||||
assertEquals(0, sim.getNodeState(node1.name).numServerBusy);
|
||||
assertEquals(0, sim.getNodeState(node1.name).numServerUnavailable);
|
||||
var fel = sim.getFutureEventList();
|
||||
fel = sim.getFutureEventList();
|
||||
assertEquals(0, fel.size());
|
||||
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
@@ -489,6 +500,8 @@ public class TestSimulation {
|
||||
assertEquals(0, sim.getNodeState(node1.name).numServerUnavailable);
|
||||
fel = sim.getFutureEventList();
|
||||
assertEquals(0, fel.size());
|
||||
final var s = sim;
|
||||
assertThrows(NullPointerException.class, () -> s.processNextEvent());
|
||||
|
||||
var elapsed = (double) (System.nanoTime() - time);
|
||||
var result = sim.endSimulation();
|
||||
@@ -529,7 +542,7 @@ public class TestSimulation {
|
||||
@Test
|
||||
public void simulationStats() {
|
||||
var net = new Net();
|
||||
net.addNode(ServerNode.Builder.sourceLimited("Source", 50, const1));
|
||||
net.addNode(ServerNode.Builder.terminal("Source", 50, const1));
|
||||
|
||||
var sim = new Simulation(net, rigged);
|
||||
var result = sim.run();
|
||||
@@ -581,7 +594,7 @@ public class TestSimulation {
|
||||
@Test
|
||||
public void simulationDrop() {
|
||||
var net = new Net();
|
||||
net.addNode(ServerNode.Builder.sourceLimited("Source", 50, const1));
|
||||
net.addNode(ServerNode.Builder.terminal("Source", 50, const1));
|
||||
net.addNode(new ServerNode.Builder("Queue", _ -> 2.0).queue(20).build());
|
||||
net.addConnection(0, 1, 1.0);
|
||||
|
||||
|
||||
|
Can't render this file because it is too large.
|
Reference in New Issue
Block a user