net.finmath.montecarlo.BrownianBridge Maven / Gradle / Ivy
Show all versions of finmath-lib Show documentation
/*
* (c) Copyright Christian P. Fries, Germany. Contact: [email protected].
*
* Created on 23.11.2013
*/
package net.finmath.montecarlo;
import java.io.IOException;
import java.util.Arrays;
import net.finmath.stochastic.RandomVariable;
import net.finmath.time.TimeDiscretization;
/**
* This class implements a Brownian bridge, i.e., samples of realizations of a Brownian motion
* conditional to a given start and end value.
*
*
* A Brownian bridge is a conditional Brownian motion, i.e. for given random variables
* X and Y the Brownian bridge is
*
* (W(t) | W(s) = X , W(T) = Y),
*
* where W is a Brownian motion and s ≤ t ≤ T.
*
*
* The samples of the Brownian bridge are generated by a Brownian motion which will be used to fill the gap between start and end.
* It is important that this Browninan motion is independent from the one which generated start and end, i.e. here: it should have a different seed.
*
*
* The class implements the {@code BrownianMotion}, i.e., it only provides the increments
* of the Brownian bridge (however, in most application, like refinement of an Euler-scheme, this is
* exactly the desired object).
*
*
* Note: The number of paths needs to be specified, because the start and the end point
* may be not stochastic, i.e. it is not possible to infer this quantity
* from the specified start and end.
*
*
* @author Christian Fries
* @date 24.11.2013
* @version 1.0
*/
public class BrownianBridge implements BrownianMotion {
private final BrownianMotion generator;
private final RandomVariable[] start;
private final RandomVariable[] end;
private final RandomVariableFactory randomVariableFactory = new RandomVariableFromArrayFactory();
private transient RandomVariable[][] brownianIncrements;
private transient Object brownianIncrementsLazyInitLock = new Object();
public BrownianBridge(final BrownianMotion generator, final RandomVariable[] start, final RandomVariable[] end) {
this.generator = generator;
this.start = start;
this.end = end;
}
/**
* Construct a Brownian bridge, bridging from a given start to a given end.
*
* @param timeDiscretization The time discretization used for the Brownian increments.
* @param numberOfPaths Number of paths to simulate.
* @param seed The seed of the random number generator.
* @param start Start value of the Brownian bridge.
* @param end End value of the Brownian bridge.
*/
public BrownianBridge(final TimeDiscretization timeDiscretization, final int numberOfPaths, final int seed, final RandomVariable[] start, final RandomVariable[] end) {
this(new BrownianMotionFromMersenneRandomNumbers(timeDiscretization, start.length, numberOfPaths, seed), start, end);
}
/**
* Construct a Brownian bridge, bridging from a given start to a given end.
*
* @param timeDiscretization The time discretization used for the Brownian increments.
* @param numberOfPaths Number of paths to simulate.
* @param seed The seed of the random number generator.
* @param start Start value of the Brownian bridge.
* @param end End value of the Brownian bridge.
*/
public BrownianBridge(final TimeDiscretization timeDiscretization, final int numberOfPaths, final int seed, final RandomVariable start, final RandomVariable end) {
this(timeDiscretization, numberOfPaths, seed, new RandomVariable[] {start}, new RandomVariable[] {end});
}
@Override
public RandomVariable getBrownianIncrement(final int timeIndex, final int factor) {
// Thread safe lazy initialization
synchronized(brownianIncrementsLazyInitLock) {
if(brownianIncrements == null) {
doGenerateBrownianMotion();
}
}
/*
* For performance reasons we return directly the stored data (no defensive copy).
* We return an immutable object to ensure that the receiver does not alter the data.
*/
return brownianIncrements[timeIndex][factor];
}
/**
* Lazy initialization of brownianIncrement. Synchronized to ensure thread safety of lazy init.
*/
private void doGenerateBrownianMotion() {
if(brownianIncrements != null)
{
return; // Nothing to do
}
// Allocate memory
brownianIncrements = new RandomVariable[generator.getTimeDiscretization().getNumberOfTimeSteps()][generator.getNumberOfFactors()];
final double endTime = getTimeDiscretization().getTime(getTimeDiscretization().getNumberOfTimeSteps());
for(int factor=0; factor