Update README and refactor EndCriteria and Simulation classes for improved clarity and functionality

This commit is contained in:
2025-02-04 11:30:25 +01:00
parent 2d5f43bbc9
commit 173dee884f
3 changed files with 62 additions and 24 deletions

View File

@@ -21,6 +21,8 @@ Esistono vari tipi di argomenti per scegliere come fare la simulazione:
* `-seed <value>` per dare un seed iniziale scelto
* `-csv <file>` per salvare i risultati delle run in un file csv
* `-p` per fare le simulazioni in parallelo (ovvero su più thread)
* `-end <criteria>` 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 <file>`\
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

View File

@@ -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;
}
}

View File

@@ -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<String, NodeState> states;
private final PriorityQueue<Event> 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<Event> 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);
}