/* *
 * Title:        

* Description:

* Copyright: Copyright (c)

* Company:

* @author * @version 1.0 */ package umontreal.iro.lecuyer.stochprocess; import umontreal.iro.lecuyer.rng.*; import umontreal.iro.lecuyer.probdist.*; import umontreal.iro.lecuyer.randvar.*; /** * Uses a faster generating method (MSH) * than the simple inversion of the distribution function * used by {@link InverseGaussianProcess}. * It is about 60 times faster. * However it requires two * {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream}'s instead * of only one for {@link InverseGaussianProcess}. * The second stream is called otherStream below and * it is used to randomly choose between two roots at each time step. * */ public class InverseGaussianProcessMSH extends InverseGaussianProcess { // otherStream is used to decide between the two roots in method MSH. protected RandomStream otherStream; // Needed for the MSH method of generating inverse gaussian. protected NormalGen normalGen; /** * Constructs a new InverseGaussianProcessMSH. * The initial value s0 will be overridden by t[0] when * the observation times are set. * */ public InverseGaussianProcessMSH (double s0, double delta, double gamma, RandomStream stream, RandomStream otherStream) { super(); // dummy this.x0 = s0; setParams(delta, gamma); this.stream = stream; this.otherStream = otherStream; normalGen = new NormalGen(stream); numberOfRandomStreams = 2; } /** * Generates the path. It is done by successively calling * nextObservation(), therefore the two * {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream}s are * sampled alternatively. * */ public double[] generatePath() { double s = x0; for (int i = 0; i < d; i++) { s += InverseGaussianMSHGen.nextDouble(otherStream, normalGen, imu[i], ilam[i]); path[i+1] = s; } observationIndex = d; observationCounter = d; return path; } /** * Instead of using the internal streams to generate the path, * uses two arrays of uniforms U[0, 1). The length of the arrays should be * equal to the number of periods in the observation * times. This method is useful for {@link NormalInverseGaussianProcess}. * */ public double[] generatePath (double[] unifNorm, double[] unifOther) { double s = x0; // The class NonRandomStream is defined below. RandomStream nonRandOther = new NonRandomStream(unifOther); // this.stream should keep in memory the original stream of the Normal. normalGen.setStream(new NonRandomStream(unifNorm)); for (int i = 0; i < d; i++) { s += InverseGaussianMSHGen.nextDouble(nonRandOther, normalGen, imu[i], ilam[i]); path[i+1] = s; } observationIndex = d; observationCounter = d; normalGen.setStream(stream); // reset to original stream return path; } /** * Not implemented, requires two * {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream}'s. * */ public double[] generatePath (double[] uniforms01) { throw new UnsupportedOperationException("Use generatePath with 2 streams"); } public double nextObservation() { double s = path[observationIndex]; s += InverseGaussianMSHGen.nextDouble(otherStream, normalGen, imu[observationIndex], ilam[observationIndex]); observationIndex++; observationCounter = observationIndex; path[observationIndex] = s; return s; } /** * Only returns a stream if both inner * {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream}'s are the same. * */ public RandomStream getStream() { if( stream != otherStream) throw new IllegalStateException("Two different streams or more are present"); return stream; } /** * Sets the streams. * */ public void setStream (RandomStream stream, RandomStream otherStream) { super.setStream(stream); normalGen.setStream(stream); setOtherStream(otherStream); } /** * Sets both inner streams to stream. * */ public void setStream (RandomStream stream) { super.setStream(stream); normalGen.setStream(stream); setOtherStream(stream); } /** * Sets the otherStream, which is the stream used * to choose between the two roots in the MSH method. * */ public void setOtherStream (RandomStream otherStream) { this.otherStream = otherStream; } /** * Returns the otherStream, which is the stream used * to choose between the two quadratic roots from the MSH method. * */ public RandomStream getOtherStream() { return otherStream; } /** * Sets the normal generator. It also sets one of the * two inner streams to the stream of the normal generator. * */ public void setNormalGen (NormalGen normalGen) { this.normalGen = normalGen; stream = normalGen.getStream(); } /** * Returns the normal generator. * */ public NormalGen getNormalGen() { return normalGen; } /* * * NonRandomStream: * Given a double array, this class will return those values * as if it where a random stream. * Careful: Will not hard copy the array given as input. * And not checking for end of array for the time being. * And not checking j>i. */ protected class NonRandomStream implements RandomStream { double[] array; int position; public NonRandomStream(double[] array) { this.array = array; position = 0; } public NonRandomStream(double value) { this.array = new double[]{value}; position = 0; } public double nextDouble() { return array[position++]; } public void nextArrayOfDouble(double[] u, int start, int n) { for(int i = 0; i < n; i++) u[start+i] = array[position++]; } public void nextArrayOfInt(int i, int j, int[] u, int start, int n) { double diff = (double)(j - i); for(int ii = 0; ii < n; ii++) u[start+ii] = i + (int)Math.round(diff * array[position++]); } public int nextInt(int i, int j) { return (int)Math.round( (double)(j-i) * array[position]); } public void resetNextSubstream() { } public void resetStartStream() { position = 0; } public void resetStartSubstream() { } public String toString() { return new String("NonRandomStream of length " + array.length); } } }

Ads help maintain this website.