Coverage Report - org.apache.commons.math.random.ValueServer

Classes in this File Line Coverage Branch Coverage Complexity
ValueServer
89% 
100% 
1.917

 1  
 /*
 2  
  * Copyright 2003-2004 The Apache Software Foundation.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.apache.commons.math.random;
 18  
 import java.io.BufferedReader;
 19  
 import java.io.InputStreamReader;
 20  
 import java.io.IOException;
 21  
 import java.net.URL;
 22  
 import java.net.MalformedURLException;
 23  
 
 24  
 /**
 25  
  * Generates values for use in simulation applications.
 26  
  * <p>
 27  
  * How values are generated is determined by the <code>mode</code>
 28  
  * property.
 29  
  * <p>
 30  
  * Supported <code>mode</code> values are: <ul>
 31  
  * <li> DIGEST_MODE -- uses an empirical distribution </li>
 32  
  * <li> REPLAY_MODE -- replays data from <code>valuesFileURL</code></li>
 33  
  * <li> UNIFORM_MODE -- generates uniformly distributed random values with
 34  
  *                      mean = <code>mu</code> </li>
 35  
  * <li> EXPONENTIAL_MODE -- generates exponentially distributed random values
 36  
  *                         with mean = <code>mu</code></li>
 37  
  * <li> GAUSSIAN_MODE -- generates Gaussian distributed random values with
 38  
  *                       mean = <code>mu</code> and
 39  
  *                       standard deviation = <code>sigma</code></li>
 40  
  * <li> CONSTANT_MODE -- returns <code>mu</code> every time.</li></ul>
 41  
  *
 42  
  * @version $Revision$ $Date: 2005-05-21 22:25:44 -0700 (Sat, 21 May 2005) $
 43  
  *
 44  
  */
 45  
 public class ValueServer {
 46  
     /** mode determines how values are generated */
 47  12
     private int mode = 5;
 48  
 
 49  
     /** URI to raw data values  */
 50  12
     private URL valuesFileURL = null;
 51  
 
 52  
     /** Mean for use with non-data-driven modes */
 53  12
     private double mu = 0.0;
 54  
 
 55  
     /** Standard deviation for use with GAUSSIAN_MODE */
 56  12
     private double sigma = 0.0;
 57  
 
 58  
     /** Empirical probability distribution for use with DIGEST_MODE */
 59  12
     private EmpiricalDistribution empiricalDistribution = null;
 60  
 
 61  
     /** file pointer for REPLAY_MODE */
 62  12
     private BufferedReader filePointer = null;
 63  
 
 64  
     /** RandomDataImpl to use for random data generation */
 65  12
     private RandomData randomData = new RandomDataImpl();
 66  
 
 67  
     // Data generation modes ======================================
 68  
 
 69  
     /** Use empirical distribution  */
 70  
     public static final int DIGEST_MODE = 0;
 71  
 
 72  
     /** Replay data from valuesFilePath */
 73  
     public static final int REPLAY_MODE = 1;
 74  
 
 75  
     /** Uniform random deviates with mean = mu */
 76  
     public static final int UNIFORM_MODE = 2;
 77  
 
 78  
     /** Exponential random deviates with mean = mu */
 79  
     public static final int EXPONENTIAL_MODE = 3;
 80  
 
 81  
     /** Gaussian random deviates with mean = mu, std dev = sigma */
 82  
     public static final int GAUSSIAN_MODE = 4;
 83  
 
 84  
     /** Always return mu */
 85  
     public static final int CONSTANT_MODE = 5;
 86  
 
 87  
     /** Creates new ValueServer */
 88  12
     public ValueServer() {
 89  12
     }
 90  
 
 91  
     /**
 92  
      * Returns the next generated value, generated according
 93  
      * to the mode value (see MODE constants).
 94  
      *
 95  
      * @return generated value
 96  
      * @throws IOException in REPLAY_MODE if a file I/O error occurs
 97  
      */
 98  
     public double getNext() throws IOException {
 99  6028
         switch (mode) {
 100  3998
             case DIGEST_MODE: return getNextDigest();
 101  2004
             case REPLAY_MODE: return getNextReplay();
 102  2
             case UNIFORM_MODE: return getNextUniform();
 103  2
             case EXPONENTIAL_MODE: return getNextExponential();
 104  2
             case GAUSSIAN_MODE: return getNextGaussian();
 105  18
             case CONSTANT_MODE: return mu;
 106  2
             default: throw new IllegalStateException
 107  
                        ("Bad mode: " + mode);
 108  
         }
 109  
     }
 110  
 
 111  
     /**
 112  
      * Fills the input array with values generated using getNext() repeatedly.
 113  
      *
 114  
      * @param values array to be filled
 115  
      * @throws IOException in REPLAY_MODE if a file I/O error occurs
 116  
      */
 117  
     public void fill(double[] values) throws IOException {
 118  12
         for (int i = 0; i < values.length; i++) {
 119  10
             values[i] = getNext();
 120  
         }
 121  2
     }
 122  
 
 123  
     /**
 124  
      * Returns an array of length <code>length</code> with values generated
 125  
      * using getNext() repeatedly.
 126  
      *
 127  
      * @param length length of output array
 128  
      * @return array of generated values
 129  
      * @throws IOException in REPLAY_MODE if a file I/O error occurs
 130  
      */
 131  
     public double[] fill(int length) throws IOException {
 132  2
         double[] out = new double[length];
 133  8
         for (int i = 0; i < length; i++) {
 134  6
             out[i] = getNext();
 135  
         }
 136  2
         return out;
 137  
     }
 138  
 
 139  
     /**
 140  
      * Computes the empirical distribution using values from the file
 141  
      * in <code>valuesFileURL</code>, using the default number of bins.
 142  
      * <p>
 143  
      * <code>valuesFileURL</code> must exist and be
 144  
      * readable by *this at runtime.
 145  
      * <p>
 146  
      * This method must be called before using <code>getNext()</code>
 147  
      * with <code>mode = DISGEST_MODE</code>
 148  
      *
 149  
      * @throws IOException if an I/O error occurs reading the input file
 150  
      */
 151  
     public void computeDistribution() throws IOException {
 152  2
         empiricalDistribution = new EmpiricalDistributionImpl();
 153  2
         empiricalDistribution.load(valuesFileURL);
 154  2
     }
 155  
 
 156  
     /**
 157  
      * Computes the empirical distribution using values from the file
 158  
      * in <code>valuesFileURL</code> and <code>binCount</code> bins.
 159  
      * <p>
 160  
      * <code>valuesFileURL</code> must exist and be
 161  
      * readable by *this at runtime.
 162  
      * <p>
 163  
      * This method must be called before using <code>getNext()</code>
 164  
      * with <code>mode = DISGEST_MODE</code>
 165  
      *
 166  
      * @param binCount the number of bins used in computing the empirical
 167  
      * distribution
 168  
      * @throws IOException if an error occurs reading the input file
 169  
      */
 170  
     public void computeDistribution(int binCount)
 171  
             throws IOException {
 172  2
         empiricalDistribution = new EmpiricalDistributionImpl(binCount);
 173  2
         empiricalDistribution.load(valuesFileURL);
 174  2
         mu = empiricalDistribution.getSampleStats().getMean();
 175  2
         sigma = empiricalDistribution.getSampleStats().getStandardDeviation();
 176  2
     }
 177  
 
 178  
     /** Getter for property mode.
 179  
      * @return Value of property mode.
 180  
      */
 181  
     public int getMode() {
 182  2
         return mode;
 183  
     }
 184  
 
 185  
     /** Setter for property mode.
 186  
      * @param mode New value of property mode.
 187  
      */
 188  
     public void setMode(int mode) {
 189  28
         this.mode = mode;
 190  28
     }
 191  
 
 192  
     /**
 193  
      * Getter for <code>valuesFileURL<code>
 194  
      * @return Value of property valuesFileURL.
 195  
      */
 196  
     public URL getValuesFileURL() {
 197  2
         return valuesFileURL;
 198  
     }
 199  
 
 200  
     /**
 201  
      * Sets the <code>valuesFileURL</code> using a string URL representation
 202  
      * @param url String representation for new valuesFileURL.
 203  
      * @throws MalformedURLException if url is not well formed
 204  
      */
 205  
     public void setValuesFileURL(String url) throws MalformedURLException {
 206  2
         this.valuesFileURL = new URL(url);
 207  2
     }
 208  
 
 209  
     /**
 210  
      * Sets the <code>valuesFileURL</code>
 211  
      * @param url New value of property valuesFileURL.
 212  
      */
 213  
     public void setValuesFileURL(URL url) {
 214  12
         this.valuesFileURL = url;
 215  12
     }
 216  
 
 217  
     /** Getter for property empiricalDistribution.
 218  
      * @return Value of property empiricalDistribution.
 219  
      */
 220  
     public EmpiricalDistribution getEmpiricalDistribution() {
 221  2
         return empiricalDistribution;
 222  
     }
 223  
 
 224  
     /**
 225  
      * Resets REPLAY_MODE file pointer to the beginning of the <code>valuesFileURL</code>.
 226  
      *
 227  
      * @throws IOException if an error occurs opening the file
 228  
      */
 229  
     public void resetReplayFile() throws IOException {
 230  4
         if (filePointer != null) {
 231  
             try {
 232  0
                 filePointer.close();
 233  0
                 filePointer = null;
 234  0
             } catch (IOException ex) {
 235  
                 // ignore
 236  0
             }
 237  
         }
 238  4
         filePointer = new BufferedReader(new InputStreamReader(valuesFileURL.openStream()));
 239  4
     }
 240  
 
 241  
     /**
 242  
      * Closes <code>valuesFileURL</code> after use in REPLAY_MODE.
 243  
      *
 244  
      * @throws IOException if an error occurs closing the file
 245  
      */
 246  
     public void closeReplayFile() throws IOException {
 247  6
         if (filePointer != null) {
 248  4
             filePointer.close();
 249  4
             filePointer = null;
 250  
         }
 251  6
     }
 252  
 
 253  
     /** Getter for property mu.
 254  
      * @return Value of property mu.
 255  
      */
 256  
     public double getMu() {
 257  4
         return mu;
 258  
     }
 259  
 
 260  
     /** Setter for property mu.
 261  
      * @param mu New value of property mu.
 262  
      */
 263  
     public void setMu(double mu) {
 264  6
         this.mu = mu;
 265  6
     }
 266  
 
 267  
     /** Getter for property sigma.
 268  
      * @return Value of property sigma.
 269  
      */
 270  
     public double getSigma() {
 271  2
         return sigma;
 272  
     }
 273  
 
 274  
     /** Setter for property sigma.
 275  
      * @param sigma New value of property sigma.
 276  
      */
 277  
     public void setSigma(double sigma) {
 278  2
         this.sigma = sigma;
 279  2
     }
 280  
 
 281  
     //------------- private methods ---------------------------------
 282  
 
 283  
     /**
 284  
      * Gets a random value in DIGEST_MODE.
 285  
      * <p>
 286  
      * <strong>Preconditions</strong>: <ul>
 287  
      * <li>Before this method is called, <code>computeDistribution()</code>
 288  
      * must have completed successfully; otherwise an
 289  
      * <code>IllegalStateException</code> will be thrown</li></ul>
 290  
      *
 291  
      * @return next random value from the empirical distribution digest
 292  
      */
 293  
     private double getNextDigest() {
 294  3998
         if ((empiricalDistribution == null) ||
 295  
             (empiricalDistribution.getBinStats().size() == 0)) {
 296  2
             throw new IllegalStateException("Digest not initialized");
 297  
         }
 298  3996
         return empiricalDistribution.getNextValue();
 299  
     }
 300  
 
 301  
     /**
 302  
      * Gets next sequential value from the <code>valuesFileURL</code>.
 303  
      * <p>
 304  
      * Throws an IOException if the read fails.
 305  
      * <p>
 306  
      * This method will open the <code>valuesFileURL</code> if there is no
 307  
      * replay file open.
 308  
      * <p>
 309  
      * The <code>valuesFileURL</code> will be closed and reopened to wrap around
 310  
      * from EOF to BOF if EOF is encountered.
 311  
      *
 312  
      * @return next value from the replay file
 313  
      * @throws IOException if there is a problem reading from the file
 314  
      */
 315  
     private double getNextReplay() throws IOException {
 316  2004
         String str = null;
 317  2004
         if (filePointer == null) {
 318  0
             resetReplayFile();
 319  
         }
 320  2004
         if ((str = filePointer.readLine()) == null) {
 321  2
             closeReplayFile();
 322  2
             resetReplayFile();
 323  2
             str = filePointer.readLine();
 324  
         }
 325  2004
         return new Double(str).doubleValue();
 326  
     }
 327  
 
 328  
     /**
 329  
      * Gets a uniformly distributed random value with mean = mu.
 330  
      *
 331  
      * @return random uniform value
 332  
      */
 333  
     private double getNextUniform() {
 334  2
         return randomData.nextUniform(0, 2 * mu);
 335  
     }
 336  
 
 337  
     /**
 338  
      * Gets an exponentially distributed random value with mean = mu.
 339  
      *
 340  
      * @return random exponential value
 341  
      */
 342  
     private double getNextExponential() {
 343  2
         return randomData.nextExponential(mu);
 344  
     }
 345  
 
 346  
     /**
 347  
      * Gets a Gaussian distributed random value with mean = mu
 348  
      * and standard deviation = sigma.
 349  
      *
 350  
      * @return random Gaussian value
 351  
      */
 352  
     private double getNextGaussian() {
 353  2
         return randomData.nextGaussian(mu, sigma);
 354  
     }
 355  
 
 356  
     /**
 357  
      * Construct a ValueServer instance using a RandomData as its source
 358  
      * of random data.
 359  
      * 
 360  
      * @param randomData the RandomData instance used to source random data
 361  
      * @since 1.1
 362  
      */
 363  
     public ValueServer(RandomData randomData) {
 364  0
         super();
 365  0
         this.randomData = randomData;
 366  0
     }
 367  
 }