From 0c82dc7dff595d500c9635452f6f33c424e9216f Mon Sep 17 00:00:00 2001 From: Berack96 Date: Wed, 29 Jan 2025 12:07:36 +0100 Subject: [PATCH] Docs - added docs for all the classes and methods - fixed variance --> stdDev --- .../net/berack/upo/valpre/Parameters.java | 42 ++++++---- .../berack/upo/valpre/rand/Distribution.java | 11 ++- .../upo/valpre/sim/stats/ConsoleTable.java | 23 ++++-- .../upo/valpre/sim/stats/ResultMultiple.java | 77 +++++++++++-------- .../upo/valpre/sim/stats/Statistics.java | 57 +++++++++----- 5 files changed, 136 insertions(+), 74 deletions(-) diff --git a/src/main/java/net/berack/upo/valpre/Parameters.java b/src/main/java/net/berack/upo/valpre/Parameters.java index 04e18cf..73617b5 100644 --- a/src/main/java/net/berack/upo/valpre/Parameters.java +++ b/src/main/java/net/berack/upo/valpre/Parameters.java @@ -4,16 +4,21 @@ import java.util.HashMap; import java.util.Map; /** - * TODO + * Class that helps with parsing the parameters passed as input in the console. */ public class Parameters { private final Map arguments; private final String prefix; /** - * TODO - * - * @param arguments + * 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 + * 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 arguments) { if (arguments == null || arguments.size() == 0) @@ -23,10 +28,11 @@ public class Parameters { } /** - * TODO + * Return a string with the standard spaced enough * - * @param eventualDescription - * @return + * @param eventualDescription the description for the argument, if not present + * the argument will be shown anyway/ + * @return a string of arguments */ public String helper(Map eventualDescription) { 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 - * @return + * @param args the arguments in input + * @throws IllegalArgumentException if the arguments are not formatted correctly + * or if there is an unknown argument + * @return a map of the values */ public Map parse(String[] args) { var result = new HashMap(); @@ -85,12 +95,14 @@ public class Parameters { } /** - * TODO + * Parse one single argument and put it into the map. * - * @param current - * @param next - * @param result - * @return + * @param current the current argument + * @param next the next argument if present + * @param result the map where to insert the value + * @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 result) { if (!current.startsWith(this.prefix)) diff --git a/src/main/java/net/berack/upo/valpre/rand/Distribution.java b/src/main/java/net/berack/upo/valpre/rand/Distribution.java index f598477..be4e43b 100644 --- a/src/main/java/net/berack/upo/valpre/rand/Distribution.java +++ b/src/main/java/net/berack/upo/valpre/rand/Distribution.java @@ -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 final double probability; 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 distribution + * @param probability the probability of returning a value > 0.0 + * @param distribution the distribution where to get the samples */ public UnavailableTime(double probability, Distribution distribution) { this.probability = probability; diff --git a/src/main/java/net/berack/upo/valpre/sim/stats/ConsoleTable.java b/src/main/java/net/berack/upo/valpre/sim/stats/ConsoleTable.java index 0532716..de038db 100644 --- a/src/main/java/net/berack/upo/valpre/sim/stats/ConsoleTable.java +++ b/src/main/java/net/berack/upo/valpre/sim/stats/ConsoleTable.java @@ -1,23 +1,31 @@ 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 { private StringBuilder builder = new StringBuilder(); private final int maxLen; + private final int columns; 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) { var max = 0; for (var name : header) max = Math.max(max, name.length()); + + this.columns = header.length; this.maxLen = max + 2; this.border = ("+" + "═".repeat(maxLen)).repeat(header.length) + "+\n"; 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) { + if (this.columns != values.length) + throw new IllegalArgumentException("Length must be " + this.columns); + for (var val : values) { var diff = maxLen - val.length(); var first = (int) Math.ceil(diff / 2.0); diff --git a/src/main/java/net/berack/upo/valpre/sim/stats/ResultMultiple.java b/src/main/java/net/berack/upo/valpre/sim/stats/ResultMultiple.java index 6dda5e2..973b380 100644 --- a/src/main/java/net/berack/upo/valpre/sim/stats/ResultMultiple.java +++ b/src/main/java/net/berack/upo/valpre/sim/stats/ResultMultiple.java @@ -5,7 +5,7 @@ import java.io.IOException; import java.util.HashMap; /** - * TODO + * This class represent the result of multiple runs of simulation. */ public class ResultMultiple { public final Result[] runs; @@ -14,9 +14,13 @@ public class ResultMultiple { 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) { if (runs == null || runs.length <= 1) @@ -24,17 +28,20 @@ public class ResultMultiple { this.runs = 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); } /** - * TODO + * Save all the runs to a csv file. * - * @param filename - * @throws IOException + * @param filename the name of the file + * @throws IOException if anything happens wile wriiting to the file */ public void saveCSV(String filename) throws IOException { + if (!filename.endsWith(".csv")) + filename = filename + ".csv"; + try (var file = new FileWriter(filename)) { var first = true; 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 - * @return + * @param runs the run to calculate + * @return the average of the runs */ public static Result calcAvg(Result... runs) { 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 runs - * @return + * @param avg the average of the runs. {@link #calcAvg(Result...)} + * @param runs the run to calculate + * @return the standard deviation of the runs */ - public static Result calcVar(Result avg, Result... runs) { - var varTime = 0.0d; - var varElapsed = 0L; + public static Result calcStdDev(Result avg, Result... runs) { + var time = 0.0d; + var elapsed = 0.0d; var nodes = new HashMap(); for (var run : runs) { - varTime += Math.pow(run.simulationTime - avg.simulationTime, 2); - varElapsed += Math.pow(run.timeElapsedMS - avg.simulationTime, 2); + time += Math.pow(run.simulationTime - avg.simulationTime, 2); + elapsed += Math.pow(run.timeElapsedMS - avg.simulationTime, 2); for (var entry : run.nodes.entrySet()) { var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics()); @@ -100,22 +109,30 @@ public class ResultMultiple { } } - varTime /= runs.length - 1; - varElapsed /= runs.length - 1; + time = Math.sqrt(time / runs.length - 1); + elapsed = Math.sqrt(elapsed / runs.length - 1); 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 - * - * @param avg - * @param stdDev - * @param sampleSize - * @param alpha - * @return + * Calculates the error at the selected alpha level. + * This method computes the error margin for the provided average and standard + * deviation values, + * considering the sample size and the confidence level (alpha). + * The result is adjusted using a t-distribution to account for the variability + * in smaller sample sizes. + * + * @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) { // Getting the correct values for the percentile diff --git a/src/main/java/net/berack/upo/valpre/sim/stats/Statistics.java b/src/main/java/net/berack/upo/valpre/sim/stats/Statistics.java index 9f68097..ef76141 100644 --- a/src/main/java/net/berack/upo/valpre/sim/stats/Statistics.java +++ b/src/main/java/net/berack/upo/valpre/sim/stats/Statistics.java @@ -4,7 +4,11 @@ import java.util.function.BiFunction; 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 double numArrivals = 0.0d; @@ -25,11 +29,11 @@ public class Statistics { public double unavailable = 0.0d; /** - * TODO - * - * @param time - * @param newQueueSize - * @param updateBusy + * Updates statistics when a new arrival occurs. It updates the number of + * arrivals, the average queue length, and the maximum queue length. + * + * @param time The current time of the arrival event. + * @param newQueueSize The size of the queue after the arrival. */ public void updateArrival(double time, double newQueueSize) { var total = this.avgQueueLength * this.numArrivals; @@ -40,10 +44,12 @@ public class Statistics { } /** - * TODO - * - * @param time - * @param response + * Updates statistics when a departure occurs. It increments the number of + * departures and calculates the total response time. + * + * @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) { this.numDepartures++; @@ -51,11 +57,14 @@ public class Statistics { } /** - * TODO - * - * @param time - * @param serverBusy - * @param serverUnavailable + * Updates statistics related to server busy time, unavailable time, and derived + * stats. It also calculates the average wait time, response time, throughput, + * utilization, and unavailability. + * + * @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) { 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 val1 - * @param val2 - * @param func + * @param save The `Statistics` object where the merged results will be stored. + * @param val1 The first `Statistics` object to merge. + * @param val2 The second `Statistics` object to merge. + * @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, BiFunction func) {