All Downloads are FREE. Search and download functionalities are using the official Maven repository.

umontreal.iro.lecuyer.stochprocess.GammaProcessBridge Maven / Gradle / Ivy

Go to download

SSJ is a Java library for stochastic simulation, developed under the direction of Pierre L'Ecuyer, in the Département d'Informatique et de Recherche Opérationnelle (DIRO), at the Université de Montréal. It provides facilities for generating uniform and nonuniform random variates, computing different measures related to probability distributions, performing goodness-of-fit tests, applying quasi-Monte Carlo methods, collecting (elementary) statistics, and programming discrete-event simulations with both events and processes.

The newest version!


/*
 * Class:        GammaProcessBridge
 * Description:  
 * Environment:  Java
 * Software:     SSJ 
 * Copyright (C) 2001  Pierre L'Ecuyer and Université de Montréal
 * Organization: DIRO, Université de Montréal
 * @author       Pierre Tremblay and Jean-Sébastien Parent
 * @since        July 2003

 * SSJ is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License (GPL) as published by the
 * Free Software Foundation, either version 3 of the License, or
 * any later version.

 * SSJ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * A copy of the GNU General Public License is available at
   GPL licence site.
 */

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.Num;


/**
 * This class represents a gamma process
 * 
 * {S(t) = G(t;μ, ν) : t >= 0} with mean parameter μ and
 * variance parameter ν, sampled using the gamma bridge method
 * (see for example).
 * This is analogous to the bridge sampling used in
 * {@link BrownianMotionBridge}.
 * 
 * 

* Note that gamma bridge sampling requires not only gamma variates, but also * beta variates. The latter generally take a longer time to generate * than the former. The class GammaSymmetricalBridgeProcess provides * a faster implementation when the number of observation times * is a power of two. * *

* The warning from class {@link BrownianMotionBridge} applies verbatim * to this class. * */ public class GammaProcessBridge extends GammaProcess { protected BetaGen Bgen; protected double mu2OverNu, mu2dTOverNu; protected double[] bMu2dtOverNuL, // For precomputations for G Bridge bMu2dtOverNuR; protected int[] wIndexList; protected int bridgeCounter = -1; // Before 1st observ /** * Constructs a new GammaProcessBridge with parameters * * μ = mu, * ν = nu and initial value * S(t0) = s0. * Uses stream to generate the gamma and beta variates by inversion. * */ public GammaProcessBridge (double s0, double mu, double nu, RandomStream stream) { this (s0, mu, nu, new GammaGen (stream, new GammaDist (1.0)), new BetaGen (stream, new BetaDist (1.0, 1.0))); } /** * Constructs a new GammaProcessBridge. Uses the * random variate generators Ggen and Bgen to generate the gamma * and beta variates, respectively. Note that both generator uses the * same {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream}. Furthermore, the * parameters of the * {@link umontreal.iro.lecuyer.randvar.GammaGen GammaGen} and * {@link umontreal.iro.lecuyer.randvar.BetaGen BetaGen} objects are not * important since the implementation forces the generators to use * the correct parameters. * (as defined in). * */ public GammaProcessBridge (double s0, double mu, double nu, GammaGen Ggen, BetaGen Bgen) { super (s0, mu, nu, Ggen); this.Bgen = Bgen; this.Bgen.setStream(Ggen.getStream()); // to avoid confusion in streams this.stream = 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 = Bgen.nextDouble(stream, bMu2dtOverNuL[newIndex], bMu2dtOverNuR[newIndex], 0.0, 1.0); s = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y ; // make sure the process is strictly increasing 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]); bMu2dtOverNuR[newIndex] = mu2OverNu * (t[oldIndexR] - t[newIndex]); double y = Bgen.nextDouble(stream, bMu2dtOverNuL[newIndex], bMu2dtOverNuR[newIndex], 0.0, 1.0); s = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y ; // make sure the process is strictly increasing if (s <= path[oldIndexL]) s = setLarger (path, oldIndexL, oldIndexR); bridgeCounter++; observationIndex = newIndex; } observationCounter = bridgeCounter + 1; path[observationIndex] = s; return s; } public double[] generatePath (double[] uniform01) { int oldIndexL, oldIndexR, newIndex; double y; 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]; y = BetaDist.inverseF(bMu2dtOverNuL[newIndex], bMu2dtOverNuR[newIndex], 8, uniform01[1 + j/3]); path[newIndex] = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y; // make sure the process is strictly increasing if (path[newIndex] <= path[oldIndexL]) setLarger (path, oldIndexL, newIndex, oldIndexR); } //resetStartProcess(); observationIndex = d; observationCounter = d; return path; } public double[] generatePath() { int oldIndexL, oldIndexR, newIndex; double y; 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]; y = Bgen.nextDouble(stream, bMu2dtOverNuL[newIndex], bMu2dtOverNuR[newIndex], 0.0, 1.0); path[newIndex] = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y; // make sure the process is strictly increasing if (path[newIndex] <= path[oldIndexL]) setLarger (path, oldIndexL, newIndex, oldIndexR); } //resetStartProcess(); observationIndex = d; observationCounter = d; return path; } public void resetStartProcess() { observationIndex = 0; observationCounter = 0; bridgeCounter = -1; } 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; } } } } /** * Resets the {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream} * of the {@link umontreal.iro.lecuyer.randvar.GammaGen GammaGen} and * the {@link umontreal.iro.lecuyer.randvar.BetaGen BetaGen} to stream. * */ public void setStream (RandomStream stream) { super.setStream(stream); this.Bgen.setStream(stream); this.stream = stream; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy