From 71dac2c6d1760356aad99d028e9d6b81328a8087 Mon Sep 17 00:00:00 2001 From: Berack96 Date: Fri, 24 Jan 2025 21:01:31 +0100 Subject: [PATCH] Updated for TStudent - calculated confidence interval --- pom.xml | 5 ++ .../berack/upo/valpre/sim/stats/Result.java | 40 +++++------ .../upo/valpre/sim/stats/ResultMultiple.java | 66 ++++++++++++++++++- 3 files changed, 89 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index 70a86c3..c9b6055 100644 --- a/pom.xml +++ b/pom.xml @@ -26,5 +26,10 @@ 1.2.0 test + + org.apache.commons + commons-math3 + 3.6.1 + \ No newline at end of file diff --git a/src/main/java/net/berack/upo/valpre/sim/stats/Result.java b/src/main/java/net/berack/upo/valpre/sim/stats/Result.java index 57d5021..3a61569 100644 --- a/src/main/java/net/berack/upo/valpre/sim/stats/Result.java +++ b/src/main/java/net/berack/upo/valpre/sim/stats/Result.java @@ -12,7 +12,7 @@ public class Result { public final Map nodes; public final long seed; public final double simulationTime; - public final long timeElapsedNano; + public final double timeElapsedMS; /** * Creates a new result object for the given parameters obtained by the @@ -20,16 +20,32 @@ public class Result { * * @param seed the initial seed used by the simulation * @param time the final time of the simulation - * @param elapsed the real time elapsed while running the simulation in ns + * @param elapsed the real time elapsed while running the simulation in ms * @param nodes all the stats collected by the simulation saved per node */ - public Result(long seed, double time, long elapsed, Map nodes) { + public Result(long seed, double time, double elapsed, Map nodes) { this.seed = seed; this.simulationTime = time; - this.timeElapsedNano = elapsed; + this.timeElapsedMS = elapsed; this.nodes = nodes; } + /** + * Get the global information of the simulation. In particular this method build + * a string that contains the seed and the time elapsed in the simulation and in + * real time + */ + public String getHeader() { + var size = (int) Math.ceil(Math.log10(this.simulationTime)); + var format = "%" + (size + 4) + ".3f"; + var builder = new StringBuilder(); + builder.append("===== Net Stats =====\n"); + builder.append(String.format("Seed: \t%d\n", this.seed)); + builder.append(String.format("Simulation: \t" + format + "\n", this.simulationTime)); + builder.append(String.format("Elapsed: \t" + format + "ms\n", this.timeElapsedMS / 1e6)); + return builder.toString(); + } + /** * Print a summary of the statistics to the console. * The summary includes the seed, the simulation time, the elapsed time, and @@ -56,20 +72,4 @@ public class Result { } return table.toString(); } - - /** - * Get the global information of the simulation. In particular this method build - * a string that contains the seed and the time elapsed in the simulation and in - * real time - */ - public String getHeader() { - var size = (int) Math.ceil(Math.log10(this.simulationTime)); - var format = "%" + (size + 4) + ".3f"; - var builder = new StringBuilder(); - builder.append("===== Net Stats =====\n"); - builder.append(String.format("Seed: \t%d\n", this.seed)); - builder.append(String.format("Simulation: \t" + format + "\n", this.simulationTime)); - builder.append(String.format("Elapsed: \t" + format + "ms\n", this.timeElapsedNano / 1e6)); - return builder.toString(); - } } 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 45fd9ca..6f5daa6 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 @@ -9,6 +9,8 @@ public class ResultMultiple { public final Result[] runs; public final Result average; public final Result variance; + public final Result lowerBound; + public final Result upperBound; /** * TODO @@ -19,6 +21,10 @@ public class ResultMultiple { this.runs = runs; this.average = ResultMultiple.calcAvg(runs); this.variance = ResultMultiple.calcVar(this.average, runs); + + var temp = calcInterval(this.average, this.variance, runs.length, 0.95); + this.lowerBound = temp[0]; + this.upperBound = temp[1]; } /** @@ -34,7 +40,7 @@ public class ResultMultiple { for (var run : runs) { avgTime += run.simulationTime; - avgElapsed += run.timeElapsedNano; + avgElapsed += run.timeElapsedMS; for (var entry : run.nodes.entrySet()) { var stats = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics()); @@ -63,7 +69,7 @@ public class ResultMultiple { for (var run : runs) { varTime += Math.pow(run.simulationTime - avg.simulationTime, 2); - varElapsed += Math.pow(run.timeElapsedNano - avg.simulationTime, 2); + varElapsed += Math.pow(run.timeElapsedMS - avg.simulationTime, 2); for (var entry : run.nodes.entrySet()) { var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics()); @@ -82,4 +88,60 @@ public class ResultMultiple { return new Result(runs[0].seed, varTime, varElapsed, nodes); } + + /** + * TODO + * + * @param avg + * @param stdDev + * @param sampleSize + * @param alpha + * @return + */ + public static Result[] calcInterval(Result avg, Result stdDev, int sampleSize, double alpha) { + if (sampleSize <= 1) + throw new IllegalArgumentException("Il numero di campioni deve essere maggiore di 1."); + + // Getting the correct values for the percentile + var distr = new org.apache.commons.math3.distribution.TDistribution(sampleSize - 1); + var percentile = distr.inverseCumulativeProbability(alpha); + + // Calculating the error + var sqrtSample = Math.sqrt(sampleSize); + var error = new Result(avg.seed, + percentile * (stdDev.simulationTime / sqrtSample), + percentile * (stdDev.timeElapsedMS / sqrtSample), + new HashMap<>()); + for (var entry : stdDev.nodes.entrySet()) { + var stat = new Statistics(); + stat.merge(entry.getValue(), (_, val) -> percentile * (val / sqrtSample)); + error.nodes.put(entry.getKey(), stat); + } + + // Calculating the lower and the upper bound + var lowerBound = new Result(avg.seed, + avg.simulationTime - error.simulationTime, + avg.timeElapsedMS - error.timeElapsedMS, + new HashMap<>()); + var upperBound = new Result(avg.seed, + avg.simulationTime + error.simulationTime, + avg.timeElapsedMS + error.timeElapsedMS, + new HashMap<>()); + error.nodes.entrySet().forEach(entry -> { + var key = entry.getKey(); + var errStat = entry.getValue(); + + var avgStat = avg.nodes.get(key); + var lower = new Statistics(); + var upper = new Statistics(); + + Statistics.apply(lower, avgStat, errStat, (a, e) -> a - e); + Statistics.apply(upper, avgStat, errStat, (a, e) -> a + e); + + lowerBound.nodes.put(key, lower); + upperBound.nodes.put(key, lower); + }); + + return new Result[] { lowerBound, upperBound }; + } } \ No newline at end of file