Submitted by: phil@steitz.com git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@140897 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1999928282
commit
a6c324e669
|
@ -61,9 +61,11 @@ import java.io.IOException;
|
|||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* Generates values for use in simulation applications.<br>
|
||||
* Generates values for use in simulation applications.
|
||||
* <p>
|
||||
* How values are generated is determined by the <code>mode</code>
|
||||
* property. <p>
|
||||
* property.
|
||||
* <p>
|
||||
* Supported <code>mode</code> values are: <ul>
|
||||
* <li> DIGEST_MODE -- uses an empirical distribution </li>
|
||||
* <li> REPLAY_MODE -- replays data from <code>valuesFile</code></li>
|
||||
|
@ -77,7 +79,7 @@ import java.net.MalformedURLException;
|
|||
* <li> CONSTANT_MODE -- returns <code>mu</code> every time.</li></ul>
|
||||
*
|
||||
* @author Phil Steitz
|
||||
* @version $Revision: 1.1 $
|
||||
* @version $Revision: 1.2 $
|
||||
*
|
||||
*/
|
||||
public class ValueServer {
|
||||
|
@ -110,13 +112,13 @@ public class ValueServer {
|
|||
/** Replay data from valuesFilePath */
|
||||
public static final int REPLAY_MODE = 1;
|
||||
|
||||
/** Uniform random variates with mean = mu */
|
||||
/** Uniform random deviates with mean = mu */
|
||||
public static final int UNIFORM_MODE = 2;
|
||||
|
||||
/** Exponential random variates with mean = mu */
|
||||
/** Exponential random deviates with mean = mu */
|
||||
public static final int EXPONENTIAL_MODE = 3;
|
||||
|
||||
/** Gaussian random variates with mean = mu, std dev = sigma */
|
||||
/** Gaussian random deviates with mean = mu, std dev = sigma */
|
||||
public static final int GAUSSIAN_MODE = 4;
|
||||
|
||||
/** Always return mu */
|
||||
|
@ -128,10 +130,10 @@ public class ValueServer {
|
|||
|
||||
/**
|
||||
* Returns the next generated value, generated according
|
||||
* to the mode value (see MODE constants)
|
||||
* to the mode value (see MODE constants).
|
||||
*
|
||||
* @return generated value
|
||||
* @throws IOException in REPLAY_MODE if file I/O error occurs
|
||||
* @throws IOException in REPLAY_MODE if a file I/O error occurs
|
||||
*/
|
||||
public double getNext() throws IOException {
|
||||
switch (mode) {
|
||||
|
@ -146,8 +148,36 @@ public class ValueServer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the input array with values generated using getNext() repeatedly.
|
||||
*
|
||||
* @param values array to be filled
|
||||
* @throws IOException in REPLAY_MODE if a file I/O error occurs
|
||||
*/
|
||||
public void fill(double[] values) throws IOException {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = getNext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of length <code>length</code> 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 file
|
||||
* Computes the empirical distribution using values from the file
|
||||
* in <code>valuesFilePath</code>, using the default number of bins.
|
||||
* <p>
|
||||
* <code>valuesFileURL</code> must exist and be
|
||||
|
@ -173,90 +203,18 @@ public class ValueServer {
|
|||
* This method must be called before using <code>getNext()</code>
|
||||
* with <code>mode = DISGEST_MODE</code>
|
||||
*
|
||||
* @param binCount the number of bins used in computing the empirical
|
||||
* distribution
|
||||
* @throws IOException if an error occurs reading the input file
|
||||
*/
|
||||
public void computeDistribution(int binCount)
|
||||
throws IOException{
|
||||
throws IOException {
|
||||
empiricalDistribution = new EmpiricalDistributionImpl(binCount);
|
||||
empiricalDistribution.load(valuesFileURL.getFile());
|
||||
mu = empiricalDistribution.getSampleStats().getMean();
|
||||
sigma = empiricalDistribution.getSampleStats().getStandardDeviation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random value in DIGEST_MODE.
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>: <ul>
|
||||
* <li>Before this method is called, <code>computeDistribution()</code>
|
||||
* must have completed successfully; otherwise an
|
||||
* <code>IllegalStateException</code> will be thrown</li></ul>
|
||||
*
|
||||
* @return next random value form the empirical distribution digest
|
||||
*/
|
||||
private double getNextDigest() {
|
||||
if ((empiricalDistribution == null) ||
|
||||
(empiricalDistribution.getBinStats().size() == 0)) {
|
||||
throw new IllegalStateException("Digest not initialized");
|
||||
}
|
||||
return empiricalDistribution.getNextValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets next sequential value from the <code>valuesFilePath</code>
|
||||
* opened by <code>openReplayFile()</code>.
|
||||
* <p>
|
||||
* Throws an IOException if <code>filePointer</code> is null or read fails.
|
||||
* Will wrap around to BOF is EOF is encountered.
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>: <ul>
|
||||
* <li> openReplayfile() must have completed successfully before
|
||||
* invoking this method; otherwise an <code>IlleglaStateException</code>
|
||||
* will be thrown</li></ul>
|
||||
*
|
||||
* @return next value from the replay file
|
||||
* @throws IOException if there is a problem reading from the file
|
||||
*/
|
||||
private double getNextReplay() throws IOException{
|
||||
String str = null;
|
||||
if (filePointer == null) {
|
||||
throw new IllegalStateException("replay file not open");
|
||||
}
|
||||
if ((str = filePointer.readLine()) == null) {
|
||||
closeReplayFile();
|
||||
openReplayFile();
|
||||
str = filePointer.readLine();
|
||||
}
|
||||
return new Double(str).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a uniformly distributed random value with mean = mu
|
||||
*
|
||||
* @return random uniform value
|
||||
*/
|
||||
private double getNextUniform() {
|
||||
return 2.0*mu*Math.random();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/** Getter for property mode.
|
||||
* @return Value of property mode.
|
||||
*/
|
||||
|
@ -279,10 +237,11 @@ public class ValueServer {
|
|||
}
|
||||
|
||||
/** Setter for property valuesFilePath.
|
||||
* @param valuesFilePath New value of property valuesFilePath.
|
||||
* @param url New value of property valuesFilePath.
|
||||
* @throws MalformedURLException if url is not well formed
|
||||
*/
|
||||
public void setValuesFileURL(String URL) throws MalformedURLException {
|
||||
this.valuesFileURL = new URL(URL);
|
||||
public void setValuesFileURL(String url) throws MalformedURLException {
|
||||
this.valuesFileURL = new URL(url);
|
||||
}
|
||||
|
||||
/** Getter for property empiricalDistribution.
|
||||
|
@ -293,7 +252,7 @@ public class ValueServer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Opens <code>valuesFilePath</code> to use in REPLAY_MODE
|
||||
* Opens <code>valuesFilePath</code> to use in REPLAY_MODE.
|
||||
*
|
||||
* @throws IOException if an error occurs opening the file
|
||||
*/
|
||||
|
@ -303,14 +262,119 @@ public class ValueServer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Closes <code>valuesFilePath</code> after use in REPLAY_MODE
|
||||
* Closes <code>valuesFilePath</code> 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.
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>: <ul>
|
||||
* <li>Before this method is called, <code>computeDistribution()</code>
|
||||
* must have completed successfully; otherwise an
|
||||
* <code>IllegalStateException</code> will be thrown</li></ul>
|
||||
*
|
||||
* @return next random value from the empirical distribution digest
|
||||
*/
|
||||
private double getNextDigest() {
|
||||
if ((empiricalDistribution == null) ||
|
||||
(empiricalDistribution.getBinStats().size() == 0)) {
|
||||
throw new IllegalStateException("Digest not initialized");
|
||||
}
|
||||
return empiricalDistribution.getNextValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets next sequential value from the <code>valuesFilePath</code>
|
||||
* opened by <code>openReplayFile()</code>.
|
||||
* <p>
|
||||
* Throws an IOException if <code>filePointer</code> is null or read fails.
|
||||
* Will wrap around to BOF is EOF is encountered.
|
||||
* <p>
|
||||
* <strong>Preconditions</strong>: <ul>
|
||||
* <li> openReplayfile() must have completed successfully before
|
||||
* invoking this method; otherwise an <code>IlleglaStateException</code>
|
||||
* will be thrown</li></ul>
|
||||
*
|
||||
* @return next value from the replay file
|
||||
* @throws IOException if there is a problem reading from the file
|
||||
*/
|
||||
private double getNextReplay() throws IOException {
|
||||
String str = null;
|
||||
if (filePointer == null) {
|
||||
throw new IllegalStateException("replay file not open");
|
||||
}
|
||||
if ((str = filePointer.readLine()) == null) {
|
||||
closeReplayFile();
|
||||
openReplayFile();
|
||||
str = filePointer.readLine();
|
||||
}
|
||||
return new Double(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ import org.apache.commons.math.stat.UnivariateImpl;
|
|||
* Test cases for the ValueServer class.
|
||||
*
|
||||
* @author Phil Steitz
|
||||
* @version $Revision: 1.3 $
|
||||
* @version $Revision: 1.4 $
|
||||
*/
|
||||
|
||||
public final class ValueServerTest extends TestCase {
|
||||
|
@ -103,6 +103,8 @@ public final class ValueServerTest extends TestCase {
|
|||
double next = 0.0;
|
||||
double tolerance = 0.1;
|
||||
vs.computeDistribution();
|
||||
assertTrue("empirical distribution property",
|
||||
vs.getEmpiricalDistribution() != null);
|
||||
Univariate stats = new UnivariateImpl();
|
||||
for (int i = 1; i < 1000; i++) {
|
||||
next = vs.getNext();
|
||||
|
@ -110,7 +112,20 @@ public final class ValueServerTest extends TestCase {
|
|||
}
|
||||
assertEquals("mean", 5.069831575018909, stats.getMean(), tolerance);
|
||||
assertEquals
|
||||
("std dev", 1.0173699343977738, stats.getStandardDeviation(), tolerance);
|
||||
("std dev", 1.0173699343977738, stats.getStandardDeviation(),
|
||||
tolerance);
|
||||
|
||||
vs.computeDistribution(500);
|
||||
stats = new UnivariateImpl();
|
||||
for (int i = 1; i < 1000; i++) {
|
||||
next = vs.getNext();
|
||||
stats.addValue(next);
|
||||
}
|
||||
assertEquals("mean", 5.069831575018909, stats.getMean(), tolerance);
|
||||
assertEquals
|
||||
("std dev", 1.0173699343977738, stats.getStandardDeviation(),
|
||||
tolerance);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,5 +174,70 @@ public final class ValueServerTest extends TestCase {
|
|||
assertEquals(compareValue,firstDataValue,tolerance);
|
||||
compareValue = vs.getNext();
|
||||
assertEquals(compareValue,secondDataValue,tolerance);
|
||||
vs.closeReplayFile();
|
||||
// make sure no NPE
|
||||
vs.closeReplayFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test other ValueServer modes
|
||||
*/
|
||||
public void testModes() throws Exception {
|
||||
vs.setMode(ValueServer.CONSTANT_MODE);
|
||||
vs.setMu(0);
|
||||
assertEquals("constant mode test",vs.getMu(),vs.getNext(),Double.MIN_VALUE);
|
||||
vs.setMode(ValueServer.UNIFORM_MODE);
|
||||
vs.setMu(2);
|
||||
double val = vs.getNext();
|
||||
assertTrue(val > 0 && val < 4);
|
||||
vs.setSigma(1);
|
||||
vs.setMode(ValueServer.GAUSSIAN_MODE);
|
||||
val = vs.getNext();
|
||||
assertTrue("gaussian value close enough to mean",
|
||||
val < vs.getMu() + 100*vs.getSigma());
|
||||
vs.setMode(ValueServer.EXPONENTIAL_MODE);
|
||||
val = vs.getNext();
|
||||
assertTrue(val > 0);
|
||||
try {
|
||||
vs.setMode(1000);
|
||||
vs.getNext();
|
||||
fail("bad mode, expecting IllegalStateException");
|
||||
} catch (IllegalStateException ex) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test fill
|
||||
*/
|
||||
public void testFill() throws Exception {
|
||||
vs.setMode(ValueServer.CONSTANT_MODE);
|
||||
vs.setMu(2);
|
||||
double[] val = new double[5];
|
||||
vs.fill(val);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
assertEquals("fill test in place",2,val[i],Double.MIN_VALUE);
|
||||
}
|
||||
double v2[] = vs.fill(3);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
assertEquals("fill test in place",2,v2[i],Double.MIN_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getters to make Clover happy
|
||||
*/
|
||||
public void testProperties() throws Exception {
|
||||
vs.setMode(ValueServer.CONSTANT_MODE);
|
||||
assertEquals("mode test",ValueServer.CONSTANT_MODE,vs.getMode());
|
||||
vs.setValuesFileURL("http://www.apache.org");
|
||||
String s = vs.getValuesFileURL();
|
||||
assertEquals("valuesFileURL test","http://www.apache.org",s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue