Commit 95a621d4 authored by Simon Eismann's avatar Simon Eismann

integrated priority scheduling

parent af73d431
......@@ -58,6 +58,7 @@ package de.tud.cs.simqpn.kernel;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Random;
import org.apache.log4j.Logger;
import org.dom4j.Element;
......@@ -74,6 +75,7 @@ public class Place extends Node {
// Supported departure disciplines (depDiscip):
public static final int NORMAL = 0; // Arriving tokens become available for output transitions immediately upon arrival.
public static final int FIFO = 1; // First-In-First-Out: Arriving tokens become available for output transitions in the order of their arrival.
public static final int RANDOM = 3; // First-In-First-Out: Arriving tokens become available for output transitions randomly.
// Supported probe actions
public static final int PROBE_ACTION_NONE = 0;
......@@ -89,6 +91,7 @@ public class Place extends Node {
public int numColors;
public String[] colors; // Names of the colors that can reside in this Place.
public int[] priorities; //priority of each color
public int statsLevel; // Determines the amount of statistics to be gathered during the run.
public int depDiscip; // Departure discipline.
@SuppressWarnings("rawtypes")
......@@ -135,6 +138,7 @@ public class Place extends Node {
super(id, name);
this.colors = colors;
this.numColors = colors.length;
this.priorities = new int[colors.length];
this.inTrans = new Transition[numInTrans];
this.outTrans = new Transition[numOutTrans];
this.tokenPop = new int[numColors];
......@@ -152,7 +156,7 @@ public class Place extends Node {
this.tokenPop[c] = 0;
this.availTokens[c] = 0;
}
if (depDiscip == FIFO) {
if (depDiscip == FIFO || depDiscip == RANDOM) {
this.depQueue = new LinkedList();
this.depReady = false;
}
......@@ -191,7 +195,7 @@ public class Place extends Node {
if (depDiscip == NORMAL) {
availTokens = tokenPop; //Note: from here on, availTokens and tokenPop point to the same array!
}
else if (depDiscip == FIFO) {
else if (depDiscip == FIFO || depDiscip == RANDOM) {
int totTkPop = 0;
int[] tkPop = new int[numColors];
for (int c = 0; c < numColors; c++) {
......@@ -327,7 +331,7 @@ public class Place extends Node {
for (int i = 0; i < outTrans.length; i++)
outTrans[i].updateState(id, color, tokenPop[color], count);
}
else if (depDiscip == FIFO) {
else if (depDiscip == FIFO || depDiscip == RANDOM) {
if (depReady) {
for (int i=0; i < count; i++)
depQueue.addLast(new Integer(color));
......@@ -406,6 +410,20 @@ public class Place extends Node {
}
else depReady = false;
}
else if (depDiscip == RANDOM) {
availTokens[color] -= count;
for (int i = 0; i < outTrans.length; i++)
outTrans[i].updateState(id, color, availTokens[color], (-1)*count);
if (depQueue.size() > 0) {
Random rand = new Random();
int nextCol = ((Integer) depQueue.remove(rand.nextInt(depQueue.size()))).intValue();
availTokens[nextCol]++;
depReady = true; // Left for clarity. Actually redundant since depReady should already be true.
for (int i = 0; i < outTrans.length; i++)
outTrans[i].updateState(id, nextCol, availTokens[nextCol], 1);
}
else depReady = false;
}
else {
log.error("Invalid depDiscip specified for place " + name);
throw new SimQPNException();
......@@ -465,5 +483,5 @@ public class Place extends Node {
}
}
}
}
......@@ -61,6 +61,7 @@
package de.tud.cs.simqpn.kernel;
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.log4j.Logger;
import org.dom4j.Element;
......
......@@ -44,12 +44,16 @@
* 2009/08/03 Frederik Zipp Added xmlId property.
* 2009/05/05 Frederik Zipp Support for central queues.
* 2010/07/24 Simon Spinner Support for tracking tokens.
* 2013/06/25 Mehran Saliminia Added RANDOM discipline.
*
*/
package de.tud.cs.simqpn.kernel;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Random;
import org.apache.log4j.Logger;
......@@ -74,6 +78,8 @@ public class Queue {
public static final int IS = 0;
public static final int FCFS = 1;
public static final int PS = 2;
public static final int RANDOM = 3;
public static final int PRIO = 4;
private static Logger log = Logger.getLogger(Queue.class);
......@@ -89,7 +95,11 @@ public class Queue {
public int numServers; // FCFS queues: Number of servers in queueing station.
public int numBusyServers; // FCFS queues: Number of currently busy servers.
public LinkedList waitingLine; // FCFS queues: List of tokens waiting for service (waiting area of the queue).
public LinkedList waitingLine; // FCFS queues: List of tokens waiting for service (waiting area of the queue).
public Comparator<Token>
comparator ; // PRIO queues comparator
public PriorityQueue<Token>
priorityQueue; // PRIO queues: List of tokens waiting for service (waiting area of the queue).
public boolean eventsUpToDate; // PS queues: True if currently scheduled events for this queue (if any)
// reflect the latest token popolation of the queue.
......@@ -137,8 +147,8 @@ public class Queue {
this.totNumColors = 0;
this.statsLevel = 0;
// FCFS Queues
if (queueDiscip == FCFS) {
// FCFS/RANDOM Queues
if (queueDiscip == FCFS || queueDiscip == RANDOM) {
this.numBusyServers = 0;
this.waitingLine = new LinkedList();
}
......@@ -148,6 +158,13 @@ public class Queue {
eventScheduled = false;
expPS = false; // By default non-exponential queue is assumed.
}
// PRIO Queues
if (queueDiscip == PRIO) {
this.numBusyServers = 0;
this.comparator = new TokenPrioComparator();
this.priorityQueue = new PriorityQueue<Token>(2,comparator);
}
}
/**
......@@ -518,6 +535,50 @@ public class Queue {
n++;
}
}
else if (queueDiscip == RANDOM) {
int n = 0;
while (n < count && numBusyServers < numServers) {
// Schedule service completion event
double servTime = qPl.randServTimeGen[color].nextDouble();
if (servTime < 0) servTime = 0;
Token tk = (tokensToBeAdded != null) ? tokensToBeAdded[n] : new Token(qPl, color);
tk.arrivTS = Simulator.clock;
Simulator.scheduleEvent(Simulator.clock + servTime, this, tk);
numBusyServers++; n++;
// Update Stats
if (qPl.statsLevel >= 3)
qPl.qPlaceQueueStats.updateDelayTimeStats(color, 0);
}
while (n < count) {
// Place the rest of the tokens in the waitingLine
Token tk = (tokensToBeAdded != null) ? tokensToBeAdded[n] : new Token(qPl, color);
tk.arrivTS = Simulator.clock;
waitingLine.addLast(tk);
n++;
}
}
else if (queueDiscip == PRIO) {
int n = 0;
while (n < count && numBusyServers < numServers) {
// Schedule service completion event
double servTime = qPl.randServTimeGen[color].nextDouble();
if (servTime < 0) servTime = 0;
Token tk = (tokensToBeAdded != null) ? tokensToBeAdded[n] : new Token(qPl, color);
tk.arrivTS = Simulator.clock;
Simulator.scheduleEvent(Simulator.clock + servTime, this, tk);
numBusyServers++; n++;
// Update Stats
if (qPl.statsLevel >= 3)
qPl.qPlaceQueueStats.updateDelayTimeStats(color, 0);
}
while (n < count) {
// Place the rest of the tokens in the priorityQueue
Token tk = (tokensToBeAdded != null) ? tokensToBeAdded[n] : new Token(qPl, color);
tk.arrivTS = Simulator.clock;
priorityQueue.add(tk);
n++;
}
}
else if (queueDiscip == PS) {
if (!expPS) {
if (eventScheduled) updateResidServTimes(); //NOTE: WATCH OUT! Method should be called before the new tokens have been added to queueTokResidServTimes!
......@@ -574,6 +635,34 @@ public class Queue {
}
else numBusyServers--;
}
else if (queueDiscip == RANDOM) {
if (waitingLine.size() > 0) {
Random randomGenerator = new Random();
int index = randomGenerator.nextInt(waitingLine.size());
Token tk = (Token) waitingLine.remove(index);
QPlace qPl = (QPlace) tk.place;
double servTime = qPl.randServTimeGen[tk.color].nextDouble();
if (servTime < 0) servTime = 0;
Simulator.scheduleEvent(Simulator.clock + servTime, this, tk);
// Update stats
if (qPl.statsLevel >= 3)
qPl.qPlaceQueueStats.updateDelayTimeStats(tk.color, Simulator.clock - tk.arrivTS);
}
else numBusyServers--;
}
else if (queueDiscip == PRIO) {
if (!priorityQueue.isEmpty()) {
Token tk = priorityQueue.remove();
QPlace qPl = (QPlace) tk.place;
double servTime = qPl.randServTimeGen[tk.color].nextDouble();
if (servTime < 0) servTime = 0;
Simulator.scheduleEvent(Simulator.clock + servTime, this, tk);
// Update stats
if (qPl.statsLevel >= 3)
qPl.qPlaceQueueStats.updateDelayTimeStats(tk.color, Simulator.clock - tk.arrivTS);
}
else numBusyServers--;
}
else if (queueDiscip == PS) {
QPlace qPl = ((QPlace) token.place);
if (!expPS) {
......
......@@ -546,7 +546,8 @@ public class Simulator {
Stats[] result = null;
simRunning = true;
// NOTE: In the following, if the simulation is interrupted, simRunning should be reset.
// NOTE: In the following, if the simulation is interrupted, simRunning should be reset.
long startTs = System.currentTimeMillis();
try {
validateInputNet(net);
......@@ -603,6 +604,8 @@ public class Simulator {
simRunning = false;
LogManager.shutdown();
}
long t = System.currentTimeMillis() - startTs;
System.out.println("Simulation Time :"+ t +" ms");
return result;
}
......@@ -620,7 +623,7 @@ public class Simulator {
xpathSelector = createXPath("//color-ref[@priority > 0]");
if(xpathSelector.selectSingleNode(net) != null) {
log.error("Priority attribute currently not supported (Set to 0 for all places)");
throw new SimQPNException();
// throw new SimQPNException();
}
xpathSelector = createXPath("//transition[@priority > 0]");
if(xpathSelector.selectSingleNode(net) != null) {
......@@ -3005,6 +3008,10 @@ public class Simulator {
throw new SimQPNException();
}
trans[i].modeWeights[j] = Double.parseDouble(mode.attributeValue("firing-weight"));
if(trans[i].modeWeights[j] == 0)
trans[i].dynamicModeWeights[j] = true;
else
trans[i].dynamicModeWeights[j] = false;
log.debug("trans[" + i + "].modeWeights[" + j + "] = " + trans[i].modeWeights[j]);
}
}
......@@ -3284,7 +3291,14 @@ public class Simulator {
queueingStrategy = Queue.FCFS;
} else if ("PS".equals(queue.attributeValue("strategy"))) {
queueingStrategy = Queue.PS;
} else {
}
else if ("RANDOM".equals(queue.attributeValue("strategy"))) {
queueingStrategy = Queue.RANDOM;
}
else if ("PRIO".equals(queue.attributeValue("strategy"))) {
queueingStrategy = Queue.PRIO;
}
else {
log.error(formatDetailMessage(
"Invalid or missing \"strategy\" (queueing discipline) setting!",
"queue-num", Integer.toString(i),
......@@ -3385,6 +3399,8 @@ public class Simulator {
dDis = Place.NORMAL;
} else if ("FIFO".equals(place.attributeValue("departure-discipline"))) {
dDis = Place.FIFO;
} else if ("RANDOM".equals(place.attributeValue("departure-discipline"))) {
dDis = Place.RANDOM;
} else {
log.error(formatDetailMessage(
"Invalid departure-discipline setting!",
......@@ -3436,13 +3452,16 @@ public class Simulator {
));
throw new SimQPNException();
}
String[] colors = new String[colorRefs.size()];
String[] colors = new String[colorRefs.size()];
int[] priorities = new int[colorRefs.size()];
Iterator colorRefIterator = colorRefs.iterator();
for (int c = 0; colorRefIterator.hasNext(); c++) {
Element colorRef = (Element) colorRefIterator.next();
XPath xpathSelector = createXPath("colors/color[(@id='" + colorRef.attributeValue("color-id") + "')]");
Element color = (Element) xpathSelector.selectSingleNode(net);
colors[c] = color.attributeValue("name");
colors[c] = color.attributeValue("name");
priorities[c] = (colorRef.attributeValue("priority") == null)?
0 : Integer.valueOf(colorRef.attributeValue("priority"));
}
if ("ordinary-place".equals(place.attributeValue(XSI_TYPE_ATTRIBUTE))) {
......@@ -3455,7 +3474,7 @@ public class Simulator {
numProbes,
statsLevel, // stats level
dDis, // departure discipline
place); // Reference to the place' XML element
place); // Reference to the place' XML element
placeToIndexMap.put(place, i);
if (log.isDebugEnabled()) {
log.debug("places[" + i + "] = new Place("
......@@ -3483,7 +3502,8 @@ public class Simulator {
statsLevel, // stats level
dDis, // departure discipline
queue, // Reference to the integrated Queue
place); // Reference to the place' XML element
place); // Reference to the place' XML element
places[i].priorities = priorities;
placeToIndexMap.put(place, i);
if (log.isDebugEnabled()) {
log.debug("places[" + i + "] = new QPlace("
......
package de.tud.cs.simqpn.kernel;
import java.util.Comparator;
public class TokenPrioComparator implements Comparator<Token> {
@Override
public int compare(Token t1, Token t2) {
if(t1.place.priorities[t1.color] > t2.place.priorities[t2.color])
return -1;
if(t1.place.priorities[t1.color] < t2.place.priorities[t2.color])
return 1;
return 0;
}
}
......@@ -77,6 +77,7 @@ public class Transition extends Node {
public int[][][] inFunc; // [mode, inPlace, color]
public int[][][] outFunc; // [mode, outPlace, color]
public double[] modeWeights; // [1..numModes]
public boolean[] dynamicModeWeights; // [1..numModes]
public boolean[] modeStatus; // [1..numModes] Specifying the current status
// (enabled/disabled) of a mode
......@@ -117,6 +118,7 @@ public class Transition extends Node {
this.numModes = numModes;
this.transWeight = transWeight;
this.modeWeights = new double[numModes];
this.dynamicModeWeights = new boolean[numModes];
this.inPlaces = new Place[numInPlaces];
this.outPlaces = new Place[numOutPlaces];
this.inFunc = new int[numModes][numInPlaces][];
......@@ -315,7 +317,6 @@ public class Transition extends Node {
* @exception
*/
public void fire() throws SimQPNException {
int nM = numModes;
// Choose mode to fire based on weights
int mode;
......@@ -327,10 +328,42 @@ public class Transition extends Node {
break;
}
}
} else {
} else {
double[] pdf = new double[enModesCnt];
int[] enModesIDs = new int[enModesCnt];
for (int m = 0, e = 0; m < nM; m++) {
// Adjust mode weights
// When initial modeWeight == 0 then the number of available expected tokens of input places with the name starting
// with '$' character will be considered as modeWeight
if(modeStatus[m] && dynamicModeWeights[m])
{
//IF (not initial mapped)
//do mappint
//endif
//modeWeights[m] = getMappedPlace(m).availTokens.
modeWeights[m] = 0;
int p, c, nP, nC;
nP = inPlaces.length;
Place pl;
for (p = 0; p < nP; p++) {
pl = inPlaces[p];
nC = pl.numColors;
String[] nameHierarchy = pl.name.split("\\.");
String name = nameHierarchy[nameHierarchy.length -1];
if(name.startsWith("$"))
for (c = 0; c < nC; c++)
{
if (inFunc[m][p][c] > 0) {
modeWeights[m] += pl.availTokens[c];
}
}
}
}
if (modeStatus[m]) {
pdf[e] = modeWeights[m];
enModesIDs[e] = m;
......@@ -338,7 +371,7 @@ public class Transition extends Node {
}
}
randModeGen.setState2(pdf);
mode = enModesIDs[randModeGen.nextInt()];
mode = enModesIDs[randModeGen.nextInt()];
}
int p, c, nP, nC, prC, n;
int maxN = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment