Param
- added parameters to main - print and/or save - added more data to the stats - removed lower and upper bounds for simplier error
This commit is contained in:
@@ -13,6 +13,9 @@ public class Result {
|
||||
public final long seed;
|
||||
public final double simulationTime;
|
||||
public final double timeElapsedMS;
|
||||
private int size;
|
||||
private String iFormat;
|
||||
private String fFormat;
|
||||
|
||||
/**
|
||||
* Creates a new result object for the given parameters obtained by the
|
||||
@@ -28,6 +31,9 @@ public class Result {
|
||||
this.simulationTime = time;
|
||||
this.timeElapsedMS = elapsed;
|
||||
this.nodes = nodes;
|
||||
this.size = (int) Math.ceil(Math.log10(this.simulationTime));
|
||||
this.iFormat = "%" + this.size + ".0f";
|
||||
this.fFormat = "%" + (this.size + 4) + ".3f";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,13 +42,11 @@ public class Result {
|
||||
* 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));
|
||||
builder.append(String.format("Simulation: \t" + fFormat + "\n", this.simulationTime));
|
||||
builder.append(String.format("Elapsed: \t" + fFormat + "ms\n", this.timeElapsedMS / 1e6));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -52,24 +56,68 @@ public class Result {
|
||||
* the statistics for each node in the network.
|
||||
*/
|
||||
public String getSummary() {
|
||||
var size = (int) Math.ceil(Math.log10(this.simulationTime));
|
||||
var iFormat = "%" + size + ".0f";
|
||||
var fFormat = "%" + (size + 4) + ".3f";
|
||||
|
||||
String[] h = { "Node", "Departures", "Avg Queue", "Avg Response", "Throughput", "Utilization %", "Last Event" };
|
||||
String[] h = { "Node", "Departures", "Avg Queue", "Avg Wait", "Avg Response", "Throughput", "Utilization %",
|
||||
"Last Event" };
|
||||
var table = new ConsoleTable(h);
|
||||
|
||||
for (var entry : this.nodes.entrySet()) {
|
||||
var stats = entry.getValue();
|
||||
table.addRow(
|
||||
entry.getKey(),
|
||||
String.format(iFormat, stats.numDepartures),
|
||||
String.format(fFormat, stats.avgQueueLength),
|
||||
String.format(fFormat, stats.avgResponse),
|
||||
String.format(fFormat, stats.troughput),
|
||||
String.format(fFormat, stats.utilization * 100),
|
||||
String.format(fFormat, stats.lastEventTime));
|
||||
iFormat.formatted(stats.numDepartures),
|
||||
fFormat.formatted(stats.avgQueueLength),
|
||||
fFormat.formatted(stats.avgWaitTime),
|
||||
fFormat.formatted(stats.avgResponse),
|
||||
fFormat.formatted(stats.troughput),
|
||||
fFormat.formatted(stats.utilization * 100),
|
||||
fFormat.formatted(stats.lastEventTime));
|
||||
}
|
||||
return table.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param tableHeader
|
||||
* @return
|
||||
*/
|
||||
public String getSummaryCSV(boolean tableHeader) {
|
||||
var builder = new StringBuilder();
|
||||
|
||||
if (tableHeader)
|
||||
builder.append(
|
||||
"Seed,Node,Arrivals,Departures,MaxQueue,AvgQueue,AvgWait,AvgResponse,BusyTime,WaitTime,ResponseTime,LastEventTime,Throughput,Utilization\n");
|
||||
for (var entry : this.nodes.entrySet()) {
|
||||
var stats = entry.getValue();
|
||||
builder.append(this.seed);
|
||||
builder.append(',');
|
||||
builder.append(entry.getKey().replace(',', ';').replace('"', '\''));
|
||||
builder.append(',');
|
||||
builder.append(stats.numArrivals);
|
||||
builder.append(',');
|
||||
builder.append(stats.numDepartures);
|
||||
builder.append(',');
|
||||
builder.append(stats.maxQueueLength);
|
||||
builder.append(',');
|
||||
builder.append(stats.avgQueueLength);
|
||||
builder.append(',');
|
||||
builder.append(stats.avgWaitTime);
|
||||
builder.append(',');
|
||||
builder.append(stats.avgResponse);
|
||||
builder.append(',');
|
||||
builder.append(stats.busyTime);
|
||||
builder.append(',');
|
||||
builder.append(stats.waitTime);
|
||||
builder.append(',');
|
||||
builder.append(stats.responseTime);
|
||||
builder.append(',');
|
||||
builder.append(stats.lastEventTime);
|
||||
builder.append(',');
|
||||
builder.append(stats.troughput);
|
||||
builder.append(',');
|
||||
builder.append(stats.utilization);
|
||||
builder.append('\n');
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.berack.upo.valpre.sim.stats;
|
||||
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
@@ -9,8 +11,7 @@ public class ResultMultiple {
|
||||
public final Result[] runs;
|
||||
public final Result average;
|
||||
public final Result variance;
|
||||
public final Result lowerBound;
|
||||
public final Result upperBound;
|
||||
public final Result error95;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
@@ -18,13 +19,31 @@ public class ResultMultiple {
|
||||
* @param runs
|
||||
*/
|
||||
public ResultMultiple(Result... runs) {
|
||||
if (runs == null || runs.length <= 1)
|
||||
throw new IllegalArgumentException("Sample size must be > 1");
|
||||
|
||||
this.runs = runs;
|
||||
this.average = ResultMultiple.calcAvg(runs);
|
||||
this.variance = ResultMultiple.calcVar(this.average, runs);
|
||||
this.error95 = calcError(this.average, this.variance, runs.length, 0.95);
|
||||
}
|
||||
|
||||
var temp = calcInterval(this.average, this.variance, runs.length, 0.95);
|
||||
this.lowerBound = temp[0];
|
||||
this.upperBound = temp[1];
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param filename
|
||||
* @throws IOException
|
||||
*/
|
||||
public void saveCSV(String filename) throws IOException {
|
||||
try (var file = new FileWriter(filename)) {
|
||||
var first = true;
|
||||
var builder = new StringBuilder();
|
||||
for (var run : this.runs) {
|
||||
builder.append(run.getSummaryCSV(first));
|
||||
first = false;
|
||||
}
|
||||
file.write(builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,10 +117,7 @@ public class ResultMultiple {
|
||||
* @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.");
|
||||
|
||||
public static Result calcError(Result avg, Result stdDev, int sampleSize, double alpha) {
|
||||
// Getting the correct values for the percentile
|
||||
var distr = new org.apache.commons.math3.distribution.TDistribution(sampleSize - 1);
|
||||
var percentile = distr.inverseCumulativeProbability(alpha);
|
||||
@@ -117,31 +133,6 @@ public class ResultMultiple {
|
||||
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 };
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,12 @@ public class Statistics {
|
||||
public double maxQueueLength = 0.0d;
|
||||
public double avgQueueLength = 0.0d;
|
||||
public double busyTime = 0.0d;
|
||||
public double waitTime = 0.0d;
|
||||
public double responseTime = 0.0d;
|
||||
public double lastEventTime = 0.0d;
|
||||
|
||||
// derived stats, you can calculate them even at the end
|
||||
public double avgWaitTime = 0.0d;
|
||||
public double avgResponse = 0.0d;
|
||||
public double troughput = 0.0d;
|
||||
public double utilization = 0.0d;
|
||||
@@ -50,7 +52,9 @@ public class Statistics {
|
||||
this.responseTime += response;
|
||||
this.busyTime += time - this.lastEventTime;
|
||||
this.lastEventTime = time;
|
||||
this.waitTime = this.responseTime - this.busyTime;
|
||||
|
||||
this.avgWaitTime = this.waitTime / this.numDepartures;
|
||||
this.avgResponse = this.responseTime / this.numDepartures;
|
||||
this.troughput = this.numDepartures / this.lastEventTime;
|
||||
this.utilization = this.busyTime / this.lastEventTime;
|
||||
@@ -102,10 +106,12 @@ public class Statistics {
|
||||
save.avgQueueLength = func.apply(val1.avgQueueLength, val2.avgQueueLength);
|
||||
save.busyTime = func.apply(val1.busyTime, val2.busyTime);
|
||||
save.responseTime = func.apply(val1.responseTime, val2.responseTime);
|
||||
save.waitTime = func.apply(val1.waitTime, val2.waitTime);
|
||||
save.lastEventTime = func.apply(val1.lastEventTime, val2.lastEventTime);
|
||||
// derived stats
|
||||
save.avgWaitTime = func.apply(val1.avgWaitTime, val2.avgWaitTime);
|
||||
save.avgResponse = func.apply(val1.avgResponse, val2.avgResponse);
|
||||
save.troughput = func.apply(val1.troughput, val2.troughput);
|
||||
save.utilization = func.apply(val1.utilization, val2.utilization);
|
||||
save.avgResponse = func.apply(val1.avgResponse, val2.avgResponse);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user