/* *
* 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.*;
/**
* Same as {@link GammaProcessPCA}, but the generated uniforms
* correspond to a bridge transformation of the {@link BrownianMotionPCA}
* instead of a sequential transformation.
*
*/
public class GammaProcessPCABridge extends GammaProcessPCA {
protected BrownianMotionBridge BMBridge;
protected double mu2OverNu,
mu2dTOverNu;
protected double[] bMu2dtOverNuL, // For precomputations for G Bridge
bMu2dtOverNuR;
protected int[] wIndexList;
/**
* Constructs a new GammaProcessPCABridge with parameters
*
* μ = mu ,
* ν = nu and initial value
* S(t0) = s0 .
* The same stream is used to generate the gamma and beta random numbers. All
* these numbers are generated by inversion in the following order:
* the first uniform random number generated
* is used for the gamma and the other d - 1 for the beta's.
*
*/
public GammaProcessPCABridge (double s0, double mu, double nu,
RandomStream stream) {
super (s0, mu, nu, stream);
this.BMBridge = new BrownianMotionBridge(0.0, 0.0, Math.sqrt(nu), stream);
}
public double[] generatePath (double[] uniform01) {
// uniformsV[] of size d+1, but element 0 never used.
double[] uniformsV = new double[d+1];
// generate BrownianMotion PCA path
double[] BMPCApath = BMPCA.generatePath(uniform01);
int oldIndexL;
int newIndex;
int oldIndexR;
double temp, y;
// Transform BMPCA points to uniforms using an inverse bridge.
for (int j = 0; j < 3*(d-1); j+=3) {
oldIndexL = BMBridge.wIndexList[j];
newIndex = BMBridge.wIndexList[j + 1];
oldIndexR = BMBridge.wIndexList[j + 2];
temp = BMPCApath[newIndex] - BMPCApath[oldIndexL];
temp -= (BMPCApath[oldIndexR] - BMPCApath[oldIndexL]) * BMBridge.wMuDt[newIndex];
temp /= BMBridge.wSqrtDt[newIndex];
uniformsV[newIndex] = NormalDist.cdf01( temp );
}
double dT = BMPCA.t[d] - BMPCA.t[0];
uniformsV[d] = NormalDist.cdf01( ( BMPCApath[d] - BMPCApath[0] - BMPCA.mu*dT )/
( BMPCA.sigma * Math.sqrt(dT) ) );
// Reconstruct the bridge for the GammaProcess from the Brownian uniforms.
path[0] = x0;
path[d] = x0 + GammaDist.inverseF(mu2dTOverNu, muOverNu, 10, uniformsV[d]);
for (int j = 0; j < 3*(d-1); j+=3) {
oldIndexL = wIndexList[j];
newIndex = wIndexList[j + 1];
oldIndexR = wIndexList[j + 2];
y = BetaDist.inverseF(bMu2dtOverNuL[newIndex], bMu2dtOverNuR[newIndex], 8, uniformsV[newIndex]);
path[newIndex] = path[oldIndexL] +
(path[oldIndexR] - path[oldIndexL]) * y;
}
observationIndex = d;
observationCounter = d;
return path;
}
public double[] generatePath() {
double[] u = new double[d];
for(int i =0; i < d; i++)
u[i] = stream.nextDouble();
return generatePath(u);
}
public void setParams (double s0, double mu, double nu) {
super.setParams(s0, mu, nu);
BMBridge.setParams(0.0, 0.0, Math.sqrt(nu));
BMPCA.setParams(0.0, 0.0, Math.sqrt(nu));
}
public void setObservationTimes (double[] t, int d) {
super.setObservationTimes(t, d);
BMBridge.setObservationTimes(t, d);
}
/**
* Returns the inner {@link BrownianMotionPCA}.
*
*/
public BrownianMotionPCA getBMPCA() {
return BMPCA;
}
protected void init() {
super.init();
if (observationTimesSet) {
// Quantities for gamma bridge process
bMu2dtOverNuL = new double[d+1];
bMu2dtOverNuR = new double[d+1];
wIndexList = new int[3*d];
int[] ptIndex = new int[d+1];
int indexCounter = 0;
int newIndex, oldLeft, oldRight;
ptIndex[0] = 0;
ptIndex[1] = d;
mu2OverNu = mu * mu / nu;
mu2dTOverNu = mu2OverNu * (t[d] - t[0]);
for (int powOfTwo = 1; powOfTwo <= d/2; powOfTwo *= 2) {
/* Make room in the indexing array "ptIndex" */
for (int j = powOfTwo; j >= 1; j--) { ptIndex[2*j] = ptIndex[j]; }
/* Insert new indices and Calculate constants */
for (int j = 1; j <= powOfTwo; j++) {
oldLeft = 2*j - 2;
oldRight = 2*j;
newIndex = (int) (0.5*(ptIndex[oldLeft] + ptIndex[oldRight]));
bMu2dtOverNuL[newIndex] = mu * mu
* (t[newIndex] - t[ptIndex[oldLeft]]) / nu;
bMu2dtOverNuR[newIndex] = mu * mu
* (t[ptIndex[oldRight]] - t[newIndex]) / nu;
ptIndex[oldLeft + 1] = newIndex;
wIndexList[indexCounter] = ptIndex[oldLeft];
wIndexList[indexCounter+1] = newIndex;
wIndexList[indexCounter+2] = ptIndex[oldRight];
indexCounter += 3;
}
}
/* Check if there are holes remaining and fill them */
for (int k = 1; k < d; k++) {
if (ptIndex[k-1] + 1 < ptIndex[k]) {
// there is a hole between (k-1) and k.
bMu2dtOverNuL[ptIndex[k-1]+1] = mu * mu
* (t[ptIndex[k-1]+1] - t[ptIndex[k-1]]) / nu;
bMu2dtOverNuR[ptIndex[k-1]+1] = mu * mu
* (t[ptIndex[k]] - t[ptIndex[k-1]+1]) / nu;
wIndexList[indexCounter] = ptIndex[k]-2;
wIndexList[indexCounter+1] = ptIndex[k]-1;
wIndexList[indexCounter+2] = ptIndex[k];
indexCounter += 3;
}
}
}
}
}
Ads help maintain this website.