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>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
</dependencies>
</project>

View File

@@ -12,7 +12,7 @@ public class Result {
public final Map<String, Statistics> 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<String, Statistics> nodes) {
public Result(long seed, double time, double elapsed, Map<String, Statistics> 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();
}
}

View File

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