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

📄 ldstrategy.java

📁 一个用于排队系统仿真的开源软件,有非常形象的图象仿真过程!
💻 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.serviceStrategies;

import jmt.gui.common.Defaults;
import jmt.gui.common.distributions.Distribution;
import org.cheffo.jeplite.JEP;
import org.cheffo.jeplite.ParseException;

import java.text.DecimalFormat;
import java.util.NoSuchElementException;
import java.util.TreeMap;

/**
 * <p>Title: Load Dependent Station Service Strategy</p>
 * <p>Description: This object holds informations for a load dependent service strategy.
 * The strategy is organized in subsequent ranges (starting from 1 to infinity),
 * and each of them can specify a distribution, its c (if any, fixed) and its mean value
 * as a function of load into the station.</p>
 * 
 * @author Bertoli Marco
 *         Date: 11-ott-2005
 *         Time: 12.25.52
 *
 *
 * Modified by Francesco D'Aquino
 */
public class LDStrategy implements ServiceStrategy{
    protected static JEP parser; // Parser used to check correctness
    protected static final String VAR = "n"; // Dipendent variable
    protected static DecimalFormat formatter = new DecimalFormat("#.####");
    protected TreeMap ranges;
    
    /**
     * Return engine classpacth for LoadDependent strategy
     * @return
     */
    public static String getEngineClassPath() {
        return "jmt.engine.NetStrategies.ServiceStrategies.LoadDependentStrategy";
    }

    /**
     * Builds a new Load Dependent Service Time Strategy with default values
     */
    public LDStrategy() {
        // Initialize parser if needed
        if (parser == null) {
            parser = new JEP();
            parser.addStandardFunctions();
            parser.addStandardConstants();
        }
        ranges = new TreeMap();
        // Adds first range
        ranges.put(new Integer(1), new Range(1));
    }
    /**
     * Adds a new range to this strategy. 'From' field is initialized
     * with greatest created range by now plus one (so if last range has from = 7,
     * this will have from = 8)
     * @return search's key for newly created range
     */
    public synchronized Object addRange() {
        int from = ((Integer)ranges.lastKey()).intValue() + 1;
        Range newRange = new Range(from);
        Object key = new Integer(from);
        ranges.put(key, newRange);
        return key;
    }

    /**
     * Changes starting number of jobs for a given range, only if it does not overlap
     * with another range.
     * @param key search's key for given range
     * @param startingInterval starting number of jobs for this range to be set
     * @return new search's key for this range
     */
    public synchronized Object setRangeFrom(Object key, int startingInterval) {
        if (ranges.containsKey(new Integer(startingInterval)))
            return key;
        // Does not allow to change first key from value.
        if (ranges.firstKey() == key)
            return key;
        Range tmp = (Range)ranges.remove(key);
        tmp.from = startingInterval;
        Object newkey = new Integer(startingInterval);
        ranges.put(newkey, tmp);
        return newkey;
    }

    /**
     * Sets distribution for this range, preserving old value of c, if applayable.
     * @param key search's key for this range
     * @param distribution distribution to set in this range
     */
    public synchronized void setRangeDistribution(Object key, Distribution distribution) {
        Range tmp = (Range)ranges.get(key);
        Distribution tmpdist = (Distribution)distribution.clone();
        // Preserve stored value of c, if applayable
        if (tmp.distribution.hasC() && distribution.hasC()) {
            double c = tmp.distribution.getC();
            tmpdist.setC(c);
        }
        tmpdist.setMean(tmp.distribution.getMean());
        // If old mean expression is not valid for new distribution, overwrites it
        if (tmpdist.getMean() - tmp.distribution.getMean() > 1e-5)
            tmp.meanExpression = formatter.format(tmpdist.getMean());
        tmp.distribution = tmpdist;
    }

    /**
     * Sets distribution for this range, don't preserver old values or C, nor of mean
     * @param key search's key for this range
     * @param distribution distribution to set in this range
     */
    public synchronized void setRangeDistributionNoCheck(Object key, Distribution distribution) {
        Range tmp = (Range)ranges.get(key);
        tmp.distribution=(Distribution)distribution.clone();
    }

    /**
     * Sets expression to calculate mean value of provided range only if it can be parsed
     * without errors and its value in 'from' point is assignable to current distribution
     * @param key search key for provided range
     * @param meanExpression expression to be evaluated to find mean value
     */
    public synchronized void setRangeDistributionMean(Object key, String meanExpression) {
        Range tmp = (Range)ranges.get(key);
        // Calculates min value using parser and sets it into distribution
        parser.addVariable(VAR, tmp.from);
        parser.parseExpression(meanExpression);
        if (!parser.hasError())
            try {
            tmp.distribution.setMean(parser.getValue());
            // Allow range only if its value in 'from' point is assignable to
            // current distribution
            if (tmp.distribution.getMean() - parser.getValue() < 1e-5)
                tmp.meanExpression = meanExpression;
        } catch(ParseException ex) {
            // Do nothing
        }
    }

    /**
     * Sets expression to calculate mean value, performing no checks
     * @param key search key for provided range
     * @param meanExpression expression to be evaluated to find mean value
     */
    public synchronized void setRangeDistributionMeanNoCheck(Object key, String meanExpression) {
        Range tmp = (Range)ranges.get(key);
        tmp.meanExpression = meanExpression;

    }
    /**
     * Sets variation coefficient 'c' for the distribution of a given range
     * @param key search key for provided range
     * @param c variation coefficient
     */
    public synchronized void setRangeDistributionC(Object key, double c) {
        Range tmp = (Range)ranges.get(key);
        if (tmp.distribution.hasC())
            tmp.distribution.setC(c);
    }

