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

net.finmath.marketdata2.interpolation.RationalFunctionInterpolation Maven / Gradle / Ivy

Go to download

finmath lib is a Mathematical Finance Library in Java. It provides algorithms and methodologies related to mathematical finance.

There is a newer version: 6.0.19
Show newest version
/*
 * (c) Copyright Christian P. Fries, Germany. Contact: [email protected].
 *
 * Created on 28.05.2004
 */
package net.finmath.marketdata2.interpolation;

import java.io.IOException;

import net.finmath.montecarlo.RandomVariableFromDoubleArray;
//import net.finmath.interpolation.RationalFunctionInterpolation.RationalFunction;
import net.finmath.stochastic.RandomVariable;

/**
 * This class provides methodologies to interpolate given sample points by
 * rational functions, that is, given interpolation points (xi,yi)
 * the class provides a continuous function y = f(x) where
 * 
    *
  • * f(xi) = yi and *
  • *
  • * for xi < x < xi+1 the function is a fraction of two polynomes * f(x) = (sum aj xj) / (sum bk xk). *
  • *
* * This setup comprises linear interpolation (for which the function is C0) and * cubic spline interpolation (for which the function is C1). * * @author Christian Fries * @version 1.3 */ public class RationalFunctionInterpolation { public enum InterpolationMethod { /** Constant interpolation. Synonym of PIECEWISE_CONSTANT_LEFTPOINT. **/ PIECEWISE_CONSTANT, /** Constant interpolation. Right continuous, i.e. using the value of the left end point of the interval. **/ PIECEWISE_CONSTANT_LEFTPOINT, /** Constant interpolation using the value of the right end point of the interval. **/ PIECEWISE_CONSTANT_RIGHTPOINT, /** Linear interpolation. **/ LINEAR, /** Cubic spline interpolation. **/ CUBIC_SPLINE, /** Akima interpolation (C1 sub-spline interpolation). **/ AKIMA, /** Akima interpolation (C1 sub-spline interpolation) with a smoothing in the weights. **/ AKIMA_CONTINUOUS, /** Harmonic spline interpolation (C1 sub-spline interpolation). **/ HARMONIC_SPLINE, /** Harmonic spline interpolation (C1 sub-spline interpolation) with a monotonic filtering at the boundary points. **/ HARMONIC_SPLINE_WITH_MONOTONIC_FILTERING } public enum ExtrapolationMethod { /** Extrapolation using the interpolation function of the adjacent interval **/ DEFAULT, /** Constant extrapolation. **/ CONSTANT, /** Linear extrapolation. **/ LINEAR } // The curve to interpolate private final double[] points; // times (i.e. double[]) private final RandomVariable[] values; private InterpolationMethod interpolationMethod = InterpolationMethod.LINEAR; private ExtrapolationMethod extrapolationMethod = ExtrapolationMethod.DEFAULT; private static class RationalFunction { private final RandomVariable[] coefficientsNumerator; private final RandomVariable[] coefficientsDenominator; /** * Create a rational interpolation function. * * @param coefficientsNumerator The coefficients of the polynomial of the numerator, in increasing order. * @param coefficientsDenominator The coefficients of the polynomial of the denominator, in increasing order. */ RationalFunction(final RandomVariable[] coefficientsNumerator, final RandomVariable[]coefficientsDenominator) { super(); this.coefficientsNumerator = coefficientsNumerator; this.coefficientsDenominator = coefficientsDenominator; } /** * Create a polynomial interpolation function. * * @param coefficients The coefficients of the polynomial, in increasing order. */ RationalFunction(final RandomVariable[] coefficients) { super(); coefficientsNumerator = coefficients; coefficientsDenominator = null; } /** * Returns the value for a given arguments. * * @param x Given argument. * @return Returns the value for the given argument. */ public RandomVariable getValue(final double x) { RandomVariable powerOfX = new RandomVariableFromDoubleArray(1.0); RandomVariable valueNumerator = coefficientsNumerator[0]; for (int i = 1; ii sample points of a function y=f(x). * @param values The corresponding array of the yi sample values to the sample points xi. */ public RationalFunctionInterpolation(final double[] points, final RandomVariable[] values) { super(); this.points = points; this.values = values; } /** * Generate a rational function interpolation from a given set of points using * the specified interpolation and extrapolation method. * * @param points The array of the xi sample points of a function y=f(x). * @param values The corresponding array of the yi sample values to the sample points xi. * @param interpolationMethod The interpolation method to be used. * @param extrapolationMethod The extrapolation method to be used. */ public RationalFunctionInterpolation(final double[] points, final RandomVariable[] values, final InterpolationMethod interpolationMethod, final ExtrapolationMethod extrapolationMethod) { super(); this.points = points; this.values = values; this.interpolationMethod = interpolationMethod; this.extrapolationMethod = extrapolationMethod; } /** * Returns the interpolation method used. * * @return Returns the interpolationMethod. */ public InterpolationMethod getInterpolationMethod() { return interpolationMethod; } /** * Get an interpolated value for a given argument x. * * @param x The abscissa at which the interpolation should be performed. * @return The interpolated value (ordinate). */ public RandomVariable getValue(final double x) // x is time { synchronized(interpolatingRationalFunctionsLazyInitLock) { if(interpolatingRationalFunctions == null) { doCreateRationalFunctions(); } } // Get interpolating rational function for the given point x final int pointIndex = java.util.Arrays.binarySearch(points, x); if(pointIndex >= 0) { return values[pointIndex]; } int intervalIndex = -pointIndex-2; // Check for extrapolation if(intervalIndex < 0) { // Extrapolation if(extrapolationMethod == ExtrapolationMethod.CONSTANT) { return values[0]; } else if(extrapolationMethod == ExtrapolationMethod.LINEAR) { return values[0].add((values[1].sub(values[0])).div(points[1]-points[0]).mult(x-points[0])); } else { intervalIndex = 0; } } else if(intervalIndex > points.length-2) { // Extrapolation if(extrapolationMethod == ExtrapolationMethod.CONSTANT) { return values[points.length-1]; } else if(extrapolationMethod == ExtrapolationMethod.LINEAR) { return values[points.length-1].add((values[points.length-2].sub(values[points.length-1])).div(points[points.length-2]-points[points.length-1]).mult(x-points[points.length-1])); } else { intervalIndex = points.length-2; } } final RationalFunction rationalFunction = interpolatingRationalFunctions[intervalIndex]; // Calculate interpolating value return rationalFunction.getValue(x-points[intervalIndex]); } private void readObject(final java.io.ObjectInputStream in) throws ClassNotFoundException, IOException { in.defaultReadObject(); // initialization of transients interpolatingRationalFunctionsLazyInitLock = new Object(); } private void doCreateRationalFunctions() { switch(interpolationMethod) { case PIECEWISE_CONSTANT: case PIECEWISE_CONSTANT_LEFTPOINT: case PIECEWISE_CONSTANT_RIGHTPOINT: doCreateRationalFunctionsForPiecewiseConstantInterpolation(); break; case LINEAR: default: doCreateRationalFunctionsForLinearInterpolation(); break; } } private void doCreateRationalFunctionsForPiecewiseConstantInterpolation() { /* * Generate a rational function for each given interval */ interpolatingRationalFunctions = new RationalFunction[points.length-1]; // create numerator polynomials (constant) for(int pointIndex = 0; pointIndex < points.length-1; pointIndex++ ) { RandomVariable[] numeratorPolynomCoeff; if (interpolationMethod == InterpolationMethod.PIECEWISE_CONSTANT_RIGHTPOINT) { numeratorPolynomCoeff = new RandomVariable[] {values[pointIndex+1]}; } else { numeratorPolynomCoeff = new RandomVariable[] {values[pointIndex]}; } interpolatingRationalFunctions[pointIndex] = new RationalFunction(numeratorPolynomCoeff); } } private void doCreateRationalFunctionsForLinearInterpolation() { /* * Generate a rational function for each given interval */ interpolatingRationalFunctions = new RationalFunction[points.length-1]; // create numerator polynomials (linear) for(int pointIndex = 0; pointIndex < points.length-1; pointIndex++ ) { final RandomVariable[] numeratorPolynomCoeff = new RandomVariable[2]; final double xl = points[pointIndex]; final double xr = points[pointIndex+1]; final RandomVariable fl = values[pointIndex]; final RandomVariable fr = values[pointIndex+1]; numeratorPolynomCoeff[1] = fr.sub(fl).div(xr-xl); numeratorPolynomCoeff[0] = fl; interpolatingRationalFunctions[pointIndex] = new RationalFunction(numeratorPolynomCoeff); } } /* private void doCreateRationalFunctionsForHarmonicSplineInterpolation(){ int numberOfPoints = points.length; // Calculate parameters double[] step = new double[numberOfPoints-1]; double[] slope = new double[numberOfPoints-1]; double[] doubleStep = new double[numberOfPoints-2]; for(int i = 0; i < numberOfPoints-1; i++){ step[i] = (points[i+1] - points[i]); slope[i] = (values[i+1] - values[i]) / step[i]; if(i > 0){ doubleStep[i-1] = points[i+1] - points[i-1]; } } // Calculate first derivatives ... double[] derivative = new double[numberOfPoints]; // ... for boundary points: // in t_0 derivative[0] =(2*step[0] + step[1])/doubleStep[0] * slope[0] - step[0]/doubleStep[0] * slope[1]; // in t_n derivative[numberOfPoints-1] =(2*step[numberOfPoints-2] + step[numberOfPoints-3])/doubleStep[numberOfPoints-3] * slope[numberOfPoints-2] - step[numberOfPoints-2]/doubleStep[numberOfPoints-3] * slope[numberOfPoints-3]; // monotonicity filtering if(interpolationMethod == InterpolationMethod.HARMONIC_SPLINE_WITH_MONOTONIC_FILTERING){ // in t_0 if((derivative[0]*slope[0] > 0) && (slope[0]*slope[1] <= 0) && (Math.abs(derivative[0]) < 3*Math.abs(slope[0]))) derivative[0] = 3 * slope[0]; if( derivative[0]*slope[0] <= 0 ) derivative[0] = 0; // in t_n if((derivative[numberOfPoints-1]*slope[numberOfPoints-2] > 0) && (slope[numberOfPoints-2]*slope[numberOfPoints-3] <= 0) && (Math.abs(derivative[numberOfPoints-1]) < 3*Math.abs(slope[numberOfPoints-2]))) derivative[numberOfPoints-1] = 3 * slope[numberOfPoints-2]; if( derivative[numberOfPoints-1]*slope[numberOfPoints-2] <= 0 ) derivative[numberOfPoints-1] = 0; } // ... for inner points: for(int i = 1; i < numberOfPoints-1; i++){ if( slope[i-1] * slope[i] <= 0 ){ derivative[i] = 0; } else{ double weightedHarmonicMean = (step[i-1] + 2*step[i]) / (3*doubleStep[i-1]*slope[i-1]) + (2*step[i-1] + step[i]) / (3*doubleStep[i-1]*slope[i]); derivative[i] = 1.0 / weightedHarmonicMean; } } interpolatingRationalFunctions = new RationalFunction[numberOfPoints-1]; // create numerator polynomials (third order polynomial) for(int i = 0; i < numberOfPoints-1; i++ ) { double[] numeratortorPolynomCoeff = new double[4]; numeratortorPolynomCoeff[0] = values[i]; numeratortorPolynomCoeff[1] = derivative[i]; numeratortorPolynomCoeff[2] = (3*slope[i] - 2*derivative[i] - derivative[i+1]) / step[i]; numeratortorPolynomCoeff[3] = (derivative[i] + derivative[i+1] - 2*slope[i]) / (step[i] * step[i]); interpolatingRationalFunctions[i] = new RationalFunction(numeratortorPolynomCoeff); } } */ }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy