/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.math.random; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.math.MathRuntimeException; import org.apache.commons.math.exception.util.LocalizedFormats; /** * Generates values for use in simulation applications. *
* How values are generated is determined by the mode
* property.
* Supported mode
values are:
valuesFileURL
mu
mu
mu
and
* standard deviation = sigma
mu
every time.length
with values generated
* using getNext() repeatedly.
*
* @param length length of output array
* @return array of generated values
* @throws IOException in REPLAY_MODE if a file I/O error occurs
*/
public double[] fill(int length) throws IOException {
double[] out = new double[length];
for (int i = 0; i < length; i++) {
out[i] = getNext();
}
return out;
}
/**
* Computes the empirical distribution using values from the file
* in valuesFileURL
, using the default number of bins.
*
* valuesFileURL
must exist and be
* readable by *this at runtime.
* This method must be called before using getNext()
* with mode = DIGEST_MODE
valuesFileURL
and binCount
bins.
*
* valuesFileURL
must exist and be readable by this process
* at runtime.
* This method must be called before using getNext()
* with mode = DIGEST_MODE
valuesFileURL
* @return Value of property valuesFileURL.
*/
public URL getValuesFileURL() {
return valuesFileURL;
}
/**
* Sets the valuesFileURL
using a string URL representation
* @param url String representation for new valuesFileURL.
* @throws MalformedURLException if url is not well formed
*/
public void setValuesFileURL(String url) throws MalformedURLException {
this.valuesFileURL = new URL(url);
}
/**
* Sets the valuesFileURL
* @param url New value of property valuesFileURL.
*/
public void setValuesFileURL(URL url) {
this.valuesFileURL = url;
}
/** Getter for property empiricalDistribution.
* @return Value of property empiricalDistribution.
*/
public EmpiricalDistribution getEmpiricalDistribution() {
return empiricalDistribution;
}
/**
* Resets REPLAY_MODE file pointer to the beginning of the valuesFileURL
.
*
* @throws IOException if an error occurs opening the file
*/
public void resetReplayFile() throws IOException {
if (filePointer != null) {
try {
filePointer.close();
filePointer = null;
} catch (IOException ex) {
// ignore
}
}
filePointer = new BufferedReader(new InputStreamReader(valuesFileURL.openStream()));
}
/**
* Closes valuesFileURL
after use in REPLAY_MODE.
*
* @throws IOException if an error occurs closing the file
*/
public void closeReplayFile() throws IOException {
if (filePointer != null) {
filePointer.close();
filePointer = null;
}
}
/** Getter for property mu.
* @return Value of property mu.
*/
public double getMu() {
return mu;
}
/** Setter for property mu.
* @param mu New value of property mu.
*/
public void setMu(double mu) {
this.mu = mu;
}
/** Getter for property sigma.
* @return Value of property sigma.
*/
public double getSigma() {
return sigma;
}
/** Setter for property sigma.
* @param sigma New value of property sigma.
*/
public void setSigma(double sigma) {
this.sigma = sigma;
}
//------------- private methods ---------------------------------
/**
* Gets a random value in DIGEST_MODE.
*
* Preconditions:
* - Before this method is called,
computeDistribution()
* must have completed successfully; otherwise an
* IllegalStateException
will be thrown
*
* @return next random value from the empirical distribution digest
*/
private double getNextDigest() {
if ((empiricalDistribution == null) ||
(empiricalDistribution.getBinStats().size() == 0)) {
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.DIGEST_NOT_INITIALIZED);
}
return empiricalDistribution.getNextValue();
}
/**
* Gets next sequential value from the valuesFileURL
.
*
* Throws an IOException if the read fails.
*
* This method will open the valuesFileURL
if there is no
* replay file open.
*
* The valuesFileURL
will be closed and reopened to wrap around
* from EOF to BOF if EOF is encountered. EOFException (which is a kind of
* IOException) may still be thrown if the valuesFileURL
is
* empty.
*
* @return next value from the replay file
* @throws IOException if there is a problem reading from the file
* @throws NumberFormatException if an invalid numeric string is
* encountered in the file
*/
private double getNextReplay() throws IOException {
String str = null;
if (filePointer == null) {
resetReplayFile();
}
if ((str = filePointer.readLine()) == null) {
// we have probably reached end of file, wrap around from EOF to BOF
closeReplayFile();
resetReplayFile();
if ((str = filePointer.readLine()) == null) {
throw MathRuntimeException.createEOFException(LocalizedFormats.URL_CONTAINS_NO_DATA,
valuesFileURL);
}
}
return Double.valueOf(str).doubleValue();
}
/**
* Gets a uniformly distributed random value with mean = mu.
*
* @return random uniform value
*/
private double getNextUniform() {
return randomData.nextUniform(0, 2 * mu);
}
/**
* Gets an exponentially distributed random value with mean = mu.
*
* @return random exponential value
*/
private double getNextExponential() {
return randomData.nextExponential(mu);
}
/**
* Gets a Gaussian distributed random value with mean = mu
* and standard deviation = sigma.
*
* @return random Gaussian value
*/
private double getNextGaussian() {
return randomData.nextGaussian(mu, sigma);
}
}