Docs
- added docs for all the classes and methods - fixed variance --> stdDev
This commit is contained in:
@@ -4,16 +4,21 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Class that helps with parsing the parameters passed as input in the console.
|
||||||
*/
|
*/
|
||||||
public class Parameters {
|
public class Parameters {
|
||||||
private final Map<String, Boolean> arguments;
|
private final Map<String, Boolean> arguments;
|
||||||
private final String prefix;
|
private final String prefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Constructs a new Parameters object with the specified prefix and arguments.
|
||||||
*
|
* The arguments can be with value, in that case in the map the boolean should
|
||||||
* @param arguments
|
* be true, otherwise it is only an argument that is a flag
|
||||||
|
*
|
||||||
|
* @param prefix the prefix to be used
|
||||||
|
* @param arguments a map of arguments where the key is a string and if the
|
||||||
|
* boolean is true then the argument expect a value
|
||||||
|
* @throws IllegalArgumentException if the arguments map is null or empty
|
||||||
*/
|
*/
|
||||||
public Parameters(String prefix, Map<String, Boolean> arguments) {
|
public Parameters(String prefix, Map<String, Boolean> arguments) {
|
||||||
if (arguments == null || arguments.size() == 0)
|
if (arguments == null || arguments.size() == 0)
|
||||||
@@ -23,10 +28,11 @@ public class Parameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Return a string with the standard <arggument> <description> spaced enough
|
||||||
*
|
*
|
||||||
* @param eventualDescription
|
* @param eventualDescription the description for the argument, if not present
|
||||||
* @return
|
* the argument will be shown anyway/
|
||||||
|
* @return a string of arguments
|
||||||
*/
|
*/
|
||||||
public String helper(Map<String, String> eventualDescription) {
|
public String helper(Map<String, String> eventualDescription) {
|
||||||
var size = 0;
|
var size = 0;
|
||||||
@@ -62,10 +68,14 @@ public class Parameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Parse the arguments passed and returns a map of Argument --> Value that can
|
||||||
|
* be used to retrieve the information. In the case that the arguments are not
|
||||||
|
* in the correct format then an exception is thrown.
|
||||||
*
|
*
|
||||||
* @param args
|
* @param args the arguments in input
|
||||||
* @return
|
* @throws IllegalArgumentException if the arguments are not formatted correctly
|
||||||
|
* or if there is an unknown argument
|
||||||
|
* @return a map of the values
|
||||||
*/
|
*/
|
||||||
public Map<String, String> parse(String[] args) {
|
public Map<String, String> parse(String[] args) {
|
||||||
var result = new HashMap<String, String>();
|
var result = new HashMap<String, String>();
|
||||||
@@ -85,12 +95,14 @@ public class Parameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Parse one single argument and put it into the map.
|
||||||
*
|
*
|
||||||
* @param current
|
* @param current the current argument
|
||||||
* @param next
|
* @param next the next argument if present
|
||||||
* @param result
|
* @param result the map where to insert the value
|
||||||
* @return
|
* @throws IllegalArgumentException if the arguments are not formatted correctly
|
||||||
|
* or if there is an unknown argument
|
||||||
|
* @return true if the next argument is used
|
||||||
*/
|
*/
|
||||||
private boolean parseSingle(String current, String next, Map<String, String> result) {
|
private boolean parseSingle(String current, String next, Map<String, String> result) {
|
||||||
if (!current.startsWith(this.prefix))
|
if (!current.startsWith(this.prefix))
|
||||||
|
|||||||
@@ -200,17 +200,20 @@ public interface Distribution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Distribution of the UnavailableTime that has a probability of happening.
|
||||||
|
* In case the node is unavailable then a value of the second distribution is
|
||||||
|
* returned.
|
||||||
*/
|
*/
|
||||||
public static class UnavailableTime implements Distribution {
|
public static class UnavailableTime implements Distribution {
|
||||||
public final double probability;
|
public final double probability;
|
||||||
public final Distribution distribution;
|
public final Distribution distribution;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Create a new distribution with a probability of happening.
|
||||||
|
* In case it happens then a value of the second distribution is returned.
|
||||||
*
|
*
|
||||||
* @param probability
|
* @param probability the probability of returning a value > 0.0
|
||||||
* @param distribution
|
* @param distribution the distribution where to get the samples
|
||||||
*/
|
*/
|
||||||
public UnavailableTime(double probability, Distribution distribution) {
|
public UnavailableTime(double probability, Distribution distribution) {
|
||||||
this.probability = probability;
|
this.probability = probability;
|
||||||
|
|||||||
@@ -1,23 +1,31 @@
|
|||||||
package net.berack.upo.valpre.sim.stats;
|
package net.berack.upo.valpre.sim.stats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Class used to build a nice table from the header and row passed.
|
||||||
|
* The result can be retrieved by {@link #toString()}
|
||||||
*/
|
*/
|
||||||
public class ConsoleTable {
|
public class ConsoleTable {
|
||||||
|
|
||||||
private StringBuilder builder = new StringBuilder();
|
private StringBuilder builder = new StringBuilder();
|
||||||
private final int maxLen;
|
private final int maxLen;
|
||||||
|
private final int columns;
|
||||||
private final String border;
|
private final String border;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Create a new table with the header passed as input.
|
||||||
|
* The table will have as many columns as the length of the header array.
|
||||||
|
* Each column will have the same size and will be the max length of all the
|
||||||
|
* headers string.
|
||||||
*
|
*
|
||||||
* @param header
|
* @param header an array of strings
|
||||||
|
* @throws NullPointerException if the array is null
|
||||||
*/
|
*/
|
||||||
public ConsoleTable(String... header) {
|
public ConsoleTable(String... header) {
|
||||||
var max = 0;
|
var max = 0;
|
||||||
for (var name : header)
|
for (var name : header)
|
||||||
max = Math.max(max, name.length());
|
max = Math.max(max, name.length());
|
||||||
|
|
||||||
|
this.columns = header.length;
|
||||||
this.maxLen = max + 2;
|
this.maxLen = max + 2;
|
||||||
this.border = ("+" + "═".repeat(maxLen)).repeat(header.length) + "+\n";
|
this.border = ("+" + "═".repeat(maxLen)).repeat(header.length) + "+\n";
|
||||||
this.builder.append(border);
|
this.builder.append(border);
|
||||||
@@ -25,11 +33,16 @@ public class ConsoleTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Add to the table the values of the array. If the array null or the length is
|
||||||
|
* different than the header.len then an exception i thrown.
|
||||||
*
|
*
|
||||||
* @param values
|
* @param values an array of values to print
|
||||||
|
* @throw IllegalArgumentException if the values.len is != than the headers.len
|
||||||
*/
|
*/
|
||||||
public void addRow(String... values) {
|
public void addRow(String... values) {
|
||||||
|
if (this.columns != values.length)
|
||||||
|
throw new IllegalArgumentException("Length must be " + this.columns);
|
||||||
|
|
||||||
for (var val : values) {
|
for (var val : values) {
|
||||||
var diff = maxLen - val.length();
|
var diff = maxLen - val.length();
|
||||||
var first = (int) Math.ceil(diff / 2.0);
|
var first = (int) Math.ceil(diff / 2.0);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import java.io.IOException;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* This class represent the result of multiple runs of simulation.
|
||||||
*/
|
*/
|
||||||
public class ResultMultiple {
|
public class ResultMultiple {
|
||||||
public final Result[] runs;
|
public final Result[] runs;
|
||||||
@@ -14,9 +14,13 @@ public class ResultMultiple {
|
|||||||
public final Result error95;
|
public final Result error95;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* This has all the result and give some statistics about the runs.
|
||||||
|
* The object created has the average, the variance, and the error95.
|
||||||
|
* The runs must be an array of at least 2 run result otherwise an exception is
|
||||||
|
* thrown.
|
||||||
*
|
*
|
||||||
* @param runs
|
* @param runs an array of run result
|
||||||
|
* @throws IllegalArgumentException if the runs is null or if has a len <= 1
|
||||||
*/
|
*/
|
||||||
public ResultMultiple(Result... runs) {
|
public ResultMultiple(Result... runs) {
|
||||||
if (runs == null || runs.length <= 1)
|
if (runs == null || runs.length <= 1)
|
||||||
@@ -24,17 +28,20 @@ public class ResultMultiple {
|
|||||||
|
|
||||||
this.runs = runs;
|
this.runs = runs;
|
||||||
this.average = ResultMultiple.calcAvg(runs);
|
this.average = ResultMultiple.calcAvg(runs);
|
||||||
this.variance = ResultMultiple.calcVar(this.average, runs);
|
this.variance = ResultMultiple.calcStdDev(this.average, runs);
|
||||||
this.error95 = calcError(this.average, this.variance, runs.length, 0.95);
|
this.error95 = calcError(this.average, this.variance, runs.length, 0.95);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Save all the runs to a csv file.
|
||||||
*
|
*
|
||||||
* @param filename
|
* @param filename the name of the file
|
||||||
* @throws IOException
|
* @throws IOException if anything happens wile wriiting to the file
|
||||||
*/
|
*/
|
||||||
public void saveCSV(String filename) throws IOException {
|
public void saveCSV(String filename) throws IOException {
|
||||||
|
if (!filename.endsWith(".csv"))
|
||||||
|
filename = filename + ".csv";
|
||||||
|
|
||||||
try (var file = new FileWriter(filename)) {
|
try (var file = new FileWriter(filename)) {
|
||||||
var first = true;
|
var first = true;
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
@@ -47,10 +54,11 @@ public class ResultMultiple {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* This method calculate the average of the runs result.
|
||||||
|
* The average is calculated for each node.
|
||||||
*
|
*
|
||||||
* @param runs
|
* @param runs the run to calculate
|
||||||
* @return
|
* @return the average of the runs
|
||||||
*/
|
*/
|
||||||
public static Result calcAvg(Result... runs) {
|
public static Result calcAvg(Result... runs) {
|
||||||
var avgTime = 0.0d;
|
var avgTime = 0.0d;
|
||||||
@@ -75,20 +83,21 @@ public class ResultMultiple {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* This method calculate the standard deviation of the runs result.
|
||||||
|
* The standard deviation is calculated for each node.
|
||||||
*
|
*
|
||||||
* @param avg
|
* @param avg the average of the runs. {@link #calcAvg(Result...)}
|
||||||
* @param runs
|
* @param runs the run to calculate
|
||||||
* @return
|
* @return the standard deviation of the runs
|
||||||
*/
|
*/
|
||||||
public static Result calcVar(Result avg, Result... runs) {
|
public static Result calcStdDev(Result avg, Result... runs) {
|
||||||
var varTime = 0.0d;
|
var time = 0.0d;
|
||||||
var varElapsed = 0L;
|
var elapsed = 0.0d;
|
||||||
var nodes = new HashMap<String, Statistics>();
|
var nodes = new HashMap<String, Statistics>();
|
||||||
|
|
||||||
for (var run : runs) {
|
for (var run : runs) {
|
||||||
varTime += Math.pow(run.simulationTime - avg.simulationTime, 2);
|
time += Math.pow(run.simulationTime - avg.simulationTime, 2);
|
||||||
varElapsed += Math.pow(run.timeElapsedMS - avg.simulationTime, 2);
|
elapsed += Math.pow(run.timeElapsedMS - avg.simulationTime, 2);
|
||||||
|
|
||||||
for (var entry : run.nodes.entrySet()) {
|
for (var entry : run.nodes.entrySet()) {
|
||||||
var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
|
var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
|
||||||
@@ -100,22 +109,30 @@ public class ResultMultiple {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
varTime /= runs.length - 1;
|
time = Math.sqrt(time / runs.length - 1);
|
||||||
varElapsed /= runs.length - 1;
|
elapsed = Math.sqrt(elapsed / runs.length - 1);
|
||||||
for (var stat : nodes.values())
|
for (var stat : nodes.values())
|
||||||
stat.apply(val -> val / (runs.length - 1));
|
stat.apply(val -> Math.sqrt(val / (runs.length - 1)));
|
||||||
|
|
||||||
return new Result(runs[0].seed, varTime, varElapsed, nodes);
|
return new Result(runs[0].seed, time, elapsed, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Calculates the error at the selected alpha level.
|
||||||
*
|
* This method computes the error margin for the provided average and standard
|
||||||
* @param avg
|
* deviation values,
|
||||||
* @param stdDev
|
* considering the sample size and the confidence level (alpha).
|
||||||
* @param sampleSize
|
* The result is adjusted using a t-distribution to account for the variability
|
||||||
* @param alpha
|
* in smaller sample sizes.
|
||||||
* @return
|
*
|
||||||
|
* @param avg The average of the results, typically computed using
|
||||||
|
* {@link #calcAvg(Result...)}.
|
||||||
|
* @param stdDev The standard deviation of the results, typically computed
|
||||||
|
* using {@link #calcVar(Result, Result...)}.
|
||||||
|
* @param sampleSize The number of runs or samples used.
|
||||||
|
* @param alpha The significance level (probability) used for the
|
||||||
|
* t-distribution. A value of 0.95 for a 95% confidence level.
|
||||||
|
* @return The calculated error.
|
||||||
*/
|
*/
|
||||||
public static Result calcError(Result avg, Result stdDev, int sampleSize, double alpha) {
|
public static Result calcError(Result avg, Result stdDev, int sampleSize, double alpha) {
|
||||||
// Getting the correct values for the percentile
|
// Getting the correct values for the percentile
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ import java.util.function.BiFunction;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* This class keeps track of various statistical metrics related to the net
|
||||||
|
* performance, such as the number of arrivals and departures, queue lengths,
|
||||||
|
* wait times, response times, server utilization, and unavailability. These
|
||||||
|
* statistics are updated during simulation events, such as arrivals and
|
||||||
|
* departures, and can be used to analyze the net's behavior and performance.
|
||||||
*/
|
*/
|
||||||
public class Statistics {
|
public class Statistics {
|
||||||
public double numArrivals = 0.0d;
|
public double numArrivals = 0.0d;
|
||||||
@@ -25,11 +29,11 @@ public class Statistics {
|
|||||||
public double unavailable = 0.0d;
|
public double unavailable = 0.0d;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Updates statistics when a new arrival occurs. It updates the number of
|
||||||
*
|
* arrivals, the average queue length, and the maximum queue length.
|
||||||
* @param time
|
*
|
||||||
* @param newQueueSize
|
* @param time The current time of the arrival event.
|
||||||
* @param updateBusy
|
* @param newQueueSize The size of the queue after the arrival.
|
||||||
*/
|
*/
|
||||||
public void updateArrival(double time, double newQueueSize) {
|
public void updateArrival(double time, double newQueueSize) {
|
||||||
var total = this.avgQueueLength * this.numArrivals;
|
var total = this.avgQueueLength * this.numArrivals;
|
||||||
@@ -40,10 +44,12 @@ public class Statistics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Updates statistics when a departure occurs. It increments the number of
|
||||||
*
|
* departures and calculates the total response time.
|
||||||
* @param time
|
*
|
||||||
* @param response
|
* @param time The current time of the departure event.
|
||||||
|
* @param response The time at which the response was generated for this
|
||||||
|
* departure.
|
||||||
*/
|
*/
|
||||||
public void updateDeparture(double time, double response) {
|
public void updateDeparture(double time, double response) {
|
||||||
this.numDepartures++;
|
this.numDepartures++;
|
||||||
@@ -51,11 +57,14 @@ public class Statistics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Updates statistics related to server busy time, unavailable time, and derived
|
||||||
*
|
* stats. It also calculates the average wait time, response time, throughput,
|
||||||
* @param time
|
* utilization, and unavailability.
|
||||||
* @param serverBusy
|
*
|
||||||
* @param serverUnavailable
|
* @param time The current time when the event occurs.
|
||||||
|
* @param serverBusy The number of servers currently busy.
|
||||||
|
* @param serverUnavailable The number of servers currently unavailable.
|
||||||
|
* @param maxServers The total number of servers available.
|
||||||
*/
|
*/
|
||||||
public void updateTimes(double time, int serverBusy, int serverUnavailable, int maxServers) {
|
public void updateTimes(double time, int serverBusy, int serverUnavailable, int maxServers) {
|
||||||
if (serverBusy > 0)
|
if (serverBusy > 0)
|
||||||
@@ -105,12 +114,20 @@ public class Statistics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* Applies a binary function to merge two sets of statistics into a third one.
|
||||||
|
* This method combines the statistics from two `Statistics` objects (`val1` and
|
||||||
|
* `val2`) and stores the result in the `save` object. The provided function is
|
||||||
|
* applied to each pair of corresponding statistics from `val1` and `val2` to
|
||||||
|
* compute the merged value. This is useful for merging or combining statistics
|
||||||
|
* from different sources (e.g., different simulation runs), allowing the
|
||||||
|
* creation of aggregated statistics.
|
||||||
*
|
*
|
||||||
* @param save
|
* @param save The `Statistics` object where the merged results will be stored.
|
||||||
* @param val1
|
* @param val1 The first `Statistics` object to merge.
|
||||||
* @param val2
|
* @param val2 The second `Statistics` object to merge.
|
||||||
* @param func
|
* @param func The binary function that defines how to merge each pair of values
|
||||||
|
* from `val1` and `val2`. It takes two `Double` values (from `val1`
|
||||||
|
* and `val2`) and returns a new `Double` value.
|
||||||
*/
|
*/
|
||||||
public static void apply(Statistics save, Statistics val1, Statistics val2,
|
public static void apply(Statistics save, Statistics val1, Statistics val2,
|
||||||
BiFunction<Double, Double, Double> func) {
|
BiFunction<Double, Double, Double> func) {
|
||||||
|
|||||||
Reference in New Issue
Block a user