Updated for TStudent

- calculated confidence interval
This commit is contained in:
2025-01-24 21:01:31 +01:00
parent bbb069d4d1
commit 71dac2c6d1
3 changed files with 89 additions and 22 deletions

View File

@@ -26,5 +26,10 @@
<version>1.2.0</version> <version>1.2.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -12,7 +12,7 @@ public class Result {
public final Map<String, Statistics> nodes; public final Map<String, Statistics> nodes;
public final long seed; public final long seed;
public final double simulationTime; public final double simulationTime;
public final long timeElapsedNano; public final double timeElapsedMS;
/** /**
* Creates a new result object for the given parameters obtained by the * 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 seed the initial seed used by the simulation
* @param time the final time of 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 * @param nodes all the stats collected by the simulation saved per node
*/ */
public Result(long seed, double time, long elapsed, Map<String, Statistics> nodes) { public Result(long seed, double time, double elapsed, Map<String, Statistics> nodes) {
this.seed = seed; this.seed = seed;
this.simulationTime = time; this.simulationTime = time;
this.timeElapsedNano = elapsed; this.timeElapsedMS = elapsed;
this.nodes = nodes; 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. * Print a summary of the statistics to the console.
* The summary includes the seed, the simulation time, the elapsed time, and * The summary includes the seed, the simulation time, the elapsed time, and
@@ -56,20 +72,4 @@ public class Result {
} }
return table.toString(); 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();
}
} }

View File

@@ -9,6 +9,8 @@ public class ResultMultiple {
public final Result[] runs; public final Result[] runs;
public final Result average; public final Result average;
public final Result variance; public final Result variance;
public final Result lowerBound;
public final Result upperBound;
/** /**
* TODO * TODO
@@ -19,6 +21,10 @@ 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.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) { for (var run : runs) {
avgTime += run.simulationTime; avgTime += run.simulationTime;
avgElapsed += run.timeElapsedNano; avgElapsed += run.timeElapsedMS;
for (var entry : run.nodes.entrySet()) { for (var entry : run.nodes.entrySet()) {
var stats = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics()); var stats = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
@@ -63,7 +69,7 @@ public class ResultMultiple {
for (var run : runs) { for (var run : runs) {
varTime += Math.pow(run.simulationTime - avg.simulationTime, 2); 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()) { for (var entry : run.nodes.entrySet()) {
var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics()); var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
@@ -82,4 +88,60 @@ public class ResultMultiple {
return new Result(runs[0].seed, varTime, varElapsed, nodes); 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 };
}
} }