diff --git a/.vscode/launch.json b/.vscode/launch.json index a7c7c9b..4736d88 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,13 +25,6 @@ "mainClass": "net.berack.upo.valpre.Main", "args": "simulation -net example1.net -runs 10" }, - { - "type": "java", - "name": "Run10", - "request": "launch", - "mainClass": "net.berack.upo.valpre.Main", - "args": "simulation -net example1.net -runs 10" - }, { "type": "java", "name": "Plot Simple", diff --git a/README.md b/README.md index 93b5a5c..e3b2096 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,49 @@ -# upo-valpre -valutazione delle prestazioni (principalemnte Reti di code e di Petri) +# Valutazione delle Prestazioni + +Il progetto riguarda un simulatore ad eventi discreti. +Il simulatore è iniziato con il lavoro trovato sul libro di testo [Discrete-Event System Simulation](https://www.pearson.com/en-us/subject-catalog/p/discrete-event-system-simulation/P200000003161/9780136062127) al Capitolo 4, per poi esser personalizzato e modificato radicalmente. + +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. + +Per fare ciò si può usare il JAR risultante che si trova nelle [Releases](https://github.com/Berack96/upo-valpre/releases). + +### 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: + +* `java -jar upo-valpre.jar net`\ +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 [other]`\ +Usato per avviare una simulazione della rete. Nel caso la rete non abbia eventuali limiti nella generazione di arrivi, viene restituito un errore. +Esistono vari tipi di argomenti per scegliere come fare la simulazione: + * `-runs ` per fare la simulazione N volte + * `-seed ` per dare un seed iniziale scelto + * `-csv ` per salvare i risultati delle run in un file csv + * `-p` per fare le simulazioni in parallelo (ovvero su più thread) +* `java -jar upo-valpre.jar plot -csv `\ +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) + +Esistono dei file prefatti per vedere eventuali simulazioni: +* `example1.net` e `example2.net` per `simulation -net` +* `example1.csv` e `example2.csv` per `plot -csv` + +### 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](https://github.com/Berack96/upo-valpre/tree/main/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: +- [net.berack.upo.valpre.rand](https://github.com/Berack96/upo-valpre/tree/main/src/main/java/net/berack/upo/valpre/rand) All'interno del quale si possono trovare: + - **Rng** che viene usato per il calcolo di numeri pseudo-casuali tramite un seed iniziale e la generazione di molteplici stream di generazione di numeri casuali + - **Distribution** interfaccia usata per la generazione di un numero casuale di una distribuzione. In questo file esistono molteplici classi interne che implementano l'interfaccia; per esempio: Exponential, Normal, Uniform +- [net.berack.upo.valpre.sim](https://github.com/Berack96/upo-valpre/tree/main/src/main/java/net/berack/upo/valpre/sim) Package che contiene tutte le parti utili alla simulazione; per esempio la creazione della rete o la simulazione si più thread: + - **Net** che viene usato per rappresentare una rete da simulare. + - **ServerNode** che viene usato per rappresentare un singolo nodo della rete. + - **Event** che viene usato per rappresentare un evento della simulazione. + - **EndCriteria** interfaccia che viene implementata dalle classi interne usata per controllare se la simulazione debba finire. + - **Simulation** e **SimulationMultiple** che vengono usate per far partire la simulazione; la versione multiple serve ad organizzare molteplici simulazioni si più thread o su un singolo core. +- [net.berack.upo.valpre.sim.stats](https://github.com/Berack96/upo-valpre/tree/main/src/main/java/net/berack/upo/valpre/sim/stats) Package che contiene tutte le classi utili per la raccolta e l'analisi statistica dei vari valori generati dalla simulazione: + - **Result** un singolo risultato e la sua controparte **ResultSummary** che contiene molteplici risultati già analizzati. + - **Statistics** un singolo valore di indici statistici di un nodo e la sua controparte **StatisticsSummary** che contiene molteplici risultati già analizzati. + - **ConsoleTable** utile per mostrare i risultati in console sottoforma di tabella + - **CsvResult** utile per la lettura/scrittura di risultati in formato csv diff --git a/image/README/1738603552417.png b/image/README/1738603552417.png new file mode 100644 index 0000000..80270dd Binary files /dev/null and b/image/README/1738603552417.png differ diff --git a/src/main/java/net/berack/upo/valpre/Main.java b/src/main/java/net/berack/upo/valpre/Main.java index eb8dc33..76e315a 100644 --- a/src/main/java/net/berack/upo/valpre/Main.java +++ b/src/main/java/net/berack/upo/valpre/Main.java @@ -18,7 +18,7 @@ public class Main { var param = Main.getParameters(program, subArgs); switch (program) { case "simulation" -> { - new Simulation(param.get("net")) + new SimulationBuilder(param.get("net")) .setCsv(param.get("csv")) .setRuns(param.getOrDefault("runs", Integer::parseInt, 100)) .setSeed(param.getOrDefault("seed", Long::parseLong, 2007539552L)) diff --git a/src/main/java/net/berack/upo/valpre/Plot.java b/src/main/java/net/berack/upo/valpre/Plot.java index 867e101..8180a02 100644 --- a/src/main/java/net/berack/upo/valpre/Plot.java +++ b/src/main/java/net/berack/upo/valpre/Plot.java @@ -142,7 +142,9 @@ public class Plot { var columnKey = String.format("%.3f", columnVal); dataset.addValue(frequency[i], "Frequency", columnKey); } - this.panelBarChart.getChart().getCategoryPlot().setDataset(dataset); + var chart = this.panelBarChart.getChart(); + chart.getCategoryPlot().setDataset(dataset); + chart.setTitle(stat + " distribution"); var model = this.statList.getModel(); for (int i = 0; i < model.getSize(); i++) { diff --git a/src/main/java/net/berack/upo/valpre/Simulation.java b/src/main/java/net/berack/upo/valpre/SimulationBuilder.java similarity index 90% rename from src/main/java/net/berack/upo/valpre/Simulation.java rename to src/main/java/net/berack/upo/valpre/SimulationBuilder.java index afe06c0..3d0fc6e 100644 --- a/src/main/java/net/berack/upo/valpre/Simulation.java +++ b/src/main/java/net/berack/upo/valpre/SimulationBuilder.java @@ -14,7 +14,7 @@ import net.berack.upo.valpre.sim.stats.CsvResult; * This class is responsible for running the simulation. It parses the arguments * and runs the simulation with the given parameters. */ -public class Simulation { +public class SimulationBuilder { private String csv; private int runs; private long seed; @@ -28,7 +28,7 @@ public class Simulation { * @param netFile the net file to load * @throws IOException if the file has a problem */ - public Simulation(String netFile) throws IOException { + public SimulationBuilder(String netFile) throws IOException { try { var file = Parameters.getFileOrExample(netFile); this.net = Net.load(file); @@ -46,7 +46,7 @@ public class Simulation { * @param net the net * @throws IllegalArgumentException if the net is null */ - public Simulation(Net net) { + public SimulationBuilder(Net net) { if (net == null) throw new IllegalArgumentException("Net needed!"); this.net = net; @@ -59,7 +59,7 @@ public class Simulation { * @throws IllegalArgumentException if the runs are less than 1 * @return this simulation */ - public Simulation setRuns(int runs) { + public SimulationBuilder setRuns(int runs) { if (runs <= 0) throw new IllegalArgumentException("Runs must be greater than 0!"); @@ -73,7 +73,7 @@ public class Simulation { * @param seed the seed * @return this simulation */ - public Simulation setSeed(long seed) { + public SimulationBuilder setSeed(long seed) { this.seed = seed; return this; } @@ -85,7 +85,7 @@ public class Simulation { * @param parallel if the simulation should run in parallel * @return this simulation */ - public Simulation setParallel(boolean parallel) { + public SimulationBuilder setParallel(boolean parallel) { this.parallel = parallel; return this; } @@ -96,7 +96,7 @@ public class Simulation { * @param csv the CSV file * @return this simulation */ - public Simulation setCsv(String csv) { + public SimulationBuilder setCsv(String csv) { this.csv = csv; return this; } @@ -110,7 +110,7 @@ public class Simulation { * @return this simulation * @throws IllegalArgumentException if the criteria are null */ - public Simulation setEndCriteria(EndCriteria... criterias) { + public SimulationBuilder setEndCriteria(EndCriteria... criterias) { if (criterias == null) throw new IllegalArgumentException("End criteria cannot be null!"); this.endCriteria = criterias; diff --git a/src/main/java/net/berack/upo/valpre/sim/Net.java b/src/main/java/net/berack/upo/valpre/sim/Net.java index 89ac3d8..95770ae 100644 --- a/src/main/java/net/berack/upo/valpre/sim/Net.java +++ b/src/main/java/net/berack/upo/valpre/sim/Net.java @@ -7,8 +7,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; -import java.util.function.Consumer; import org.objenesis.strategy.StdInstantiatorStrategy; @@ -25,7 +25,7 @@ import net.berack.upo.valpre.rand.Rng; * connections between nodes. In order to start a simulation, at least one node * must be a Source or must generate at least one event to be processed. */ -public final class Net { +public final class Net implements Iterable { private final List servers = new ArrayList<>(); private final HashMap indices = new HashMap<>(); private final List> connections = new ArrayList<>(); @@ -220,16 +220,6 @@ public final class Net { } } - /** - * Apply a consumer to all the nodes. The implementation uses a stream and for - * this reason you should consider to make thread safe the consumer. - * - * @param consumer a function that takes in input a ServerNode - */ - public void forEachNode(Consumer consumer) { - this.servers.stream().forEach(consumer); - } - /** * Save the current net to a file. * The resulting file is saved with Kryo. @@ -304,4 +294,9 @@ public final class Net { this.weight = weight; } } + + @Override + public Iterator iterator() { + return this.servers.iterator(); + } } diff --git a/src/main/java/net/berack/upo/valpre/sim/Simulation.java b/src/main/java/net/berack/upo/valpre/sim/Simulation.java index 4a32605..37549c9 100644 --- a/src/main/java/net/berack/upo/valpre/sim/Simulation.java +++ b/src/main/java/net/berack/upo/valpre/sim/Simulation.java @@ -40,8 +40,17 @@ public final class Simulation { this.rng = rng; this.time = 0.0d; + // check for ending criteria in simulation + boolean hasLimit = false; + for (var node : net) + if (node.spawnArrivals != Integer.MAX_VALUE) + hasLimit = true; + + if (!hasLimit && (criterias == null || criterias.length == 0)) + throw new IllegalArgumentException("At least one end criteria is needed!"); + // Initial arrivals (if spawned) - net.forEachNode(node -> { + net.forEach(node -> { this.states.put(node.name, new NodeState()); if (node.shouldSpawnArrival(0)) this.addArrival(node); @@ -152,7 +161,7 @@ public final class Simulation { * on the given node, and the delay is determined by the node's service * distribution. * - * @param node The node to create the event for. + * @param node The node to create the event for. * @param state The current state of the node */ public void addDepartureIfPossible(ServerNode node, NodeState state) { diff --git a/src/test/java/net/berack/upo/valpre/sim/TestSimulation.java b/src/test/java/net/berack/upo/valpre/sim/TestSimulation.java index 0b7007e..7d453dc 100644 --- a/src/test/java/net/berack/upo/valpre/sim/TestSimulation.java +++ b/src/test/java/net/berack/upo/valpre/sim/TestSimulation.java @@ -134,7 +134,7 @@ public class TestSimulation { var nodes = new HashSet(); nodes.add(node); nodes.add(node1); - net.forEachNode(n -> assertTrue(nodes.contains(n))); + net.forEach(n -> assertTrue(nodes.contains(n))); net.addConnection(0, 1, 1.0); var conn = net.getChildren(0);