diff --git a/.vscode/launch.json b/.vscode/launch.json index e8d586b..fabc344 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,13 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "type": "java", + "name": "NetExamples", + "request": "launch", + "mainClass": "net.berack.upo.valpre.NetExamples", + "projectName": "valpre" + }, { "type": "java", "name": "Run1k Simple", @@ -52,6 +59,6 @@ "request": "launch", "mainClass": "net.berack.upo.valpre.Main", "args": "interactive" - }, + } ] } \ No newline at end of file diff --git a/src/main/java/net/berack/upo/valpre/NetExamples.java b/src/main/java/net/berack/upo/valpre/NetExamples.java index a6f31b4..9ee6d4f 100644 --- a/src/main/java/net/berack/upo/valpre/NetExamples.java +++ b/src/main/java/net/berack/upo/valpre/NetExamples.java @@ -1,8 +1,12 @@ package net.berack.upo.valpre; +import java.util.concurrent.ExecutionException; + import net.berack.upo.valpre.rand.Distribution; import net.berack.upo.valpre.sim.Net; import net.berack.upo.valpre.sim.ServerNode; +import net.berack.upo.valpre.sim.SimulationMultiple; +import net.berack.upo.valpre.sim.stats.Result; /** * This class provides two example networks. @@ -10,37 +14,64 @@ import net.berack.upo.valpre.sim.ServerNode; * The second network is composed of a terminal node and two queue nodes. */ public final class NetExamples { + + /** + * Main method to test the example networks. + * It runs the fist network and prints the results. + * The network will have the distribution changed but the mean will be the same. + * + * @param args not needed + * @throws ExecutionException if the execution fails + * @throws InterruptedException if the execution is interrupted + */ + public static void main(String[] args) throws InterruptedException, ExecutionException { + var avg1 = 3.2; + var seed = 0l; + + var nets = new Net[] { + getNet1("Normal", new Distribution.NormalBoxMuller(avg1, 0.6)), + getNet1("Exponential", new Distribution.Exponential(1 / avg1)), + getNet1("Erlang", new Distribution.Erlang(5, 5 / avg1)), + getNet1("Uniform", new Distribution.Uniform(avg1 - 1, avg1 + 1)) + }; + + for (var net : nets) { + var summary = new SimulationMultiple(net).runParallel(seed, 1000); + var table = Result.getResultString(summary.getNodes(), summary.getStats()); + System.out.println(table); + } + } + /** * Return the first example network. * The net is composed of a terminal node and a queue node. * The terminal node generates 10000 jobs with an exponential distribution 4.5. * The queue node has a capacity of 1 and a service time of 3.2 with a standard * deviation of 0.6. - * The terminal node is connected to the queue node with a probability of 1.0. * * @return the first example network */ public static Net getNet1() { - var exp0_22 = new Distribution.Exponential(1.0 / 4.5); var norm3_2 = new Distribution.NormalBoxMuller(3.2, 0.6); - var spawn = 10000; - return getNet1(spawn, exp0_22, norm3_2); + return getNet1("Queue", norm3_2); } /** * Return the first example network. * The net is composed of a terminal node and a queue node. * The terminal node is connected to the queue node. + * The terminal node generates 10000 jobs with an exponential distribution 4.5. * - * @param spawn the number of jobs to generate - * @param source the distribution of the source node - * @param queue the distribution of the queue node + * @param queue the distribution of the queue node * @return the first example network */ - public static Net getNet1(int spawn, Distribution source, Distribution queue) { + public static Net getNet1(String name, Distribution queue) { + var spawn = 10000; + var source = new Distribution.Exponential(1.0 / 4.5); + var net1 = new Net(); net1.addNode(ServerNode.Builder.terminal("Source", spawn, source)); - net1.addNode(ServerNode.Builder.queue("Queue", 1, queue)); + net1.addNode(ServerNode.Builder.queue(name, 1, queue)); net1.addConnection(0, 1, 1.0); return net1; } diff --git a/src/main/java/net/berack/upo/valpre/Plot.java b/src/main/java/net/berack/upo/valpre/Plot.java index 7f1d696..15c815c 100644 --- a/src/main/java/net/berack/upo/valpre/Plot.java +++ b/src/main/java/net/berack/upo/valpre/Plot.java @@ -44,7 +44,7 @@ public class Plot { var results = new CsvResult(csv).loadResults(); this.summary = new Result.Summary(results); - var nodes = this.summary.getNodes().toArray(new String[0]); + var nodes = this.summary.getNodes(); this.panelBarChart = new ChartPanel(null); this.nodeComboBox = new JComboBox<>(nodes); 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 c811875..c9a708e 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 @@ -1,6 +1,7 @@ package net.berack.upo.valpre.sim.stats; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -36,6 +37,11 @@ public class Result implements Iterable> { this.stats = stats; } + /** + * Gets the stats of a node. + * + * @return the stats of a node + */ public NodeStats getStat(String node) { for (var i = 0; i < this.nodes.length; i++) if (this.nodes[i].equals(node)) @@ -45,7 +51,7 @@ public class Result implements Iterable> { @Override public String toString() { - return buildPrintable(this.seed, this.simulationTime, this.timeElapsedMS, this.nodes, this.stats); + return getResultString(this.seed, this.simulationTime, this.timeElapsedMS, this.nodes, this.stats); } @Override @@ -80,9 +86,8 @@ public class Result implements Iterable> { * @param stats the stats of each node * @return a string representation of the result */ - private static String buildPrintable(long seed, double simTime, double timeMS, String[] nodes, NodeStats[] stats) { + public static String getResultString(long seed, double simTime, double timeMS, String[] nodes, NodeStats[] stats) { var size = (int) Math.ceil(Math.max(Math.log10(simTime), 1)); - var iFormat = "%" + size + ".0f"; var fFormat = "%" + (size + 4) + ".3f"; var builder = new StringBuilder(); @@ -90,6 +95,26 @@ public class Result implements Iterable> { builder.append(String.format("Seed: \t%d\n", seed)); builder.append(String.format("Simulation: \t" + fFormat + "\n", simTime)); builder.append(String.format("Elapsed: \t" + fFormat + "ms\n", timeMS)); + builder.append(getResultString(nodes, stats)); + return builder.toString(); + } + + /** + * Create a string representation of the result. It only display the stats of + * each node in a table format. + * + * @param nodes the names of the nodes + * @param stats the stats of each node + * @return a string representation of the result + * @throws AssertionError if the nodes and stats do not match + */ + public static String getResultString(String[] nodes, NodeStats[] stats) { + assert nodes.length == stats.length; + + var size = (int) Math.ceil(Math.max(Math.log10(stats[0].lastEventTime), 1)); + var iFormat = "%" + size + ".0f"; + var fFormat = "%" + (size + 4) + ".3f"; + var builder = new StringBuilder(); var table = new ConsoleTable("Node", "Departures", "Avg Queue", "Avg Wait", "Avg Response", "Throughput", "Utilization %", "Unavailable %", "Last Event"); @@ -206,12 +231,24 @@ public class Result implements Iterable> { } /** - * Gets the nodes of the summary. + * Gets a copy of the nodes of the summary. * * @return the nodes of the summary */ - public List getNodes() { - return List.of(this.nodes); + public String[] getNodes() { + return Arrays.copyOf(this.nodes, this.nodes.length); + } + + /** + * Gets the statistics of the nodes of the summary. + * + * @return the statistics of the nodes of the summary + */ + public NodeStats[] getStats() { + var stats = new NodeStats[this.nodes.length]; + for (var i = 0; i < this.nodes.length; i++) + stats[i] = this.stats[i].average; + return stats; } /** @@ -239,11 +276,8 @@ public class Result implements Iterable> { @Override public String toString() { - var stats = new NodeStats[this.nodes.length]; - for (var i = 0; i < this.nodes.length; i++) - stats[i] = this.stats[i].average; - - return buildPrintable(this.seed, this.avgSimulationTime, this.avgTimeElapsedMS, this.nodes, stats); + return getResultString(this.seed, this.avgSimulationTime, this.avgTimeElapsedMS, this.nodes, + this.getStats()); } }