Refactor Net and ServerNodeState classes to improve child node handling and simplify simulation initialization

This commit is contained in:
2025-02-09 22:14:23 +01:00
parent 0a5b4ae954
commit d7d74e231e
4 changed files with 25 additions and 40 deletions

View File

@@ -17,8 +17,6 @@ import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.io.Output;
import net.berack.upo.valpre.rand.Rng;
/** /**
* A class that represents a network of queues, each with its own servers. * A class that represents a network of queues, each with its own servers.
* The network in question is created by adding a node and then establishing * The network in question is created by adding a node and then establishing
@@ -141,26 +139,6 @@ public final class Net implements Iterable<ServerNode> {
return this.servers.get(index); return 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 -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 int getChildOf(int parent, Rng rng) {
var random = rng.random();
for (var conn : this.connections.get(parent)) {
random -= conn.weight;
if (random <= 0)
return conn.index;
}
return -1;
}
/** /**
* Get a list of all the children of the parent. * Get a list of all the children of the parent.
* In the list there is the node and the weight associated with. * In the list there is the node and the weight associated with.

View File

@@ -1,8 +1,10 @@
package net.berack.upo.valpre.sim; package net.berack.upo.valpre.sim;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.List;
import net.berack.upo.valpre.rand.Rng; import net.berack.upo.valpre.rand.Rng;
import net.berack.upo.valpre.sim.Net.Connection;
import net.berack.upo.valpre.sim.stats.NodeStats; import net.berack.upo.valpre.sim.stats.NodeStats;
/** /**
@@ -17,9 +19,9 @@ public class ServerNodeState {
public final ArrayDeque<Double> queue = new ArrayDeque<>(); public final ArrayDeque<Double> queue = new ArrayDeque<>();
public final int index; public final int index;
public final Net net;
public final ServerNode node; public final ServerNode node;
public final NodeStats stats = new NodeStats(); public final NodeStats stats = new NodeStats();
public final List<Connection> children;
/** /**
* Create a new node state based on the index and the net passed as input * Create a new node state based on the index and the net passed as input
@@ -29,8 +31,8 @@ public class ServerNodeState {
*/ */
ServerNodeState(int index, Net net) { ServerNodeState(int index, Net net) {
this.index = index; this.index = index;
this.net = net;
this.node = net.getNode(index); this.node = net.getNode(index);
this.children = net.getChildren(index);
} }
/** /**
@@ -166,9 +168,14 @@ public class ServerNodeState {
* otherwise * otherwise
*/ */
public Event spawnArrivalToChild(double time, Rng rng) { public Event spawnArrivalToChild(double time, Rng rng) {
var childIndex = this.net.getChildOf(this.index, rng); if (!this.children.isEmpty()) {
if (childIndex >= 0) var random = rng.random();
return Event.newArrival(childIndex, time); for (var child : this.children) {
random -= child.weight;
if (random <= 0)
return Event.newArrival(child.index, time);
}
}
return null; return null;
} }
} }

View File

@@ -24,10 +24,15 @@ public final class Simulation {
private long eventProcessed = 0; private long eventProcessed = 0;
/** /**
* Creates a new run of the simulation with the given nodes and random number * Creates a new simulation for the given network.
* generator. * The random number generator is used to generate random numbers for the
* simulation.
* The simulation will end when the given criteria are met.
* NOTE: the network passed is only used to create the initial states of the
* nodes, so the simulation is not affected by changes to the network after
* the creation of this object.
* *
* @param states The nodes in the network. * @param net The network to simulate.
* @param rng The random number generator to use. * @param rng The random number generator to use.
* @param criterias when the simulation has to end. * @param criterias when the simulation has to end.
*/ */

View File

@@ -121,7 +121,7 @@ public class TestSimulation {
net.addConnection(0, 1, 1.0); net.addConnection(0, 1, 1.0);
var conn = net.getChildren(0); var conn = net.getChildren(0);
assertEquals(1, conn.size()); assertEquals(1, conn.size());
assertEquals(node1, conn.get(0).child); assertEquals(1, conn.get(0).index);
assertEquals(1.0, conn.get(0).weight, DELTA); assertEquals(1.0, conn.get(0).weight, DELTA);
conn = net.getChildren(1); conn = net.getChildren(1);
assertEquals(0, conn.size()); assertEquals(0, conn.size());
@@ -131,8 +131,8 @@ public class TestSimulation {
net.addConnection(0, 2, 1.0); net.addConnection(0, 2, 1.0);
conn = net.getChildren(0); conn = net.getChildren(0);
assertEquals(2, conn.size()); assertEquals(2, conn.size());
assertEquals(node1, conn.get(0).child); assertEquals(1, conn.get(0).index);
assertEquals(node2, conn.get(1).child); assertEquals(2, conn.get(1).index);
assertEquals(1.0, conn.get(0).weight, DELTA); assertEquals(1.0, conn.get(0).weight, DELTA);
assertEquals(1.0, conn.get(1).weight, DELTA); assertEquals(1.0, conn.get(1).weight, DELTA);
conn = net.getChildren(1); conn = net.getChildren(1);
@@ -143,18 +143,14 @@ public class TestSimulation {
net.normalizeWeights(); net.normalizeWeights();
conn = net.getChildren(0); conn = net.getChildren(0);
assertEquals(2, conn.size()); assertEquals(2, conn.size());
assertEquals(node1, conn.get(0).child); assertEquals(1, conn.get(0).index);
assertEquals(node2, conn.get(1).child); assertEquals(2, conn.get(1).index);
assertEquals(0.5, conn.get(0).weight, DELTA); assertEquals(0.5, conn.get(0).weight, DELTA);
assertEquals(0.5, conn.get(1).weight, DELTA); assertEquals(0.5, conn.get(1).weight, DELTA);
conn = net.getChildren(1); conn = net.getChildren(1);
assertEquals(0, conn.size()); assertEquals(0, conn.size());
conn = net.getChildren(2); conn = net.getChildren(2);
assertEquals(0, conn.size()); assertEquals(0, conn.size());
var sample = net.getChildOf(0, rigged);
assertEquals(1, sample);
assertEquals(node1, net.getNode(sample));
} }
@Test @Test
@@ -162,7 +158,6 @@ public class TestSimulation {
var state = new ServerNodeState(1, simpleNet); var state = new ServerNodeState(1, simpleNet);
assertEquals(1, state.index); assertEquals(1, state.index);
assertEquals(simpleNet, state.net);
assertEquals(node1, state.node); assertEquals(node1, state.node);
assertEquals(0, state.numServerBusy); assertEquals(0, state.numServerBusy);
assertEquals(0, state.numServerUnavailable); assertEquals(0, state.numServerUnavailable);