Add maxQueue to ServerNode, refactor Event to use node index, and implement buildNodeStates method in Net
This commit is contained in:
@@ -6,7 +6,7 @@ package net.berack.upo.valpre.sim;
|
||||
public class Event implements Comparable<Event> {
|
||||
public final double time;
|
||||
public final Type type;
|
||||
public final ServerNode node;
|
||||
public final int nodeIndex;
|
||||
|
||||
/**
|
||||
* Create a new event.
|
||||
@@ -15,10 +15,10 @@ public class Event implements Comparable<Event> {
|
||||
* @param node The node that the event is associated with.
|
||||
* @param time The time at which the event occurs.
|
||||
*/
|
||||
private Event(Type type, ServerNode node, double time) {
|
||||
private Event(Type type, int node, double time) {
|
||||
this.type = type;
|
||||
this.time = time;
|
||||
this.node = node;
|
||||
this.nodeIndex = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,7 +37,7 @@ public class Event implements Comparable<Event> {
|
||||
* @param time The time at which the event occurs.
|
||||
* @return The new event.
|
||||
*/
|
||||
public static Event newArrival(ServerNode node, double time) {
|
||||
public static Event newArrival(int node, double time) {
|
||||
return new Event(Type.ARRIVAL, node, time);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class Event implements Comparable<Event> {
|
||||
* @param time The time at which the event occurs.
|
||||
* @return The new event.
|
||||
*/
|
||||
public static Event newDeparture(ServerNode node, double time) {
|
||||
public static Event newDeparture(int node, double time) {
|
||||
return new Event(Type.DEPARTURE, node, time);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class Event implements Comparable<Event> {
|
||||
* @param time The time at which the event occurs.
|
||||
* @return The new event.
|
||||
*/
|
||||
public static Event newAvailable(ServerNode node, double time) {
|
||||
public static Event newAvailable(int node, double time) {
|
||||
return new Event(Type.AVAILABLE, node, time);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ public final class Net implements Iterable<ServerNode> {
|
||||
* @param weight The probability of the child node.
|
||||
* @throws IndexOutOfBoundsException if one of the two nodes are not in the net
|
||||
* @throws IllegalArgumentException if the weight is negative or zero
|
||||
* @throws IllegalArgumentException if the child is a source node
|
||||
*/
|
||||
public void addConnection(int parent, int child, double weight) {
|
||||
if (weight <= 0)
|
||||
@@ -86,6 +87,9 @@ public final class Net implements Iterable<ServerNode> {
|
||||
if (parent < 0 || child < 0 || parent > max || child > max)
|
||||
throw new IndexOutOfBoundsException("One of the nodes does not exist");
|
||||
|
||||
if (this.servers.get(child).spawnArrivals > 0)
|
||||
throw new IllegalArgumentException("Can't connect to a source node");
|
||||
|
||||
var list = this.connections.get(parent);
|
||||
for (var conn : list) {
|
||||
if (conn.index == child) {
|
||||
@@ -136,6 +140,7 @@ public final class Net implements Iterable<ServerNode> {
|
||||
*
|
||||
* @param index the index of the node
|
||||
* @return the node
|
||||
* @throws IndexOutOfBoundsException if the index is not in the range
|
||||
*/
|
||||
public ServerNode getNode(int index) {
|
||||
return this.servers.get(index);
|
||||
@@ -151,28 +156,28 @@ public final class Net implements Iterable<ServerNode> {
|
||||
*/
|
||||
public ServerNode getChildOf(ServerNode parent, Rng rng) {
|
||||
var index = this.indices.get(parent);
|
||||
return this.getChildOf(index, rng);
|
||||
index = this.getChildOf(index, rng);
|
||||
return index < 0 ? null : this.servers.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one of the child nodes from the parent specified. If the index is out of
|
||||
* bounds then an exception is thrown. If the node has no child then null is
|
||||
* returned;
|
||||
* bounds then an exception is thrown. If the node has no child then -1 is
|
||||
* returned.
|
||||
*
|
||||
* @param parent the parent node
|
||||
* @param rng the random number generator used for getting one of the child
|
||||
* @throws IndexOutOfBoundsException If the index is not in the range
|
||||
* @return the resultig node
|
||||
*/
|
||||
public ServerNode getChildOf(int parent, Rng rng) {
|
||||
public int getChildOf(int parent, Rng rng) {
|
||||
var random = rng.random();
|
||||
for (var conn : this.connections.get(parent)) {
|
||||
random -= conn.weight;
|
||||
if (random <= 0) {
|
||||
return this.servers.get(conn.index);
|
||||
}
|
||||
if (random <= 0)
|
||||
return conn.index;
|
||||
}
|
||||
return null;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,6 +226,20 @@ public final class Net implements Iterable<ServerNode> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the node states for the simulation.
|
||||
* This method is used to create the state of each node in the network.
|
||||
* Note that each call to this method will create a new state for each node.
|
||||
*
|
||||
* @return the array of node states
|
||||
*/
|
||||
public ServerNodeState[] buildNodeStates() {
|
||||
var states = new ServerNodeState[this.servers.size()];
|
||||
for (var i = 0; i < states.length; i++)
|
||||
states[i] = new ServerNodeState(i, this);
|
||||
return states;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current net to a file.
|
||||
* The resulting file is saved with Kryo.
|
||||
@@ -237,6 +256,11 @@ public final class Net implements Iterable<ServerNode> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ServerNode> iterator() {
|
||||
return this.servers.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the net from the file passed as input.
|
||||
* The net will be the same as the one saved.
|
||||
@@ -295,9 +319,4 @@ public final class Net implements Iterable<ServerNode> {
|
||||
this.weight = weight;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ServerNode> iterator() {
|
||||
return this.servers.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.berack.upo.valpre.rand.Rng;
|
||||
*/
|
||||
public class ServerNode {
|
||||
public final String name;
|
||||
public final int maxQueue;
|
||||
public final int maxServers;
|
||||
public final int spawnArrivals;
|
||||
public final Distribution service;
|
||||
@@ -89,6 +90,7 @@ public class ServerNode {
|
||||
spawnArrivals = 0;
|
||||
|
||||
this.name = name;
|
||||
this.maxQueue = 100; // TODO change to runtime
|
||||
this.maxServers = maxServers;
|
||||
this.spawnArrivals = spawnArrivals;
|
||||
this.service = service;
|
||||
@@ -117,17 +119,6 @@ public class ServerNode {
|
||||
return Distribution.getPositiveSample(this.unavailable, rng);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the node should spawn an arrival based on the number of
|
||||
* arrivals.
|
||||
*
|
||||
* @param numArrivals The number of arrivals to check against.
|
||||
* @return True if the node should spawn an arrival, false otherwise.
|
||||
*/
|
||||
public boolean shouldSpawnArrival(double numArrivals) {
|
||||
return this.spawnArrivals > Math.max(0, numArrivals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ServerNode))
|
||||
|
||||
174
src/main/java/net/berack/upo/valpre/sim/ServerNodeState.java
Normal file
174
src/main/java/net/berack/upo/valpre/sim/ServerNodeState.java
Normal file
@@ -0,0 +1,174 @@
|
||||
package net.berack.upo.valpre.sim;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
import net.berack.upo.valpre.rand.Rng;
|
||||
import net.berack.upo.valpre.sim.stats.NodeStats;
|
||||
|
||||
/**
|
||||
* Represents a summary of the state of a server node in the network.
|
||||
* It is used by the simulation to track the number of arrivals and departures,
|
||||
* the maximum queue length, the busy time, and the response time.
|
||||
* It also has a connection to the node and the net where it is.
|
||||
*/
|
||||
public class ServerNodeState {
|
||||
public int numServerBusy = 0;
|
||||
public int numServerUnavailable = 0;
|
||||
public final ArrayDeque<Double> queue = new ArrayDeque<>();
|
||||
|
||||
public final int index;
|
||||
public final Net net;
|
||||
public final ServerNode node;
|
||||
public final NodeStats stats = new NodeStats();
|
||||
|
||||
/**
|
||||
* Create a new node state based on the index and the net passed as input
|
||||
*
|
||||
* @param index the index of the node
|
||||
* @param net the net where the node is
|
||||
*/
|
||||
ServerNodeState(int index, Net net) {
|
||||
this.index = index;
|
||||
this.net = net;
|
||||
this.node = net.getNode(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the queue is full based on the maximum queue length of the node
|
||||
*
|
||||
* @return true if the queue is full
|
||||
*/
|
||||
public boolean isQueueFull() {
|
||||
return this.queue.size() >= this.node.maxQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the node can serve a new request based on the number of servers
|
||||
*
|
||||
* @return true if the node can serve
|
||||
*/
|
||||
public boolean canServe() {
|
||||
return this.node.maxServers > this.numServerBusy + this.numServerUnavailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the node has requests to serve based on the number of busy servers
|
||||
*
|
||||
* @return true if the node has requests
|
||||
*/
|
||||
public boolean hasRequests() {
|
||||
return this.queue.size() > this.numServerBusy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the node should spawn an arrival based on the number of
|
||||
* arrivals.
|
||||
*
|
||||
* @return True if the node should spawn an arrival, false otherwise.
|
||||
*/
|
||||
public boolean shouldSpawnArrival() {
|
||||
return this.node.spawnArrivals > this.stats.numArrivals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update stats and queue when an unavailability event finish. The
|
||||
* unavailability
|
||||
* time is the time of the event.
|
||||
*
|
||||
* @param time the time of the event
|
||||
*/
|
||||
public void updateAvailable(double time) {
|
||||
this.stats.updateTimes(time, this.numServerBusy, this.numServerUnavailable, this.node.maxServers);
|
||||
this.numServerUnavailable--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update stats and queue when an arrival event occurs. The arrival time is the
|
||||
* time of the event.
|
||||
*
|
||||
* @param time the time of the event
|
||||
*/
|
||||
public void updateArrival(double time) {
|
||||
this.queue.add(time);
|
||||
this.stats.updateArrival(time, this.queue.size());
|
||||
this.stats.updateTimes(time, this.numServerBusy, this.numServerUnavailable, node.maxServers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update stats and queue when a departure event occurs. The departure time is
|
||||
* the time of the event.
|
||||
*
|
||||
* @param time the time of the event
|
||||
*/
|
||||
public void updateDeparture(double time) {
|
||||
var arrivalTime = this.queue.poll();
|
||||
this.stats.updateDeparture(time, arrivalTime);
|
||||
this.stats.updateTimes(time, this.numServerBusy, this.numServerUnavailable, node.maxServers);
|
||||
this.numServerBusy--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an arrival event based on the node and the time passed as input
|
||||
*
|
||||
* @param time the time of the event
|
||||
* @return the arrival event
|
||||
*/
|
||||
public Event spawnArrivalIfPossilbe(double time) {
|
||||
if (this.shouldSpawnArrival())
|
||||
return Event.newArrival(this.index, time);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a departure event if the node can serve and has requests. The event is
|
||||
* created based on the node and the delay is determined by the node's service
|
||||
* time distribution.
|
||||
*
|
||||
* @param time the time of the event
|
||||
* @param rng the random number generator
|
||||
* @return the departure event if the node can serve and has requests, null
|
||||
* otherwise
|
||||
*/
|
||||
public Event spawnDepartureIfPossible(double time, Rng rng) {
|
||||
if (this.canServe() && this.hasRequests()) {
|
||||
this.numServerBusy++;
|
||||
var delay = node.getServiceTime(rng);
|
||||
return Event.newDeparture(this.index, time + delay);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an unavailable event if the node is unavailable. The event is created
|
||||
* based on the given node, and the delay is determined by the node's
|
||||
* unavailability distribution.
|
||||
*
|
||||
* @param time The time of the event
|
||||
* @param rng The random number generator
|
||||
* @return The event if the node is unavailable, null otherwise
|
||||
*/
|
||||
public Event spawnUnavailableIfPossible(double time, Rng rng) {
|
||||
var delay = node.getUnavailableTime(rng);
|
||||
if (delay > 0) {
|
||||
this.numServerUnavailable++;
|
||||
return Event.newAvailable(this.index, time + delay);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an arrival event to a child node based on the node and the time passed
|
||||
* as input
|
||||
*
|
||||
* @param time the time of the event
|
||||
* @param rng the random number generator
|
||||
* @return the arrival event to a child node if the node has children, null
|
||||
* otherwise
|
||||
*/
|
||||
public Event spawnArrivalToChild(double time, Rng rng) {
|
||||
var childIndex = this.net.getChildOf(this.index, rng);
|
||||
if (childIndex >= 0)
|
||||
return Event.newArrival(childIndex, time);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
package net.berack.upo.valpre.sim;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
import net.berack.upo.valpre.rand.Rng;
|
||||
@@ -20,8 +18,7 @@ public final class Simulation {
|
||||
public final EndCriteria[] criterias;
|
||||
public final long seed;
|
||||
|
||||
private final Net net;
|
||||
private final Map<String, NodeState> states;
|
||||
private final ServerNodeState[] states;
|
||||
private final PriorityQueue<Event> fel;
|
||||
private double time = 0.0d;
|
||||
private long eventProcessed = 0;
|
||||
@@ -36,23 +33,22 @@ public final class Simulation {
|
||||
*/
|
||||
public Simulation(Net net, Rng rng, EndCriteria... criterias) {
|
||||
this.timeStartedNano = System.nanoTime();
|
||||
this.net = net;
|
||||
this.states = new HashMap<>();
|
||||
this.states = net.buildNodeStates();
|
||||
this.fel = new PriorityQueue<>();
|
||||
this.criterias = criterias;
|
||||
this.seed = rng.getSeed();
|
||||
this.rng = rng;
|
||||
|
||||
boolean hasLimit = false;
|
||||
for (var node : net) {
|
||||
for (var state : this.states) {
|
||||
var node = state.node;
|
||||
|
||||
// check for ending criteria in simulation
|
||||
if (node.spawnArrivals != Integer.MAX_VALUE)
|
||||
hasLimit = true;
|
||||
|
||||
// Initial arrivals (if spawned)
|
||||
this.states.put(node.name, new NodeState());
|
||||
if (node.shouldSpawnArrival(0))
|
||||
this.addArrival(node);
|
||||
this.addToFel(state.spawnArrivalIfPossilbe(0.0d));
|
||||
}
|
||||
|
||||
if (!hasLimit && (criterias == null || criterias.length == 0))
|
||||
@@ -83,38 +79,26 @@ public final class Simulation {
|
||||
if (event == null)
|
||||
throw new NullPointerException("No more events to process!");
|
||||
|
||||
var node = event.node;
|
||||
var state = this.states.get(node.name);
|
||||
var state = this.states[event.nodeIndex];
|
||||
this.time = event.time;
|
||||
this.eventProcessed += 1;
|
||||
|
||||
switch (event.type) {
|
||||
case AVAILABLE -> {
|
||||
state.stats.updateTimes(this.time, state.numServerBusy, state.numServerUnavailable, node.maxServers);
|
||||
state.numServerUnavailable--;
|
||||
this.addDepartureIfPossible(node, state);
|
||||
state.updateAvailable(time);
|
||||
this.addToFel(state.spawnDepartureIfPossible(time, this.rng));
|
||||
}
|
||||
case ARRIVAL -> {
|
||||
state.queue.add(this.time);
|
||||
state.stats.updateArrival(this.time, state.queue.size());
|
||||
state.stats.updateTimes(this.time, state.numServerBusy, state.numServerUnavailable, node.maxServers);
|
||||
this.addDepartureIfPossible(node, state);
|
||||
state.updateArrival(time);
|
||||
this.addToFel(state.spawnDepartureIfPossible(time, this.rng));
|
||||
}
|
||||
case DEPARTURE -> {
|
||||
var arrivalTime = state.queue.poll();
|
||||
state.stats.updateDeparture(this.time, arrivalTime);
|
||||
state.stats.updateTimes(this.time, state.numServerBusy, state.numServerUnavailable, node.maxServers);
|
||||
state.numServerBusy--;
|
||||
state.updateDeparture(time);
|
||||
|
||||
this.addUnavailableIfPossible(node, state);
|
||||
this.addDepartureIfPossible(node, state);
|
||||
|
||||
var next = this.net.getChildOf(node, this.rng);
|
||||
if (next != null)
|
||||
this.addArrival(next);
|
||||
|
||||
if (node.shouldSpawnArrival(state.stats.numArrivals))
|
||||
this.addArrival(node);
|
||||
this.addToFel(state.spawnUnavailableIfPossible(time, this.rng));
|
||||
this.addToFel(state.spawnDepartureIfPossible(time, this.rng));
|
||||
this.addToFel(state.spawnArrivalToChild(time, rng));
|
||||
this.addToFel(state.spawnArrivalIfPossilbe(time));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,8 +111,8 @@ public final class Simulation {
|
||||
public Result endSimulation() {
|
||||
var elapsed = System.nanoTime() - this.timeStartedNano;
|
||||
var nodes = new HashMap<String, NodeStats>();
|
||||
for (var entry : this.states.entrySet())
|
||||
nodes.put(entry.getKey(), entry.getValue().stats);
|
||||
for (var state : this.states)
|
||||
nodes.put(state.node.name, state.stats);
|
||||
|
||||
return new Result(this.seed, this.time, elapsed * 1e-6, nodes);
|
||||
}
|
||||
@@ -166,9 +150,10 @@ public final class Simulation {
|
||||
*
|
||||
* @param node the name of the node
|
||||
* @return the node
|
||||
* @throws NullPointerException if the node does not exist.
|
||||
*/
|
||||
public ServerNode getNode(String node) {
|
||||
return this.net.getNode(node);
|
||||
return this.getNodeState(node).node;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,55 +161,26 @@ public final class Simulation {
|
||||
*
|
||||
* @param node the name of the node
|
||||
* @return the current state of the node
|
||||
* @throws NullPointerException if the node does not exist.
|
||||
*/
|
||||
public NodeState getNodeState(String node) {
|
||||
return this.states.get(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an arrival event to the future event list. The event is created based
|
||||
* on the given node, and no delay is added.
|
||||
*
|
||||
* @param node The node to create the event for.
|
||||
*/
|
||||
public void addArrival(ServerNode node) {
|
||||
var event = Event.newArrival(node, this.time);
|
||||
fel.add(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a departure event to the future event list. The event is created based
|
||||
* on the given node, and the delay is determined by the node's service
|
||||
* distribution.
|
||||
*
|
||||
* @param node The node to create the event for.
|
||||
* @param state The current state of the node
|
||||
*/
|
||||
public void addDepartureIfPossible(ServerNode node, NodeState state) {
|
||||
var canServe = node.maxServers > state.numServerBusy + state.numServerUnavailable;
|
||||
var hasRequests = state.queue.size() > state.numServerBusy;
|
||||
|
||||
if (canServe && hasRequests) {
|
||||
state.numServerBusy++;
|
||||
var delay = node.getServiceTime(this.rng);
|
||||
var event = Event.newDeparture(node, this.time + delay);
|
||||
fel.add(event);
|
||||
public ServerNodeState getNodeState(String node) {
|
||||
for (var state : this.states) {
|
||||
if (state.node.name.equals(node))
|
||||
return state;
|
||||
}
|
||||
|
||||
throw new NullPointerException("Node not found: " + node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an AVAILABLE event in the case that the node has an unavailability time.
|
||||
* Add an arrival event to the future event list if the event is not null,
|
||||
* otherwise do nothing.
|
||||
*
|
||||
* @param node The node to create the event for
|
||||
* @param state The current state of the node
|
||||
* @param e the event to add
|
||||
*/
|
||||
public void addUnavailableIfPossible(ServerNode node, NodeState state) {
|
||||
var delay = node.getUnavailableTime(rng);
|
||||
if (delay > 0) {
|
||||
state.numServerUnavailable++;
|
||||
var event = Event.newAvailable(node, time + delay);
|
||||
this.fel.add(event);
|
||||
}
|
||||
public void addToFel(Event e) {
|
||||
if (e != null)
|
||||
this.fel.add(e);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,16 +199,4 @@ public final class Simulation {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a summary of the state of a server node in the network.
|
||||
* It is used by the simulation to track the number of arrivals and departures,
|
||||
* the maximum queue length, the busy time, and the response time.
|
||||
*/
|
||||
public static class NodeState {
|
||||
public int numServerBusy = 0;
|
||||
public int numServerUnavailable = 0;
|
||||
public final NodeStats stats = new NodeStats();
|
||||
public final ArrayDeque<Double> queue = new ArrayDeque<>();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,61 @@
|
||||
package net.berack.upo.valpre.sim;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.esotericsoftware.kryo.KryoException;
|
||||
|
||||
import net.berack.upo.valpre.rand.Distribution;
|
||||
|
||||
public class TestSaveExamplesNet {
|
||||
|
||||
private static final Distribution exp0_22 = new Distribution.Exponential(1.0 / 4.5);
|
||||
private static final Distribution exp2 = new Distribution.Exponential(2.0);
|
||||
private static final Distribution exp1_5 = new Distribution.Exponential(1.5);
|
||||
private static final Distribution exp3_5 = new Distribution.Exponential(3.5);
|
||||
private static final Distribution exp10 = new Distribution.Exponential(10.0);
|
||||
|
||||
private static final Distribution norm3_2 = new Distribution.NormalBoxMuller(3.2, 0.6);
|
||||
private static final Distribution norm4_2 = new Distribution.NormalBoxMuller(4.2, 0.6);
|
||||
|
||||
private static final Distribution unNorm = new Distribution.UnavailableTime(0.2, norm4_2);
|
||||
private static final Distribution unExp = new Distribution.UnavailableTime(0.1, exp10);
|
||||
|
||||
@Test
|
||||
public void testSaveExample1() throws KryoException, IOException {
|
||||
var net = new Net();
|
||||
net.addNode(ServerNode.createLimitedSource("Source", exp0_22, 1000));
|
||||
net.addNode(ServerNode.createQueue("Queue", 1, norm3_2));
|
||||
net.addConnection(0, 1, 1.0);
|
||||
|
||||
net.save("src/main/resources/example1.net");
|
||||
net = Net.load("src/main/resources/example1.net");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveExample2() throws KryoException, IOException {
|
||||
var net = new Net();
|
||||
net.addNode(ServerNode.createLimitedSource("Source", exp0_22, 1000));
|
||||
net.addNode(ServerNode.createQueue("Queue", 1, norm3_2));
|
||||
net.addNode(ServerNode.createQueue("Queue Wait", 1, norm3_2, unNorm));
|
||||
net.addConnection(0, 1, 1.0);
|
||||
net.addConnection(1, 2, 1.0);
|
||||
|
||||
net.save("src/main/resources/example2.net");
|
||||
net = Net.load("src/main/resources/example2.net");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveExample3() throws KryoException, IOException {
|
||||
var net = new Net();
|
||||
net.addNode(ServerNode.createLimitedSource("Source", exp1_5, 1000));
|
||||
net.addNode(ServerNode.createQueue("Service1", 1, exp2));
|
||||
net.addNode(ServerNode.createQueue("Service2", 1, exp3_5, unExp));
|
||||
net.addConnection(0, 1, 1.0);
|
||||
net.addConnection(1, 2, 1.0);
|
||||
|
||||
net.save("src/main/resources/example3.net");
|
||||
net = Net.load("src/main/resources/example3.net");
|
||||
}
|
||||
}
|
||||
@@ -42,61 +42,42 @@ public class TestSimulation {
|
||||
var node = ServerNode.createQueue("Nodo", 0, const1);
|
||||
assertEquals("Nodo", node.name);
|
||||
assertEquals(1, node.maxServers);
|
||||
assertFalse(node.shouldSpawnArrival(0));
|
||||
assertFalse(node.shouldSpawnArrival(50));
|
||||
assertFalse(node.shouldSpawnArrival(1000));
|
||||
assertFalse(node.shouldSpawnArrival(Integer.MAX_VALUE));
|
||||
assertFalse(node.shouldSpawnArrival(-1));
|
||||
assertEquals(0, node.spawnArrivals);
|
||||
assertEquals(1.0, node.getServiceTime(null), DELTA);
|
||||
|
||||
node = ServerNode.createQueue("Queue", 50, const1);
|
||||
assertEquals("Queue", node.name);
|
||||
assertEquals(50, node.maxServers);
|
||||
assertFalse(node.shouldSpawnArrival(0));
|
||||
assertFalse(node.shouldSpawnArrival(50));
|
||||
assertFalse(node.shouldSpawnArrival(1000));
|
||||
assertFalse(node.shouldSpawnArrival(Integer.MAX_VALUE));
|
||||
assertFalse(node.shouldSpawnArrival(-1));
|
||||
assertEquals(0, node.spawnArrivals);
|
||||
assertEquals(1.0, node.getServiceTime(null), DELTA);
|
||||
|
||||
node = ServerNode.createSource("Source", const1);
|
||||
assertEquals("Source", node.name);
|
||||
assertEquals(Integer.MAX_VALUE, node.maxServers);
|
||||
assertTrue(node.shouldSpawnArrival(0));
|
||||
assertTrue(node.shouldSpawnArrival(50));
|
||||
assertTrue(node.shouldSpawnArrival(1000));
|
||||
assertTrue(node.shouldSpawnArrival(Integer.MAX_VALUE - 1));
|
||||
assertFalse(node.shouldSpawnArrival(Integer.MAX_VALUE));
|
||||
assertTrue(node.shouldSpawnArrival(-1));
|
||||
assertEquals(Integer.MAX_VALUE, node.spawnArrivals);
|
||||
assertEquals(1.0, node.getServiceTime(null), DELTA);
|
||||
|
||||
node = ServerNode.createLimitedSource("Source", const1, 50);
|
||||
assertEquals("Source", node.name);
|
||||
assertEquals(Integer.MAX_VALUE, node.maxServers);
|
||||
assertTrue(node.shouldSpawnArrival(0));
|
||||
assertTrue(node.shouldSpawnArrival(49));
|
||||
assertFalse(node.shouldSpawnArrival(50));
|
||||
assertFalse(node.shouldSpawnArrival(1000));
|
||||
assertFalse(node.shouldSpawnArrival(Integer.MAX_VALUE));
|
||||
assertTrue(node.shouldSpawnArrival(-1));
|
||||
assertEquals(50, node.spawnArrivals);
|
||||
assertEquals(1.0, node.getServiceTime(null), DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void event() {
|
||||
var node = ServerNode.createSource("Source", const0);
|
||||
var event = Event.newAvailable(node, 1.0);
|
||||
assertEquals(node, event.node);
|
||||
var event = Event.newAvailable(0, 1.0);
|
||||
assertEquals(0, event.nodeIndex);
|
||||
assertEquals(1.0, event.time, 0.000000000001);
|
||||
assertEquals(Event.Type.AVAILABLE, event.type);
|
||||
|
||||
var event2 = Event.newArrival(node, 5.0);
|
||||
assertEquals(node, event2.node);
|
||||
var event2 = Event.newArrival(0, 5.0);
|
||||
assertEquals(0, event2.nodeIndex);
|
||||
assertEquals(5.0, event2.time, 0.000000000001);
|
||||
assertEquals(Event.Type.ARRIVAL, event2.type);
|
||||
|
||||
var event3 = Event.newDeparture(node, 8.0);
|
||||
assertEquals(node, event3.node);
|
||||
var event3 = Event.newDeparture(1, 8.0);
|
||||
assertEquals(1, event3.nodeIndex);
|
||||
assertEquals(8.0, event3.time, 0.000000000001);
|
||||
assertEquals(Event.Type.DEPARTURE, event3.type);
|
||||
|
||||
@@ -170,9 +151,30 @@ public class TestSimulation {
|
||||
assertEquals(0, conn.size());
|
||||
|
||||
var sample = net.getChildOf(0, rigged);
|
||||
assertEquals(node1, sample);
|
||||
sample = net.getChildOf(node, rigged);
|
||||
assertEquals(node1, sample);
|
||||
assertEquals(1, sample);
|
||||
var sample2 = net.getChildOf(node, rigged);
|
||||
assertEquals(node1, sample2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nodeState() {
|
||||
var net = new Net();
|
||||
var node = ServerNode.createQueue("First", 1, const0);
|
||||
net.addNode(node);
|
||||
var state = new ServerNodeState(0, net);
|
||||
|
||||
assertEquals(0, state.index);
|
||||
assertEquals(net, state.net);
|
||||
assertEquals(node, state.node);
|
||||
assertEquals(0, state.numServerBusy);
|
||||
assertEquals(0, state.numServerUnavailable);
|
||||
assertEquals(0, state.queue.size());
|
||||
assertFalse(state.isQueueFull());
|
||||
assertTrue(state.canServe());
|
||||
assertFalse(state.hasRequests());
|
||||
assertFalse(state.shouldSpawnArrival());
|
||||
|
||||
// TODO better test
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -183,7 +185,7 @@ public class TestSimulation {
|
||||
assertTrue(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
|
||||
sim.addArrival(node0);
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
assertFalse(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
sim.processNextEvent(); // Arrival
|
||||
@@ -204,7 +206,7 @@ public class TestSimulation {
|
||||
assertTrue(sim.hasEnded()); // No more events
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
|
||||
sim.addArrival(node0);
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
assertFalse(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
sim.processNextEvent(); // Arrival
|
||||
@@ -225,7 +227,7 @@ public class TestSimulation {
|
||||
assertTrue(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
|
||||
sim.addArrival(node0);
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
assertFalse(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
|
||||
@@ -247,7 +249,7 @@ public class TestSimulation {
|
||||
assertTrue(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
|
||||
sim.addArrival(node0);
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
assertFalse(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
sim.processNextEvent(); // Arrival
|
||||
@@ -264,7 +266,7 @@ public class TestSimulation {
|
||||
assertTrue(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
|
||||
sim.addArrival(node0);
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
assertFalse(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
|
||||
@@ -286,7 +288,7 @@ public class TestSimulation {
|
||||
assertTrue(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
|
||||
sim.addArrival(node0);
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
assertFalse(sim.hasEnded());
|
||||
assertFalse(criteria.shouldEnd(sim));
|
||||
sim.processNextEvent(); // Arrival
|
||||
@@ -321,7 +323,7 @@ public class TestSimulation {
|
||||
var fel = sim.getFutureEventList();
|
||||
assertEquals(0, fel.size());
|
||||
|
||||
sim.addArrival(node0);
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
assertFalse(sim.hasEnded());
|
||||
assertEquals(0, sim.getEventsProcessed());
|
||||
assertEquals(0.0, sim.getTime(), DELTA);
|
||||
@@ -334,7 +336,7 @@ public class TestSimulation {
|
||||
fel = sim.getFutureEventList();
|
||||
assertEquals(1, fel.size());
|
||||
assertEquals(Event.Type.ARRIVAL, fel.get(0).type);
|
||||
assertEquals(node0, fel.get(0).node);
|
||||
assertEquals(0, fel.get(0).nodeIndex);
|
||||
assertEquals(0.0, fel.get(0).time, DELTA);
|
||||
|
||||
sim.processNextEvent(); // Arrival
|
||||
@@ -350,7 +352,7 @@ public class TestSimulation {
|
||||
fel = sim.getFutureEventList();
|
||||
assertEquals(1, fel.size());
|
||||
assertEquals(Event.Type.DEPARTURE, fel.get(0).type);
|
||||
assertEquals(node0, fel.get(0).node);
|
||||
assertEquals(0, fel.get(0).nodeIndex);
|
||||
assertEquals(1.0, fel.get(0).time, DELTA);
|
||||
|
||||
sim.processNextEvent(); // Departure Source
|
||||
@@ -366,7 +368,7 @@ public class TestSimulation {
|
||||
fel = sim.getFutureEventList();
|
||||
assertEquals(1, fel.size());
|
||||
assertEquals(Event.Type.ARRIVAL, fel.get(0).type);
|
||||
assertEquals(node1, fel.get(0).node);
|
||||
assertEquals(1, fel.get(0).nodeIndex);
|
||||
assertEquals(1.0, fel.get(0).time, DELTA);
|
||||
|
||||
sim.processNextEvent(); // Arrival Queue
|
||||
@@ -382,7 +384,7 @@ public class TestSimulation {
|
||||
fel = sim.getFutureEventList();
|
||||
assertEquals(1, fel.size());
|
||||
assertEquals(Event.Type.DEPARTURE, fel.get(0).type);
|
||||
assertEquals(node1, fel.get(0).node);
|
||||
assertEquals(1, fel.get(0).nodeIndex);
|
||||
assertEquals(2.0, fel.get(0).time, DELTA);
|
||||
|
||||
sim.processNextEvent(); // Departure Queue
|
||||
@@ -402,7 +404,7 @@ public class TestSimulation {
|
||||
var result = sim.endSimulation();
|
||||
assertEquals(2.0, result.simulationTime, DELTA);
|
||||
assertEquals(sim.seed, result.seed);
|
||||
assertEquals(elapsed * 1e-6, result.timeElapsedMS * 1e-6, diff);
|
||||
assertEquals(elapsed * 1e-6, result.timeElapsedMS, diff);
|
||||
assertEquals(2, result.nodes.size());
|
||||
assertEquals(1, result.nodes.get(node0.name).numArrivals, DELTA);
|
||||
assertEquals(1, result.nodes.get(node0.name).numDepartures, DELTA);
|
||||
@@ -414,12 +416,12 @@ public class TestSimulation {
|
||||
public void endSim() {
|
||||
var criteria = new EndCriteria.MaxDepartures(node0.name, 5);
|
||||
var sim = new Simulation(simpleNet, rigged, criteria);
|
||||
sim.addArrival(node0);
|
||||
sim.addArrival(node0);
|
||||
sim.addArrival(node0);
|
||||
sim.addArrival(node0);
|
||||
sim.addArrival(node0);
|
||||
sim.addArrival(node0);
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
sim.addToFel(Event.newArrival(0, sim.getTime()));
|
||||
|
||||
while (!criteria.shouldEnd(sim)) {
|
||||
sim.processNextEvent();
|
||||
|
||||
Reference in New Issue
Block a user