/* *
 * 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.*; import umontreal.iro.lecuyer.util.*; /** * This class differs from GammaProcessBridge only in that it requires * the number of interval of the path to be * a power of 2 and of equal size. * It is then possible to generate the bridge process using * a special implementation of the beta random variate generator * (using the symmetrical beta distribution) * that is much faster (HOW MUCH? QUANTIFY!) than the general case. * Note that when the method setObservationTimes is called, * the equality of the size of the time steps is verified. * To allow for differences due to floating point errors, time steps * are considered to be equal if their relative difference is less * than 10-15. * */ public class GammaProcessSymmetricalBridge extends GammaProcessBridge { protected BetaSymmetricalGen BSgen; /** * Constructs a new GammaProcessSymmetricalBridge * with parameters * μ = mu, * ν = nu and initial * value * S(t0) = s0. * The random variables are created using the * {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream} stream. * Note that the same {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream} * stream is used for the * {@link umontreal.iro.lecuyer.randvar.GammaGen GammaGen} and for the * {@link umontreal.iro.lecuyer.randvar.BetaSymmetricalGen BetaSymmetricalGen} * inluded in this class. * */ public GammaProcessSymmetricalBridge (double s0, double mu, double nu, RandomStream stream) { this (s0, mu, nu, new GammaGen (stream, new GammaDist (1.0)), new BetaSymmetricalGen (stream, new BetaSymmetricalDist (1.0))); } /** * Constructs a new GammaProcessSymmetricalBridge * with parameters * μ = mu, * ν = nu and initial * value * S(t0) = s0. Note that the * {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream} included in * the {@link umontreal.iro.lecuyer.randvar.BetaSymmetricalGen BetaSymmetricalGen} * is sets to the one included in the * {@link umontreal.iro.lecuyer.randvar.GammaGen GammaGen} to avoid confusion. * This {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream} is then used to * generate all the random variables. * * */ public GammaProcessSymmetricalBridge (double s0, double mu, double nu, GammaGen Ggen, BetaSymmetricalGen BSgen) { super (s0, mu, nu, Ggen, BSgen); this.BSgen = BSgen; BSgen.setStream(Ggen.getStream()); } public double nextObservation() { double s; if (bridgeCounter == -1) { s = x0 + Ggen.nextDouble(stream, mu2dTOverNu, muOverNu); if (s <= x0) s = setLarger (x0); bridgeCounter = 0; observationIndex = d; } else { int j = bridgeCounter * 3; int oldIndexL = wIndexList[j]; int newIndex = wIndexList[j + 1]; int oldIndexR = wIndexList[j + 2]; double y = BSgen.nextDouble(stream, bMu2dtOverNuL[newIndex]); s = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y; if (s <= path[oldIndexL]) s = setLarger (path, oldIndexL, oldIndexR); bridgeCounter++; observationIndex = newIndex; } observationCounter = bridgeCounter + 1; path[observationIndex] = s; return s; } public double nextObservation (double nextT) { double s; if (bridgeCounter == -1) { t[d] = nextT; mu2dTOverNu = mu2OverNu * (t[d] - t[0]); s = x0 + Ggen.nextDouble(stream, mu2dTOverNu, muOverNu); if (s <= x0) s = setLarger (x0); bridgeCounter = 0; observationIndex = d; } else { int j = bridgeCounter*3; int oldIndexL = wIndexList[j]; int newIndex = wIndexList[j + 1]; int oldIndexR = wIndexList[j + 2]; t[newIndex] = nextT; bMu2dtOverNuL[newIndex] = mu2OverNu * (t[newIndex] - t[oldIndexL]); double y = BSgen.nextDouble(stream, bMu2dtOverNuL[newIndex]); s = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y; if (s <= path[oldIndexL]) s = setLarger (path, oldIndexL, oldIndexR); bridgeCounter++; observationIndex = newIndex; } observationCounter = bridgeCounter + 1; path[observationIndex] = s; return s; } public double[] generatePath() { int oldIndexL, oldIndexR, newIndex; path[d] = x0 + Ggen.nextDouble(stream, mu2dTOverNu, muOverNu); for (int j = 0; j < 3*(d-1); j+=3) { oldIndexL = wIndexList[j]; newIndex = wIndexList[j + 1]; oldIndexR = wIndexList[j + 2]; double y = BSgen.nextDouble(stream, bMu2dtOverNuL[newIndex]); path[newIndex] = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y; if (path[newIndex] <= path[oldIndexL]) setLarger (path, oldIndexL, newIndex, oldIndexR); } observationIndex = d; observationCounter = d; return path; } public double[] generatePath (double[] uniform01) { int oldIndexL, oldIndexR, newIndex; path[d] = x0 + GammaDist.inverseF(mu2dTOverNu, muOverNu, 10, uniform01[0]); for (int j = 0; j < 3*(d-1); j+=3) { oldIndexL = wIndexList[j]; newIndex = wIndexList[j + 1]; oldIndexR = wIndexList[j + 2]; double y = BetaSymmetricalDist.inverseF(bMu2dtOverNuL[newIndex], uniform01[1 + j/3]); path[newIndex] = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y; if (path[newIndex] <= path[oldIndexL]) setLarger (path, oldIndexL, newIndex, oldIndexR); } observationIndex = d; observationCounter = d; return path; } protected void init () { super.init (); if (observationTimesSet) { /* Testing to make sure number of observations n = 2^k */ int k = 0; int x = d; int y = 1; while (x>1) { x = x / 2; y = y * 2; k++; } if (y != d) throw new IllegalArgumentException ( "GammaProcessSymmetricalBridge:" +"Number 'n' of observation times is not a power of 2" ); /* Testing that time intervals are equidistant */ boolean equidistant = true; double macheps = 1.0e-13; // Num.DBL_EPSILON; double dt = t[1] - t[0]; for (int i=1; i

Ads help maintain this website.