From 173dee884f21d146224ef5d76f4d72a7cceb8e10 Mon Sep 17 00:00:00 2001 From: Berack96 Date: Tue, 4 Feb 2025 11:30:25 +0100 Subject: [PATCH] Update README and refactor EndCriteria and Simulation classes for improved clarity and functionality --- README.md | 12 ++-- .../berack/upo/valpre/sim/EndCriteria.java | 4 +- .../net/berack/upo/valpre/sim/Simulation.java | 70 ++++++++++++++----- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e3b2096..e345a89 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ Esistono vari tipi di argomenti per scegliere come fare la simulazione: * `-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) + * `-end ` per scegliere quando la simulazione finisce nel caso non ci siano dei source limitati nella creazione di arrivi. La tipologia di fine simulazione la si può trovare dentro `EndCriteria` (ovvero MaxArrivals, MaxDepartures, MaxTime) e la formattazione da usare per passare il parametro è la seguente:\ + `[Tipo1:param1,..,paramN];[..];[TipoN:param1,..,paramN]` * `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) @@ -40,10 +42,10 @@ I percorsi che invece sono direttamente responsabili per la simulazione sono: - **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. + - **EndCriteria** interfaccia che viene implementata dalle classi interne usata per controllare se e quando la simulazione debba finire. + - **Simulation** e **SimulationMultiple** che vengono usate per far partire la simulazione; la versione multiple serve ad organizzare molteplici simulazioni su 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. + - **Result** il risultato di una run e la sua controparte **ResultSummary** che contiene molteplici risultati di run già analizzati. + - **Statistics** contiene indici statistici di un nodo e la sua controparte **StatisticsSummary** che contiene molteplici indici statistici già analizzati. - **ConsoleTable** utile per mostrare i risultati in console sottoforma di tabella - - **CsvResult** utile per la lettura/scrittura di risultati in formato csv + - **CsvResult** utile per la lettura/scrittura dei risultati in formato csv diff --git a/src/main/java/net/berack/upo/valpre/sim/EndCriteria.java b/src/main/java/net/berack/upo/valpre/sim/EndCriteria.java index e7c3077..d6e96bd 100644 --- a/src/main/java/net/berack/upo/valpre/sim/EndCriteria.java +++ b/src/main/java/net/berack/upo/valpre/sim/EndCriteria.java @@ -73,7 +73,7 @@ public interface EndCriteria { @Override public boolean shouldEnd(Simulation run) { - return run.getNode(nodeName).stats.numArrivals >= this.maxArrivals; + return run.getNodeState(nodeName).stats.numArrivals >= this.maxArrivals; } } @@ -99,7 +99,7 @@ public interface EndCriteria { @Override public boolean shouldEnd(Simulation run) { - return run.getNode(nodeName).stats.numDepartures >= this.maxDepartures; + return run.getNodeState(nodeName).stats.numDepartures >= this.maxDepartures; } } 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 37549c9..323d20f 100644 --- a/src/main/java/net/berack/upo/valpre/sim/Simulation.java +++ b/src/main/java/net/berack/upo/valpre/sim/Simulation.java @@ -1,7 +1,9 @@ package net.berack.upo.valpre.sim; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.PriorityQueue; @@ -13,14 +15,16 @@ import net.berack.upo.valpre.sim.stats.Statistics; * Process an entire run of the simulation. */ public final class Simulation { + public final Rng rng; + public final long timeStartedNano; + public final EndCriteria[] criterias; + public final long seed; + private final Net net; private final Map states; private final PriorityQueue fel; - private final EndCriteria[] criterias; - private final long timeStartedNano; - private final long seed; - private final Rng rng; - private double time; + private double time = 0.0d; + private long eventProcessed = 0; /** * Creates a new run of the simulation with the given nodes and random number @@ -31,30 +35,28 @@ public final class Simulation { * @param criterias when the simulation has to end. */ public Simulation(Net net, Rng rng, EndCriteria... criterias) { + this.timeStartedNano = System.nanoTime(); this.net = net; this.states = new HashMap<>(); this.fel = new PriorityQueue<>(); this.criterias = criterias; - this.timeStartedNano = System.nanoTime(); this.seed = rng.getSeed(); this.rng = rng; - this.time = 0.0d; - // check for ending criteria in simulation boolean hasLimit = false; - for (var node : net) + for (var node : net) { + // check for ending criteria in simulation 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.forEach(node -> { + // Initial arrivals (if spawned) this.states.put(node.name, new NodeState()); if (node.shouldSpawnArrival(0)) this.addArrival(node); - }); + } + + if (!hasLimit && (criterias == null || criterias.length == 0)) + throw new IllegalArgumentException("At least one end criteria is needed!"); } /** @@ -74,12 +76,17 @@ public final class Simulation { * You should check if the simulation has ended before calling this method. * * @see #hasEnded() + * @throws NullPointerException if there are no more events to process. */ public void processNextEvent() { var event = fel.poll(); + if (event == null) + throw new NullPointerException("No more events to process!"); + var node = event.node; var state = this.states.get(node.name); this.time = event.time; + this.eventProcessed += 1; switch (event.type) { case AVAILABLE -> { @@ -136,12 +143,41 @@ public final class Simulation { } /** - * Get the node state requested by the name passed as a string. + * Get the number of events processed. + * + * @return the number of events processed. + */ + public long getEventsProcessed() { + return this.eventProcessed; + } + + /** + * Get the list of future events. + * This method returns a copy of the list, so the original list is not modified. + * + * @return a list of future events. + */ + public List getFutureEventList() { + return new ArrayList<>(this.fel); + } + + /** + * Get the node requested by the name passed as a string. * * @param node the name of the node * @return the node */ - public NodeState getNode(String node) { + public ServerNode getNode(String node) { + return this.net.getNode(node); + } + + /** + * Get the node state requested by the name passed as a string. + * + * @param node the name of the node + * @return the current state of the node + */ + public NodeState getNodeState(String node) { return this.states.get(node); }