
umontreal.iro.lecuyer.stochprocess.StochasticProcess Maven / Gradle / Ivy
Show all versions of ssj Show documentation
/*
* Class: StochasticProcess
* Description: Base class for all stochastic processes
* Environment: Java
* Software: SSJ
* Copyright (C) 2001 Pierre L'Ecuyer and Université de Montréal
* Organization: DIRO, Université de Montréal
* @author
* @since
* 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.RandomStream;
/**
* Abstract base class for a stochastic process
* {X(t) : t >= 0}
* sampled (or observed) at a finite number of time points,
*
* 0 = t0 < t1 < ... < td.
* The observation times are usually all specified before generating a sample path.
* This can be done via setObservationTimes.
* The method generatePath generates
* X(t1),..., X(td) and memorizes
* them in a vector, which can be recovered by getPath.
*
*
* Alternatively, for some types of processes, the observations X(tj) can be
* generated sequentially, one at a time, by invoking resetStartProcess
* first, and then nextObservation repeatedly.
* For some types of processes, the observation times can be specified one by one
* as well, when generating the path. This may be convenient or even necessary
* if the observation times are random, for example.
*
*
* WARNING: After having called the constructor for one of the subclass,
* one must always set the observation times of the process,
* by calling method setObservationTimes for example or otherwise.
*
*/
public abstract class StochasticProcess {
// Used in some subclasses to make sure the 'setObservationTimes'
// method has already been invoked before calling 'init'
protected boolean observationTimesSet = false;
protected double x0 = 0.0; // Default Initial Value of the process
protected int d = -1; // Num. of observation times
protected int observationIndex = 0; // Index of last generated obs time
protected int observationCounter = 0; // Counts how many observations have
// been generated so far. Useful when they are not generated in
// chronological order.
protected double[] t; // Observation times
protected double[] path; // Observations of the process
//protected RandomStream stream; // Random stream used to generate the process
protected int[] observationIndexFromCounter; // Links counter# to index#
/**
* Sets the observation times of the process to a copy of T,
* with t0 = T[0] and td = T[d].
* The size of T must be d + 1.
*
*/
public void setObservationTimes (double[] T, int d) {
if (d <= 0) throw new IllegalArgumentException (
"Number of observation times d <= 0");
this.d = d;
observationTimesSet = true;
// Copy of the observation times
this.t = new double[d+1];
System.arraycopy (T, 0, this.t, 0, d+1);
// Test chronological order
for (int i = 0; i < d; i++) {
if (T[i+1] < T[i])
throw new IllegalArgumentException (
"Observation times T[] are not time-ordered");
}
// Construction of 'path' object
// We do not do it in 'init()' because we don't have to change the
// path object if the user only calls 'setParams'
path = new double[d+1];
/* Process specific initialization; usually precomputes quantities
that depend on the observation times. */
init();
}
/**
* Sets equidistant observation times at
* tj = jδ, for
* j = 0,..., d, and delta = δ.
*
*/
public void setObservationTimes (double delta, int d) {
t = new double[d+1];
for (int i=0; i<=d; i++) t[i] = i*delta;
setObservationTimes (t, d);
}
/**
* Returns a reference to the array that contains the observation times
*
* (t0,..., td).
* Warning: This method should only be used to read the observation times.
* Changing the values in the array directly may have unexpected consequences.
* The method setObservationTimes should be used to modify the observation times.
*
*/
public double[] getObservationTimes() {
return t;
}
/**
* Returns the number of observation times excluding the time t0.
*
*/
public int getNbObservationTimes() {
return d;
}
/**
* Generates, returns, and saves the sample path
*
* {X(t0), X(t1),…, X(td)}. It can then be accessed via
* getPath, getSubpath, or getObservation.
* The generation method depends on the process type.
*
*/
public abstract double[] generatePath();
/**
* Same as generatePath(), but first resets the stream to stream.
*
*/
public double[] generatePath (RandomStream stream) {
setStream (stream);
return generatePath();
}
/**
* Returns a reference to the last generated sample path
*
* {X(t0),..., X(td)}.
* Warning: The returned array and its size should not be modified,
* because this is the one that memorizes the observations (not a copy of it).
* To obtain a copy, use getSubpath instead.
*
*/
public double[] getPath() {
return path;
}
/**
* Returns in subpath the values of the process at a subset of the observation times,
* specified as the times tj whose indices j are in the array pathIndices.
* The size of pathIndices should be at least as much as that of subpath.
*
*/
public void getSubpath (double[] subpath, int[] pathIndices) {
for (int j=0; jX(tj) from the current sample path.
* Warning: If the observation X(tj) for the current path has not yet been
* generated, then the value returned is unpredictable.
*
*/
public double getObservation (int j) {
return path[j];
}
/**
* Resets the observation counter to its initial value j = 0, so
* that the current observation X(tj) becomes X(t0). This method should
* be invoked before generating observations sequentially one by one
* via {@link #nextObservation nextObservation}, for a new sample path.
*
*/
public void resetStartProcess() {
observationIndex = 0;
observationCounter = 0;
}
/**
* Returns true if j < d, where j is the number of observations of the current
* sample path generated since the last call to {@link #resetStartProcess resetStartProcess}.
* Otherwise returns false.
*
*/
public boolean hasNextObservation() {
if (observationCounter < d) return true;
else return false;
}
/**
* Generates and returns the next observation X(tj) of the stochastic process.
* The processes are usually sampled sequentially, i.e.
* if the last observation generated was for time tj-1, the next observation
* returned will be for time tj.
* In some cases, subclasses extending this abstract class
* may use non-sequential sampling algorithms (such as bridge sampling).
* The order of generation of the tj's is then specified by the subclass.
* All the processes generated using principal components analysis (PCA) do not have
* this method.
*
*/
public double nextObservation() {
throw new UnsupportedOperationException("Method not defined in this class");
}
/**
* Returns the value of the index j corresponding to
* the time tj of the last generated observation.
*
*/
public int getCurrentObservationIndex() {
return observationIndex;
}
/**
* Returns the value of the last generated observation X(tj).
*
*/
public double getCurrentObservation() {
return path[observationIndex];
}
/**
* Returns the initial value X(t0) for this process.
*
*/
public double getX0() {
return x0;
}
/**
* Sets the initial value X(t0) for this process to s0,
* and reinitializes.
*
*/
public void setX0 (double s0) {
x0 = s0;
init();
}
/**
* Resets the random stream of the underlying generator to stream.
*
*/
public abstract void setStream (RandomStream stream);
/**
* Returns the random stream of the underlying generator.
*
*/
public abstract RandomStream getStream();
/* ** Called by 'setObservationTimes' to initialize arrays and precompute
constants to speed up execution. See overriding method 'init'
in subclasses for details ***/
protected void init() {
if (observationTimesSet) // If observation times are not defined, do nothing.
path[0] = x0;
// We do this here because the s0 parameter may have changed through
// a call to the 'setParams' method.
}
/**
* Returns a reference to an array that maps an integer k
* to ik, the index of the observation
* S(tik) corresponding
* to the k-th observation to be generated for a sample path of this process.
* If this process is sampled sequentially, then this map is trivial
* (i.e. ik = k). But it can be useful in a more general setting where
* the process is not sampled sequentially
* (for example, by a Brownian or gamma bridge) and one wants to know which
* observations of the current sample path were previously generated
* or will be generated next.
*
*/
public int[] getArrayMappingCounterToIndex() {
return observationIndexFromCounter;
}
}