📄 modelconverter.java
字号:
/**
* Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package jmt.gui.common.definitions;
import Jama.Matrix;
import jmt.gui.common.Defaults;
import jmt.gui.common.distributions.Distribution;
import jmt.gui.common.distributions.Exponential;
import jmt.gui.common.routingStrategies.ProbabilityRouting;
import jmt.gui.common.routingStrategies.RandomRouting;
import jmt.gui.common.routingStrategies.RoutingStrategy;
import jmt.gui.common.serviceStrategies.LDStrategy;
import jmt.gui.common.serviceStrategies.ZeroStrategy;
import jmt.gui.exact.ExactModel;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
/**
* <p>Title: Model Converter</p>
* <p>Description: This class provides methods to convert models between JMODEL, JSIM,
* JMVA and JABA.</p>
*
* @author Bertoli Marco
* Date: 20-feb-2006
* Time: 12.23.12
*/
public class ModelConverter {
// --- Methods for conversion JMVA --> JSIM -----------------------------------------------
/**
* Converts a JMVA model to JSIM. Conversion is performed by equalling service times in every
* LI station (adjusting visits) and creating FCFS queues with exponential service time distribution.
* <br>
* Visits are converted with routing probability, to mantain correctness of computated response time values
* a "virtual" node called RefStation is added as a reference station for closed classes and
* routed when (in terms of mean values) a single visit is performed in the system. (as visits values are scaled to
* compute probability distribution).
* <br>
* Note that a single router node, called "Router" is used to route jobs through the
* entire network, simplyfing its thopology. Stations (LI, LD and Delays) are connected in a parallel form with
* the Router.
* @param input JMVA model (read only access)
* @param output target JSIM or JMODEL model. This is expected to be empty
* @return a Vector with all found warnings during conversion (in String format)
*/
public static Vector convertJMVAtoJSIM(ExactModel input, CommonModel output) {
return convertJMVAtoJSIM(input, output, false);
}
/**
* Converts a JMVA model to JSIM. Conversion is performed by equalling service times in every
* LI station (adjusting visits) and creating FCFS queues with exponential service time distribution.
* <br>
* Visits are converted with routing probability, to mantain correctness of computated response time values
* a "virtual" node called RefStation is added as a reference station for closed classes and
* routed when (in terms of mean values) a single visit is performed in the system. (as visits values are scaled to
* compute probability distribution).
* <br>
* Note that a single router node, called "Router" is used to route jobs through the
* entire network, simplyfing its thopology. Stations (LI, LD and Delays) are connected in a parallel form with
* the Router.
* @param input JMVA model (read only access)
* @param output target JSIM or JMODEL model. This is expected to be empty
* @param visitTransform if true last element of returned vector is a matrix with visit transformation
* to be applied to throughput
* @return a Vector with all found warnings during conversion (in String format). Last element (if selected)
* is visit matrix to be applied
*/
public static Vector convertJMVAtoJSIM(ExactModel input, CommonModel output, boolean visitTransform) {
// Changes default values, then restores default back at the end of method
String defaultRouting = Defaults.get("stationRoutingStrategy");
String defaultQueue = Defaults.get("stationQueueStrategy");
Defaults.set("stationRoutingStrategy", RandomRouting.class.getName());
Defaults.set("stationQueueStrategy", CommonModel.QUEUE_STRATEGY_FCFS);
Vector res = new Vector();
// Keys for unique items
Object sourceKey = null, sinkKey = null, routerKey, refRouterKey = null;
// Sums visit for each class
double[] visitSum = new double[input.getClasses()];
// Visits matrix (row: stations, column: classes)
double[][] visits = new double[input.getStations()][input.getClasses()];
// Original visits vector
double[][] origVisits = input.getVisits();
// New service times vector
double[] servTimes = new double[input.getStations()];
// Now converts service times to be all equals by adjusting visit ratio
// This is needed as we will create FCFS exponential servers
for (int i=0; i<input.getStations(); i++) {
// Change only LI stations
if (!(input.getStationTypes()[i] == ExactModel.STATION_LI)) {
System.arraycopy(origVisits[i], 0, visits[i], 0, origVisits[i].length);
continue;
}
// Finds the service time of first non-zero service demand
double sTime = input.getServiceTimes()[i][0][0];
int pos = 0;
while (Math.abs(origVisits[i][pos] * sTime) < 1e-10 && pos < input.getClasses()-1) {
pos++;
sTime = input.getServiceTimes()[i][pos][0];
}
// All service demand are zero
if (Math.abs(origVisits[i][pos] * sTime) < 1e-10){
Arrays.fill(visits[i], 0.0);
}
// Normal case
else {
for (int j=0; j<input.getClasses(); j++)
visits[i][j] = origVisits[i][j]*input.getServiceTimes()[i][j][0] / sTime;
}
// Unique service time
servTimes[i] = sTime;
}
// Convert classes
Object[] classKeys = new Object[input.getClasses()];
for (int i=0; i<input.getClasses(); i++) {
String name = input.getClassNames()[i];
int type = input.getClassTypes()[i];
// This holds customers if class is closed or arrival rate if open
double data = input.getClassData()[i];
Object key;
visitSum[i] = 1; // Sums visit for each station. This is initialized to one as we
// count visit to reference station
for (int j=0; j<input.getStations(); j++)
visitSum[i] += visits[j][i];
if (type == ExactModel.CLASS_CLOSED) {
// Closed class
key = output.addClass(name, CommonModel.CLASS_TYPE_CLOSED, 0, new Integer((int)data), null);
}
else {
// Open class
Exponential ex = new Exponential();
ex.setMean(1/data);
key = output.addClass(name, CommonModel.CLASS_TYPE_OPEN, 0, null, ex);
}
classKeys[i] = key;
}
routerKey = output.addStation("Router", CommonModel.STATION_TYPE_ROUTER);
// Creates source, sink and router (if needed)
if (input.isClosed() || input.isMixed()) {
refRouterKey = output.addStation("RefStation", CommonModel.STATION_TYPE_ROUTER);
// Makes connection between refRouter and router
output.setConnected(refRouterKey, routerKey, true);
output.setConnected(routerKey, refRouterKey, true);
// Gives warning on refStation
res.add("A special node, called \"RefStation\" was added in order to compute correctly the System Response Time and System Throughput of closed classes." +
" Its presence is fundamental to compute correctly number of visits at each station for closed classes.");
}
if (input.isOpen() || input.isMixed()) {
sourceKey = output.addStation("Source", CommonModel.STATION_TYPE_SOURCE);
sinkKey = output.addStation("Sink", CommonModel.STATION_TYPE_SINK);
//Makes connections between source, sink and router
output.setConnected(sourceKey, routerKey, true);
output.setConnected(routerKey, sinkKey, true);
}
// Convert stations
Object[] stationKeys = new Object[input.getStations()];
for (int i=0; i<input.getStations(); i++) {
String name = input.getStationNames()[i];
int type = input.getStationTypes()[i];
double[][] serviceTimes = input.getServiceTimes()[i];
Object key = null;
switch (type) {
case ExactModel.STATION_DELAY:
// Delay
key = output.addStation(name, CommonModel.STATION_TYPE_DELAY);
// Sets distribution for each class
for (int j=0; j<classKeys.length; j++) {
Exponential ex = new Exponential();
ex.setMean(serviceTimes[j][0]);
output.setServiceTimeDistribution(key, classKeys[j], ex);
}
break;
case ExactModel.STATION_LI:
// Load independent
key = output.addStation(name, CommonModel.STATION_TYPE_SERVER);
// Sets distribution for each class
for (int j=0; j<classKeys.length; j++) {
Exponential ex = new Exponential();
ex.setMean(servTimes[i]);
output.setServiceTimeDistribution(key, classKeys[j], ex);
}
break;
case ExactModel.STATION_LD:
// Load dependent - this is single class only, but here
// we support multiclass too (future extensions).
key = output.addStation(name, CommonModel.STATION_TYPE_SERVER);
// Sets distribution for each class
for (int j=0; j<classKeys.length; j++) {
LDStrategy lds = new LDStrategy();
Object rangeKey = lds.getAllRanges()[0];
for (int range=0; range<serviceTimes[j].length; range++) {
// First range is already available
if (range > 0)
rangeKey = lds.addRange();
Exponential ex = new Exponential();
ex.setMean(serviceTimes[j][range]);
lds.setRangeDistribution(rangeKey, ex);
lds.setRangeDistributionMean(rangeKey, Double.toString(serviceTimes[j][range]));
}
output.setServiceTimeDistribution(key, classKeys[j], lds);
}
break;
}
stationKeys[i] = key;
// Make connections with router
output.setConnected(routerKey, key, true);
output.setConnected(key, routerKey, true);
}
// Sets routing for router
for (int i=0; i<classKeys.length; i++) {
ProbabilityRouting pr = new ProbabilityRouting();
output.setRoutingStrategy(routerKey, classKeys[i], pr);
for (int j=0; j<stationKeys.length; j++)
pr.getValues().put(stationKeys[j], new Double(visits[j][i] / visitSum[i]));
// Sets refRouter as reference station for closed class, sets its routing and avoid put jobs into sink
if (output.getClassType(classKeys[i])== CommonModel.CLASS_TYPE_CLOSED) {
output.setClassRefStation(classKeys[i], refRouterKey);
pr.getValues().put(refRouterKey, new Double(1 / visitSum[i]));
if (sinkKey != null)
pr.getValues().put(sinkKey, new Double(0.0));
}
// Sets source as reference station for open class and sets sink routing, avoid routing to refRouter
else {
output.setClassRefStation(classKeys[i], sourceKey);
pr.getValues().put(sinkKey, new Double(1 / visitSum[i]));
if (refRouterKey != null)
pr.getValues().put(refRouterKey, new Double(0.0));
}
}
// Create measures
for (int i=0; i<classKeys.length; i++)
for (int j=0; j<stationKeys.length; j++) {
// Queue length
output.addMeasure(CommonModel.MEASURE_QL, stationKeys[j], classKeys[i]);
// Residence Time
output.addMeasure(CommonModel.MEASURE_RD, stationKeys[j], classKeys[i]);
// Utilization
output.addMeasure(CommonModel.MEASURE_U, stationKeys[j], classKeys[i]);
// Throughput
output.addMeasure(CommonModel.MEASURE_X, stationKeys[j], classKeys[i]);
}
// Restores default values
Defaults.set("stationRoutingStrategy", defaultRouting);
Defaults.set("stationQueueStrategy", defaultQueue);
// Manage preloading
output.manageJobs();
// Calculate visit transformation to be applied to throughputs: origVisits ./ visits
double[][] transform = new double[visits.length][visits[0].length];
if (visitTransform) {
for (int i=0; i<visits.length; i++)
for (int j=0; j<visits[i].length; j++)
if (visits[i][j] != 0)
transform[i][j] = origVisits[i][j] / visits[i][j];
else
transform[i][j] = 1;
// Adds created matrix to results Vector
res.add(transform);
}
// Return warnings
return res;
}
// ----------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -