MultiSegmentSequenceModifier.java

  1. package org.drip.spline.stretch;

  2. /*
  3.  * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  4.  */

  5. /*!
  6.  * Copyright (C) 2020 Lakshmi Krishnamurthy
  7.  * Copyright (C) 2019 Lakshmi Krishnamurthy
  8.  * Copyright (C) 2018 Lakshmi Krishnamurthy
  9.  * Copyright (C) 2017 Lakshmi Krishnamurthy
  10.  * Copyright (C) 2016 Lakshmi Krishnamurthy
  11.  * Copyright (C) 2015 Lakshmi Krishnamurthy
  12.  * Copyright (C) 2014 Lakshmi Krishnamurthy
  13.  * Copyright (C) 2013 Lakshmi Krishnamurthy
  14.  *
  15.  *  This file is part of DROP, an open-source library targeting analytics/risk, transaction cost analytics,
  16.  *      asset liability management analytics, capital, exposure, and margin analytics, valuation adjustment
  17.  *      analytics, and portfolio construction analytics within and across fixed income, credit, commodity,
  18.  *      equity, FX, and structured products. It also includes auxiliary libraries for algorithm support,
  19.  *      numerical analysis, numerical optimization, spline builder, model validation, statistical learning,
  20.  *      and computational support.
  21.  *  
  22.  *      https://lakshmidrip.github.io/DROP/
  23.  *  
  24.  *  DROP is composed of three modules:
  25.  *  
  26.  *  - DROP Product Core - https://lakshmidrip.github.io/DROP-Product-Core/
  27.  *  - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/
  28.  *  - DROP Computational Core - https://lakshmidrip.github.io/DROP-Computational-Core/
  29.  *
  30.  *  DROP Product Core implements libraries for the following:
  31.  *  - Fixed Income Analytics
  32.  *  - Loan Analytics
  33.  *  - Transaction Cost Analytics
  34.  *
  35.  *  DROP Portfolio Core implements libraries for the following:
  36.  *  - Asset Allocation Analytics
  37.  *  - Asset Liability Management Analytics
  38.  *  - Capital Estimation Analytics
  39.  *  - Exposure Analytics
  40.  *  - Margin Analytics
  41.  *  - XVA Analytics
  42.  *
  43.  *  DROP Computational Core implements libraries for the following:
  44.  *  - Algorithm Support
  45.  *  - Computation Support
  46.  *  - Function Analysis
  47.  *  - Model Validation
  48.  *  - Numerical Analysis
  49.  *  - Numerical Optimizer
  50.  *  - Spline Builder
  51.  *  - Statistical Learning
  52.  *
  53.  *  Documentation for DROP is Spread Over:
  54.  *
  55.  *  - Main                     => https://lakshmidrip.github.io/DROP/
  56.  *  - Wiki                     => https://github.com/lakshmiDRIP/DROP/wiki
  57.  *  - GitHub                   => https://github.com/lakshmiDRIP/DROP
  58.  *  - Repo Layout Taxonomy     => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md
  59.  *  - Javadoc                  => https://lakshmidrip.github.io/DROP/Javadoc/index.html
  60.  *  - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal
  61.  *  - Release Versions         => https://lakshmidrip.github.io/DROP/version.html
  62.  *  - Community Credits        => https://lakshmidrip.github.io/DROP/credits.html
  63.  *  - Issues Catalog           => https://github.com/lakshmiDRIP/DROP/issues
  64.  *  - JUnit                    => https://lakshmidrip.github.io/DROP/junit/index.html
  65.  *  - Jacoco                   => https://lakshmidrip.github.io/DROP/jacoco/index.html
  66.  *
  67.  *  Licensed under the Apache License, Version 2.0 (the "License");
  68.  *      you may not use this file except in compliance with the License.
  69.  *  
  70.  *  You may obtain a copy of the License at
  71.  *      http://www.apache.org/licenses/LICENSE-2.0
  72.  *  
  73.  *  Unless required by applicable law or agreed to in writing, software
  74.  *      distributed under the License is distributed on an "AS IS" BASIS,
  75.  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  76.  *  
  77.  *  See the License for the specific language governing permissions and
  78.  *      limitations under the License.
  79.  */

  80. /**
  81.  * <i>MultiSegmentSequenceModifier</i> exports Stretch modification/alteration methods to generate customized
  82.  * basis splines, with customized segment behavior using the segment control. It exposes the following
  83.  * stretch modification methods:
  84.  *
  85.  * <br><br>
  86.  *  <ul>
  87.  *      <li>
  88.  *          Insert the specified Predictor Ordinate Knot into the specified Stretch, using the specified
  89.  *              Response Value
  90.  *      </li>
  91.  *      <li>
  92.  *          Append a Segment to the Right of the Specified Stretch using the Supplied Constraint
  93.  *      </li>
  94.  *      <li>
  95.  *          Insert the Predictor Ordinate Knot into the specified Stretch
  96.  *      </li>
  97.  *      <li>
  98.  *          Insert a Cardinal Knot into the specified Stretch at the specified Predictor Ordinate Location
  99.  *      </li>
  100.  *      <li>
  101.  *          Insert a Catmull-Rom Knot into the specified Stretch at the specified Predictor Ordinate Location
  102.  *      </li>
  103.  *  </ul>
  104.  *
  105.  * <br><br>
  106.  *  <ul>
  107.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ComputationalCore.md">Computational Core Module</a></li>
  108.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/SplineBuilderLibrary.md">Spline Builder Library</a></li>
  109.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/spline/README.md">Basis Splines and Linear Compounders across a Broad Family of Spline Basis Functions</a></li>
  110.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/spline/stretch/README.md">Multi-Segment Sequence Spline Stretch</a></li>
  111.  *  </ul>
  112.  * <br><br>
  113.  *
  114.  * @author Lakshmi Krishnamurthy
  115.  */

  116. public class MultiSegmentSequenceModifier {

  117.     /**
  118.      * Insert the specified Predictor Ordinate Knot into the specified Stretch, using the specified Response
  119.      *  Value
  120.      *
  121.      * @param mssIn Input Stretch
  122.      * @param dblPredictorOrdinate Predictor Ordinate Knot
  123.      * @param dblResponseValue Response Value
  124.      * @param bs The Calibration Boundary Condition
  125.      * @param iCalibrationDetail The Calibration Detail
  126.      *
  127.      * @return The Stretch with the Knot inserted
  128.      */

  129.     public static final org.drip.spline.stretch.MultiSegmentSequence InsertKnot (
  130.         final org.drip.spline.stretch.MultiSegmentSequence mssIn,
  131.         final double dblPredictorOrdinate,
  132.         final double dblResponseValue,
  133.         final org.drip.spline.stretch.BoundarySettings bs,
  134.         final int iCalibrationDetail)
  135.     {
  136.         if (!org.drip.numerical.common.NumberUtil.IsValid (dblPredictorOrdinate) ||
  137.             !org.drip.numerical.common.NumberUtil.IsValid (dblResponseValue) || null == mssIn || mssIn.isKnot
  138.                 (dblPredictorOrdinate))
  139.             return null;

  140.         org.drip.spline.segment.LatentStateResponseModel[] aCS = mssIn.segments();

  141.         int iNewIndex = 0;
  142.         int iNumSegmentIn = aCS.length;
  143.         double[] adblResponseValue = new double[iNumSegmentIn + 2];
  144.         double[] adblPredictorOrdinate = new double[iNumSegmentIn + 2];
  145.         org.drip.spline.params.SegmentCustomBuilderControl[] aSCBCOut = new
  146.             org.drip.spline.params.SegmentCustomBuilderControl[iNumSegmentIn + 1];

  147.         org.drip.spline.params.SegmentCustomBuilderControl[] aSCBCIn = mssIn.segmentBuilderControl();

  148.         if (dblPredictorOrdinate < aCS[0].left()) {
  149.             adblPredictorOrdinate[iNewIndex] = dblPredictorOrdinate;
  150.             adblResponseValue[iNewIndex] = dblResponseValue;
  151.             aSCBCOut[iNewIndex++] = aSCBCIn[0];
  152.         }

  153.         for (int i = 0; i < iNumSegmentIn; ++i) {
  154.             aSCBCOut[iNewIndex] = aSCBCIn[i];

  155.             adblPredictorOrdinate[iNewIndex] = aCS[i].left();

  156.             try {
  157.                 adblResponseValue[iNewIndex++] = mssIn.responseValue (aCS[i].left());
  158.             } catch (java.lang.Exception e) {
  159.                 e.printStackTrace();

  160.                 return null;
  161.             }

  162.             if (dblPredictorOrdinate > aCS[i].left() && dblPredictorOrdinate < aCS[i].right()) {
  163.                 adblPredictorOrdinate[iNewIndex] = dblPredictorOrdinate;
  164.                 adblResponseValue[iNewIndex] = dblResponseValue;
  165.                 aSCBCOut[iNewIndex++] = aSCBCIn[i];
  166.             }
  167.         }

  168.         adblPredictorOrdinate[iNewIndex] = aCS[iNumSegmentIn - 1].right();

  169.         try {
  170.             adblResponseValue[iNewIndex++] = mssIn.responseValue (aCS[iNumSegmentIn - 1].right());
  171.         } catch (java.lang.Exception e) {
  172.             e.printStackTrace();

  173.             return null;
  174.         }

  175.         if (dblPredictorOrdinate > aCS[iNumSegmentIn - 1].right()) {
  176.             adblResponseValue[iNewIndex] = dblResponseValue;
  177.             adblPredictorOrdinate[iNewIndex] = dblPredictorOrdinate;
  178.             aSCBCOut[aSCBCOut.length - 1] = aSCBCIn[aSCBCIn.length - 1];
  179.         }

  180.         return org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  181.             (mssIn.name(), adblPredictorOrdinate, adblResponseValue, aSCBCOut, null, bs, iCalibrationDetail);
  182.     }

  183.     /**
  184.      * Append a Segment to the Right of the Specified Stretch using the Supplied Constraint
  185.      *
  186.      * @param mssIn Input Stretch
  187.      * @param dblPredictorOrdinateAppendRight The Predictor Ordinate at the Right Edge of the Segment to be
  188.      *  appended
  189.      * @param srvc The Segment Response Value Constraint
  190.      * @param scbc Segment Builder Parameters
  191.      * @param bs The Calibration Boundary Condition
  192.      * @param iCalibrationDetail The Calibration Detail
  193.      *
  194.      * @return The Stretch with the Segment Appended
  195.      */

  196.     public static final org.drip.spline.stretch.MultiSegmentSequence AppendSegment (
  197.         final org.drip.spline.stretch.MultiSegmentSequence mssIn,
  198.         final double dblPredictorOrdinateAppendRight,
  199.         final org.drip.spline.params.SegmentResponseValueConstraint srvc,
  200.         final org.drip.spline.params.SegmentCustomBuilderControl scbc,
  201.         final org.drip.spline.stretch.BoundarySettings bs,
  202.         final int iCalibrationDetail)
  203.     {
  204.         if (null == mssIn || null == srvc || null == scbc || !org.drip.numerical.common.NumberUtil.IsValid
  205.             (dblPredictorOrdinateAppendRight))
  206.             return null;

  207.         double dblStretchPredictorOrdinateRight = mssIn.getRightPredictorOrdinateEdge();

  208.         double[] adblConstraintOrdinate = srvc.predictorOrdinates();

  209.         for (int i = 0; i < adblConstraintOrdinate.length; ++i) {
  210.             if (adblConstraintOrdinate[i] <= dblStretchPredictorOrdinateRight) return null;
  211.         }

  212.         org.drip.spline.segment.LatentStateResponseModel[] aCS = mssIn.segments();

  213.         org.drip.spline.params.SegmentCustomBuilderControl[] aSCBCIn = mssIn.segmentBuilderControl();

  214.         int iNumSegmentIn = aCS.length;
  215.         double dblStretchResponseValueLeft = java.lang.Double.NaN;
  216.         double[] adblPredictorOrdinateOut = new double[iNumSegmentIn + 2];
  217.         org.drip.spline.params.SegmentCustomBuilderControl[] aSCBCOut = new
  218.             org.drip.spline.params.SegmentCustomBuilderControl[iNumSegmentIn + 1];
  219.         org.drip.spline.params.SegmentResponseValueConstraint[] aSRVCOut = new
  220.             org.drip.spline.params.SegmentResponseValueConstraint[iNumSegmentIn + 1];

  221.         try {
  222.             dblStretchResponseValueLeft = mssIn.responseValue (mssIn.getLeftPredictorOrdinateEdge());
  223.         } catch (java.lang.Exception e) {
  224.             e.printStackTrace();

  225.             return null;
  226.         }

  227.         for (int i = 0; i < iNumSegmentIn; ++i) {
  228.             aSCBCOut[i] = aSCBCIn[i];

  229.             adblPredictorOrdinateOut[i] = aCS[i].left();

  230.             double dblPredictorOrdinateRight = aCS[i].right();

  231.             try {
  232.                 aSRVCOut[i] = new org.drip.spline.params.SegmentResponseValueConstraint (new double[]
  233.                     {dblPredictorOrdinateRight}, new double[] {1.}, mssIn.responseValue
  234.                         (dblPredictorOrdinateRight));
  235.             } catch (java.lang.Exception e) {
  236.                 e.printStackTrace();

  237.                 return null;
  238.             }
  239.         }

  240.         aSRVCOut[iNumSegmentIn] = srvc;
  241.         aSCBCOut[iNumSegmentIn] = scbc;
  242.         adblPredictorOrdinateOut[iNumSegmentIn + 1] = dblPredictorOrdinateAppendRight;

  243.         adblPredictorOrdinateOut[iNumSegmentIn] = aCS[iNumSegmentIn - 1].right();

  244.         return org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  245.             (mssIn.name(), adblPredictorOrdinateOut, dblStretchResponseValueLeft, aSRVCOut, aSCBCOut, null,
  246.                 bs, iCalibrationDetail);
  247.     }

  248.     /**
  249.      * Insert the Predictor Ordinate Knot into the specified Stretch
  250.      *
  251.      * @param mssIn Input Stretch
  252.      * @param dblPredictorOrdinate Knot Predictor Ordinate
  253.      * @param sprdLeftSegmentRightEdge Response Values for the Right Edge of the Left Segment
  254.      * @param sprdRightSegmentLeftEdge Response Values for the Left Edge of the Right segment
  255.      *
  256.      * @return The Stretch with the Predictor Ordinate Knot inserted
  257.      */

  258.     public static final org.drip.spline.stretch.MultiSegmentSequence InsertKnot (
  259.         final org.drip.spline.stretch.MultiSegmentSequence mssIn,
  260.         final double dblPredictorOrdinate,
  261.         final org.drip.spline.params.SegmentPredictorResponseDerivative sprdLeftSegmentRightEdge,
  262.         final org.drip.spline.params.SegmentPredictorResponseDerivative sprdRightSegmentLeftEdge)
  263.     {
  264.         if (!org.drip.numerical.common.NumberUtil.IsValid (dblPredictorOrdinate) || null == mssIn ||
  265.             mssIn.isKnot (dblPredictorOrdinate) || null == sprdLeftSegmentRightEdge || null ==
  266.                 sprdRightSegmentLeftEdge)
  267.             return null;

  268.         org.drip.spline.segment.LatentStateResponseModel[] aCSIn = mssIn.segments();

  269.         int iOutSegmentIndex = 1;
  270.         int iNumSegmentIn = aCSIn.length;
  271.         double[] adblPredictorOrdinateOut = new double[iNumSegmentIn + 2];
  272.         org.drip.spline.params.SegmentPredictorResponseDerivative[] aSPRDOutLeft = new
  273.             org.drip.spline.params.SegmentPredictorResponseDerivative[iNumSegmentIn + 1];
  274.         org.drip.spline.params.SegmentPredictorResponseDerivative[] aSPRDOutRight = new
  275.             org.drip.spline.params.SegmentPredictorResponseDerivative[iNumSegmentIn + 1];
  276.         org.drip.spline.params.SegmentCustomBuilderControl[] aSCBCOut = new
  277.             org.drip.spline.params.SegmentCustomBuilderControl[iNumSegmentIn + 1];

  278.         if (dblPredictorOrdinate < aCSIn[0].left() || dblPredictorOrdinate >
  279.             aCSIn[iNumSegmentIn - 1].right())
  280.             return null;

  281.         adblPredictorOrdinateOut[0] = aCSIn[0].left();

  282.         org.drip.spline.params.SegmentCustomBuilderControl[] aSCBCIn = mssIn.segmentBuilderControl();

  283.         for (int i = 0; i < iNumSegmentIn; ++i) {
  284.             aSCBCOut[iOutSegmentIndex - 1] = aSCBCIn[i];

  285.             aSPRDOutLeft[iOutSegmentIndex - 1] = mssIn.calcSPRD (aCSIn[i].left());

  286.             if (dblPredictorOrdinate > aCSIn[i].left() && dblPredictorOrdinate < aCSIn[i].right()) {
  287.                 aSPRDOutRight[iOutSegmentIndex - 1] = sprdLeftSegmentRightEdge;
  288.                 adblPredictorOrdinateOut[iOutSegmentIndex++] = dblPredictorOrdinate;
  289.                 aSCBCOut[iOutSegmentIndex - 1] = aSCBCIn[i];
  290.                 aSPRDOutLeft[iOutSegmentIndex - 1] = sprdRightSegmentLeftEdge;
  291.             }

  292.             aSPRDOutRight[iOutSegmentIndex - 1] = mssIn.calcSPRD (aCSIn[i].right());

  293.             adblPredictorOrdinateOut[iOutSegmentIndex++] = aCSIn[i].right();
  294.         }

  295.         org.drip.spline.stretch.MultiSegmentSequence mssOut =
  296.             org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateUncalibratedStretchEstimator
  297.                 (mssIn.name(), adblPredictorOrdinateOut, aSCBCOut);

  298.         if (null == mssOut) return null;

  299.         return mssOut.setupHermite (aSPRDOutLeft, aSPRDOutRight, null, null,
  300.             org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE) ? mssOut : null;
  301.     }

  302.     /**
  303.      * Insert a Cardinal Knot into the specified Stretch at the specified Predictor Ordinate Location
  304.      *
  305.      * @param mssIn Input Stretch
  306.      * @param dblPredictorOrdinate Knot Predictor Ordinate
  307.      * @param dblCardinalTension Cardinal Tension Parameter
  308.      *
  309.      * @return The Stretch with the Knot inserted
  310.      */

  311.     public static final org.drip.spline.stretch.MultiSegmentSequence InsertCardinalKnot (
  312.         final org.drip.spline.stretch.MultiSegmentSequence mssIn,
  313.         final double dblPredictorOrdinate,
  314.         final double dblCardinalTension)
  315.     {
  316.         if (!org.drip.numerical.common.NumberUtil.IsValid (dblPredictorOrdinate) ||
  317.             !org.drip.numerical.common.NumberUtil.IsValid (dblCardinalTension) || null == mssIn || mssIn.isKnot
  318.                 (dblPredictorOrdinate))
  319.             return null;

  320.         org.drip.spline.segment.LatentStateResponseModel[] aCSIn = mssIn.segments();

  321.         int iOutSegmentIndex = 0;
  322.         int iNumSegmentIn = aCSIn.length;

  323.         if (dblPredictorOrdinate < aCSIn[0].left() || dblPredictorOrdinate >
  324.             aCSIn[iNumSegmentIn - 1].right())
  325.             return null;

  326.         for (; iOutSegmentIndex < iNumSegmentIn; ++iOutSegmentIndex) {
  327.             if (dblPredictorOrdinate > aCSIn[iOutSegmentIndex].left() && dblPredictorOrdinate <
  328.                 aCSIn[iOutSegmentIndex].right())
  329.                 break;
  330.         }

  331.         org.drip.spline.params.SegmentPredictorResponseDerivative sprdCardinalOut =
  332.             org.drip.spline.params.SegmentPredictorResponseDerivative.CardinalEdgeAggregate
  333.                 (mssIn.calcSPRD (aCSIn[iOutSegmentIndex].left()), mssIn.calcSPRD
  334.                     (aCSIn[iOutSegmentIndex].right()), dblCardinalTension);

  335.         return null == sprdCardinalOut ? null : InsertKnot (mssIn, dblPredictorOrdinate, sprdCardinalOut,
  336.             sprdCardinalOut);
  337.     }

  338.     /**
  339.      * Insert a Catmull-Rom Knot into the specified Stretch at the specified Predictor Ordinate Location
  340.      *
  341.      * @param mssIn Input Stretch
  342.      * @param dblPredictorOrdinate Knot Predictor Ordinate
  343.      *
  344.      * @return The Stretch with the Knot inserted
  345.      */

  346.     public static final org.drip.spline.stretch.MultiSegmentSequence InsertCatmullRomKnot (
  347.         final org.drip.spline.stretch.MultiSegmentSequence mssIn,
  348.         final double dblPredictorOrdinate)
  349.     {
  350.         return InsertCardinalKnot (mssIn, dblPredictorOrdinate, 0.);
  351.     }
  352. }