From fbc9aeac2c652c347d9677977a6c1ced35f30960 Mon Sep 17 00:00:00 2001 From: Berack96 Date: Fri, 7 Feb 2025 17:33:27 +0100 Subject: [PATCH] Refactor simulation and net example tests to use builder pattern for ServerNode and improve arrival handling logic --- .../upo/valpre/NetBuilderInteractive.java | 4 +- .../net/berack/upo/valpre/sim/ServerNode.java | 196 ++++++++++++------ .../net/berack/upo/valpre/sim/Simulation.java | 6 +- src/main/resources/example1.net | Bin 396 -> 388 bytes src/main/resources/example2.net | Bin 588 -> 580 bytes src/main/resources/example3.net | Bin 487 -> 479 bytes .../upo/valpre/sim/TestSaveExamplesNet.java | 95 +++++++-- .../berack/upo/valpre/sim/TestSimulation.java | 127 ++++++++++-- 8 files changed, 329 insertions(+), 99 deletions(-) diff --git a/src/main/java/net/berack/upo/valpre/NetBuilderInteractive.java b/src/main/java/net/berack/upo/valpre/NetBuilderInteractive.java index d63e753..c510695 100644 --- a/src/main/java/net/berack/upo/valpre/NetBuilderInteractive.java +++ b/src/main/java/net/berack/upo/valpre/NetBuilderInteractive.java @@ -74,12 +74,12 @@ public class NetBuilderInteractive { var limit = ask("Arrivals limit (0 for Int.Max): ", Integer::parseInt, 1); if (limit <= 0) limit = Integer.MAX_VALUE; - yield ServerNode.createLimitedSource(name, distribution, limit); + yield ServerNode.Builder.sourceLimited(name, limit, distribution); } case 2 -> { var servers = ask("Number of servers: ", Integer::parseInt, 1); var unavailable = askDistribution("Unavailable distribution"); - yield ServerNode.createQueue(name, servers, distribution, unavailable); + yield ServerNode.Builder.queue(name, servers, distribution, unavailable); } default -> null; }; diff --git a/src/main/java/net/berack/upo/valpre/sim/ServerNode.java b/src/main/java/net/berack/upo/valpre/sim/ServerNode.java index 9475b65..caa82c4 100644 --- a/src/main/java/net/berack/upo/valpre/sim/ServerNode.java +++ b/src/main/java/net/berack/upo/valpre/sim/ServerNode.java @@ -15,84 +15,36 @@ public class ServerNode { public final Distribution service; public final Distribution unavailable; - /** - * Creates a source node with the given name and distribution. - * It swpawns infinite arrivals (Integer.MAX_VALUE) that are served by infinite - * servers (Integer.MAX_VALUE). - * - * @param name The name of the node. - * @param distribution The distribution of the inter-arrival times. - * @return The created source node. - */ - public static ServerNode createSource(String name, Distribution distribution) { - return new ServerNode(name, Integer.MAX_VALUE, distribution, null, Integer.MAX_VALUE); - } - - /** - * Creates a source node with the given name, distribution, and number of - * arrivals to spawn that are served by infinite servers (Integer.MAX_VALUE). - * - * @param name The name of the node. - * @param service The distribution of the inter-arrival times. - * @param spawnArrivals The number of arrivals to spawn. - * @return The created source node. - */ - public static ServerNode createLimitedSource(String name, Distribution service, int spawnArrivals) { - return new ServerNode(name, Integer.MAX_VALUE, service, null, spawnArrivals); - } - - /** - * Creates a queue node with the given name, maximum number of servers, and - * distribution. - * - * @param name The name of the node. - * @param maxServers The maximum number of servers in the queue. - * @param service The distribution of the service times. - * @return The created queue node. - */ - public static ServerNode createQueue(String name, int maxServers, Distribution service) { - return new ServerNode(name, maxServers, service, null, 0); - } - - /** - * Creates a queue node with the given name, maximum number of servers, and - * distribution. - * - * @param name The name of the node. - * @param maxServers The maximum number of servers in the queue. - * @param service The distribution of the service times. - * @param unavailable The distribution of the unavailable times after service. - * @return The created queue node. - */ - public static ServerNode createQueue(String name, int maxServers, Distribution service, Distribution unavailable) { - return new ServerNode(name, maxServers, service, unavailable, 0); - } - /** * Creates a generic node with the given name and distribution. * The servers number must be 1 or higher; if lower will be put to 1. * The spawn number must be 0 or higher; if lower will be put to 0. - * The distribution can't be null, otherwise an exception is thrown. + * The queue number must be equal or higher than the servers number; if lower + * will be put to the servers number. + * The service distribution can't be null, otherwise an exception is thrown. * - * @param name The name of the node. - * @param maxServers The maximum number of servers in the queue. - * @param service The distribution of the service times. - * @param unavailable The distribution of the unavailable times after service. - * @param spawnArrivals The number of arrivals to spawn. + * @param name The name of the node. + * @param servers The maximum number of servers in the queue. + * @param spawn The number of arrivals to spawn. + * @param queue The maximum number of requests in the queue. + * @param service The distribution of the service times. + * @param unavailable The distribution of the unavailable times after service. * @throws NullPointerException if the distribution is null */ - private ServerNode(String name, int maxServers, Distribution service, Distribution unavailable, int spawnArrivals) { + private ServerNode(String name, int servers, int spawn, int queue, Distribution service, Distribution unavailable) { if (service == null) throw new NullPointerException("Service distribution can't be null"); - if (maxServers <= 0) - maxServers = 1; - if (spawnArrivals < 0) - spawnArrivals = 0; + if (servers <= 0) + servers = 1; + if (spawn < 0) + spawn = 0; + if (queue < servers) + queue = servers; this.name = name; - this.maxQueue = 100; // TODO change to runtime - this.maxServers = maxServers; - this.spawnArrivals = spawnArrivals; + this.maxQueue = queue; + this.maxServers = servers; + this.spawnArrivals = spawn; this.service = service; this.unavailable = unavailable; } @@ -131,4 +83,114 @@ public class ServerNode { public int hashCode() { return this.name.hashCode(); } + + /** + * Creates a new builder for the node. + * It is useful to create a node with a more readable syntax and a in a more + * flexible way. + */ + public static class Builder { + private String name; + private int maxQueue; + private int maxServers; + private int spawnArrivals; + private Distribution service; + private Distribution unavailable; + + /** + * Creates a new builder for the node with the given name and distribution. + * The maximum number of servers is set to 1, the maximum number of requests in + * the queue is set to 100, the number of arrivals to spawn is set to 0, and + * the unavailable time is set to null. + * + * @param name The name of the node. + * @param service The distribution of the service times. + * @return The created sink node. + */ + public Builder(String name, Distribution service) { + this.name = name; + this.service = service; + this.maxQueue = 100; // default value + this.maxServers = 1; + this.spawnArrivals = 0; + this.unavailable = null; + } + + public Builder queue(int maxQueue) { + this.maxQueue = maxQueue; + return this; + } + + public Builder servers(int maxServers) { + this.maxServers = maxServers; + return this; + } + + public Builder spawn(int spawnArrivals) { + this.spawnArrivals = spawnArrivals; + return this; + } + + public Builder unavailable(Distribution unavailable) { + this.unavailable = unavailable; + return this; + } + + public ServerNode build() { + return new ServerNode(name, maxServers, spawnArrivals, maxQueue, service, unavailable); + } + + /** + * Creates a source node with the given name and distribution. + * It swpawns infinite arrivals (Integer.MAX_VALUE) that are served by infinite + * servers (Integer.MAX_VALUE). + * + * @param name The name of the node. + * @param distribution The distribution of the inter-arrival times. + * @return The created source node. + */ + public static ServerNode source(String name, Distribution distribution) { + return new Builder(name, distribution).spawn(Integer.MAX_VALUE).build(); + } + + /** + * Creates a source node with the given name, distribution, and number of + * arrivals to spawn that are served by infinite servers (Integer.MAX_VALUE). + * + * @param name The name of the node. + * @param service The distribution of the inter-arrival times. + * @param spawnArrivals The number of arrivals to spawn. + * @return The created source node. + */ + public static ServerNode sourceLimited(String name, int spawnArrivals, Distribution service) { + return new Builder(name, service).spawn(spawnArrivals).build(); + } + + /** + * Creates a queue node with the given name, maximum number of servers, and + * distribution. + * + * @param name The name of the node. + * @param maxServers The maximum number of servers in the queue. + * @param service The distribution of the service times. + * @return The created queue node. + */ + public static ServerNode queue(String name, int maxServers, Distribution service) { + return new Builder(name, service).servers(maxServers).build(); + } + + /** + * Creates a queue node with the given name, maximum number of servers, and + * distribution. + * + * @param name The name of the node. + * @param maxServers The maximum number of servers in the queue. + * @param service The distribution of the service times. + * @param unavailable The distribution of the unavailable times after service. + * @return The created queue node. + */ + public static ServerNode queue(String name, int maxServers, Distribution service, Distribution unavailable) { + return new Builder(name, service).unavailable(unavailable).servers(maxServers).build(); + } + } } diff --git a/src/main/java/net/berack/upo/valpre/sim/Simulation.java b/src/main/java/net/berack/upo/valpre/sim/Simulation.java index b1b3a61..40b2e50 100644 --- a/src/main/java/net/berack/upo/valpre/sim/Simulation.java +++ b/src/main/java/net/berack/upo/valpre/sim/Simulation.java @@ -97,8 +97,12 @@ public final class Simulation { this.addToFel(state.spawnUnavailableIfPossible(time, this.rng)); this.addToFel(state.spawnDepartureIfPossible(time, this.rng)); - this.addToFel(state.spawnArrivalToChild(time, this.rng)); this.addToFel(state.spawnArrivalIfPossilbe(time)); + + // Spawn arrival to child node if queue is not full otherwise drop + var ev = state.spawnArrivalToChild(time, this.rng); + if (ev != null && !this.states[ev.nodeIndex].isQueueFull()) + this.addToFel(ev); } } } diff --git a/src/main/resources/example1.net b/src/main/resources/example1.net index bd6b8bc80535ecd5af1baaefcaabe818cef506fa..52d954e3fe6912461d8b40f210efcf09a5a83d31 100644 GIT binary patch delta 19 ZcmeBSZeiZQ$jHbvnT;_JNX9T4001fj1KI!p delta 27 dcmZo+?qS}*$jJKd|NsB|lbIL;p{x)_0|20_3+4a- diff --git a/src/main/resources/example2.net b/src/main/resources/example2.net index e2139846d7d7266b878c36bb23f6ee8082cfe797..b7dc9d3823834ba88430d8b3083087edd2ef2e81 100644 GIT binary patch delta 19 ZcmX@Za)f0=D