⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modelconverter.java

📁 一个用于排队系统仿真的开源软件,有非常形象的图象仿真过程!
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * 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 + -