    /**
     * Gets starting number of jobs for this range
     * @param key search key for provided range
     * @return starting number of jobs for this range
     */
    public synchronized int getRangeFrom(Object key) {
        Range tmp = (Range)ranges.get(key);
        return tmp.from;
    }

    /**
     * Gets maximum number of jobs for this range
     * @param key search key for provided range
     * @return maximum number of jobs for this range. -1 means Infinity.
     */
    public synchronized int getRangeTo(Object key) {
        Integer nextKey = new Integer(((Integer)key).intValue() + 1);
        try {
            Range next = (Range)ranges.get(ranges.tailMap(nextKey).firstKey());
            return next.from - 1;
        } catch (NoSuchElementException ex) {
            return -1;
        }
    }

    /**
     * Returns the distribution of a given range
     * @param key search key for given range
     * @return its distribution
     */
    public synchronized Distribution getRangeDistribution(Object key) {
        Range tmp = (Range)ranges.get(key);
        return tmp.distribution;
    }

    /**
     * Returns the expression to be evaluated to find the mean of the distribution
     * of a given range
     * @param key search key for given range
     * @return expression to find mean value
     */
    public synchronized String getRangeDistributionMean(Object key) {
        Range tmp = (Range)ranges.get(key);
        return tmp.meanExpression;
    }

    /**
     * Returns number of defined ranges
     * @return number of defined ranges
     */
    public synchronized int getRangeNumber() {
        return ranges.size();
    }

    /**
     * Returns an array with all available ranges keys
     * @return all available ranges keys, in ordered form
     */
    public synchronized Object[] getAllRanges() {
        return ranges.keySet().toArray();
    }

    /**
     * Removes a Range from this data structure
     * @param key search's key for range to be removed
     */
    public synchronized void deleteRange(Object key) {
        // Does not allow delete of first range
        if (ranges.firstKey() != key)
            ranges.remove(key);
    }

    /**
     * Returns a String description of this object
     * @return a String description of this object
     */
    public String toString() {
        return "Load Dependent Service Strategy";
    }

    /**
     * Clones this strategy in a new Object
     * @return a clone of current service strategy
     */
    public Object clone() {
        LDStrategy tmp = new LDStrategy();
        // Sets first range
        Object[] rangesKeys = ranges.keySet().toArray();
        for (int i=0; i<rangesKeys.length; i++) {
            Range oldRange = (Range)ranges.get(rangesKeys[i]);
            Range newRange = new Range(oldRange.from);
            newRange.distribution = (Distribution)oldRange.distribution.clone();
            newRange.meanExpression = oldRange.meanExpression;
            tmp.ranges.put(rangesKeys[i], newRange);
        }
        return tmp;
    }

    /**
     * Returns mean value of service time distribution for given number of jobs.
     * @param jobs queue lenght of the station
     * @return  mean value of service time distribution. On insuccess returns -1
     */
    public double getMeanValue(int jobs) {
        // Finds key of right range
        Object key = ranges.headMap(new Integer(jobs+1)).lastKey();
        Range range =  (Range) ranges.get(key);
        parser.addVariable(VAR, jobs);
        parser.parseExpression(range.meanExpression);
        if (!parser.hasError())
            try {
                return parser.getValue();
            } catch(ParseException ex) {
            // Do nothing
            }
        // This will never be returned
        return -1;
    }

    /**
     * Checks if the given Load Dependent Strategy equals <code>this</code>,
     * where the equivalence is iff:
     * <br>1) have the same number of ranges</br>
     * <br>2) have the same distribution in each range</br>
     * <br>3) have the same mean value in each range</br>
     * <br>4) have the same 'from' and 'to' values in each range</br>
     * @param ld the given LD strategy
     * @return  true if ld equals <code>this</code>
     *
     * Author: Francesco D'Aquino
     */
    public boolean isEquivalent(LDStrategy ld) {
        boolean equivalent = true;
        Object[] ldRanges = ld.getAllRanges();
        Object[] thisRanges = this.getAllRanges();
        if (this.getRangeNumber() == ld.getRangeNumber()) {
            for (int i=0;i<ld.getRangeNumber();i++) {
                if (ld.getRangeDistribution(ldRanges[i]).getName().equals(getRangeDistribution(thisRanges[i]).getName())) {
                    if (ld.getRangeDistributionMean(ldRanges[i]).equals(getRangeDistributionMean(thisRanges[i]))) {
                        if ( (ld.getRangeFrom(ldRanges[i])!=getRangeFrom(thisRanges[i]))  ||  (ld.getRangeTo(ldRanges[i])!=getRangeTo(thisRanges[i]))  ) {
                            equivalent = false;
                            break;
                        }
                    }
                    else {
                        equivalent = false;
                        break;
                    }
                }
                else {
                    equivalent = false;
                    break;
                }
            }
        }
        else equivalent = false;
        return equivalent;
    }

    /**
     * Inner class used to store definition of a Range
     */
    protected class Range implements Comparable {
        public int from;
        public Distribution distribution;
        public String meanExpression;
        /**
         * Builds a new Range, starting interval from specified queue length. Distribution
         * is set as Default service time distribution, if it allows mean, otherwise to the
         * first distribution with mean available.
         * @param from starting index for this range
         */
        public Range(int from) {
            this.from = from;
            distribution = (Distribution)Defaults.getAsNewInstance("stationServiceStrategy");
            if (!distribution.hasMean())
                distribution = Distribution.findAllWithMean()[0];
            meanExpression = formatter.format(distribution.getMean());
        }

        /**
         * Used to store this object in a SortedSet.
         * @param o object to compare with
         * @return a negative integer, zero, or a positive integer as this object
         * is less than, equal to, or greater than the specified object.
         */
        public int compareTo(Object o) {
            Range tmp = (Range) o;
            return from - tmp.from;
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -