OptimizationFramework.java

  1. package org.drip.optimization.constrained;

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

  77. /**
  78.  * <i>OptimizationFramework</i> holds the Non Linear Objective Function and the Collection of Equality and
  79.  * the Inequality Constraints that correspond to the Optimization Setup. The References are:
  80.  *
  81.  * <br><br>
  82.  *  <ul>
  83.  *      <li>
  84.  *          Boyd, S., and L. van den Berghe (2009): <i>Convex Optimization</i> <b>Cambridge University
  85.  *              Press</b> Cambridge UK
  86.  *      </li>
  87.  *      <li>
  88.  *          Eustaquio, R., E. Karas, and A. Ribeiro (2008): <i>Constraint Qualification for Nonlinear
  89.  *              Programming</i> <b>Federal University of Parana</b>
  90.  *      </li>
  91.  *      <li>
  92.  *          Karush, A. (1939): <i>Minima of Functions of Several Variables with Inequalities as Side
  93.  *          Constraints</i> <b>University of Chicago</b> Chicago IL
  94.  *      </li>
  95.  *      <li>
  96.  *          Kuhn, H. W., and A. W. Tucker (1951): Nonlinear Programming <i>Proceedings of the Second Berkeley
  97.  *              Symposium</i> <b>University of California</b> Berkeley CA 481-492
  98.  *      </li>
  99.  *      <li>
  100.  *          Ruszczynski, A. (2006): <i>Nonlinear Optimization</i> <b>Princeton University Press</b> Princeton
  101.  *              NJ
  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/NumericalOptimizerLibrary.md">Numerical Optimizer Library</a></li>
  109.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/optimization/README.md">Necessary, Sufficient, and Regularity Checks for Gradient Descent in a Constrained Optimization Setup</a></li>
  110.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/optimization/constrained/README.md">KKT Fritz-John Constrained Optimizer</a></li>
  111.  *  </ul>
  112.  *
  113.  * @author Lakshmi Krishnamurthy
  114.  */

  115. public class OptimizationFramework {
  116.     private org.drip.function.definition.RdToR1 _rdToR1Objective = null;
  117.     private org.drip.function.definition.RdToR1[] _aRdToR1EqualityConstraint = null;
  118.     private org.drip.function.definition.RdToR1[] _aRdToR1InequalityConstraint = null;

  119.     /**
  120.      * OptimizationFramework Constructor
  121.      *
  122.      * @param rdToR1Objective The R^d To R^1 Objective Function
  123.      * @param aRdToR1EqualityConstraint The Array of R^d To R^1 Equality Constraint Functions
  124.      * @param aRdToR1InequalityConstraint The Array of R^d To R^1 Inequality Constraint Functions
  125.      *
  126.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  127.      */

  128.     public OptimizationFramework (
  129.         final org.drip.function.definition.RdToR1 rdToR1Objective,
  130.         final org.drip.function.definition.RdToR1[] aRdToR1EqualityConstraint,
  131.         final org.drip.function.definition.RdToR1[] aRdToR1InequalityConstraint)
  132.         throws java.lang.Exception
  133.     {
  134.         if (null == (_rdToR1Objective = rdToR1Objective))
  135.             throw new java.lang.Exception ("OptimizationFramework Constructor => Invalid Inputs");

  136.         int iObjectiveDimension = _rdToR1Objective.dimension();

  137.         if (null != (_aRdToR1EqualityConstraint = aRdToR1EqualityConstraint)) {
  138.             int iNumEqualityConstraint = _aRdToR1EqualityConstraint.length;

  139.             for (int i = 0; i < iNumEqualityConstraint; ++i) {
  140.                 if (null == _aRdToR1EqualityConstraint[i] || _aRdToR1EqualityConstraint[i].dimension() !=
  141.                     iObjectiveDimension)
  142.                     throw new java.lang.Exception ("OptimizationFramework Constructor => Invalid Inputs");
  143.             }
  144.         }

  145.         if (null != (_aRdToR1InequalityConstraint = aRdToR1InequalityConstraint)) {
  146.             int iNumInequalityConstraint = _aRdToR1InequalityConstraint.length;

  147.             for (int i = 0; i < iNumInequalityConstraint; ++i) {
  148.                 if (null == _aRdToR1InequalityConstraint[i] || _aRdToR1InequalityConstraint[i].dimension() !=
  149.                     iObjectiveDimension)
  150.                     throw new java.lang.Exception ("OptimizationFramework Constructor => Invalid Inputs");
  151.             }
  152.         }
  153.     }

  154.     /**
  155.      * Retrieve the R^d To R^1 Objective Function
  156.      *
  157.      * @return The R^d To R^1 Objective Function
  158.      */

  159.     public org.drip.function.definition.RdToR1 objectiveFunction()
  160.     {
  161.         return _rdToR1Objective;
  162.     }

  163.     /**
  164.      * Retrieve the Array of R^d To R^1 Equality Constraint Functions
  165.      *
  166.      * @return The Array of R^d To R^1 Equality Constraint Functions
  167.      */

  168.     public org.drip.function.definition.RdToR1[] equalityConstraint()
  169.     {
  170.         return _aRdToR1EqualityConstraint;
  171.     }

  172.     /**
  173.      * Retrieve the Array of R^d To R^1 Inequality Constraint Functions
  174.      *
  175.      * @return The Array of R^d To R^1 Inequality Constraint Functions
  176.      */

  177.     public org.drip.function.definition.RdToR1[] inequalityConstraint()
  178.     {
  179.         return _aRdToR1InequalityConstraint;
  180.     }

  181.     /**
  182.      * Retrieve the Number of Equality Constraints
  183.      *
  184.      * @return The Number of Equality Constraints
  185.      */

  186.     public int numEqualityConstraint()
  187.     {
  188.         return null == _aRdToR1EqualityConstraint ? 0 : _aRdToR1EqualityConstraint.length;
  189.     }

  190.     /**
  191.      * Retrieve the Number of Inequality Constraints
  192.      *
  193.      * @return The Number of Inequality Constraints
  194.      */

  195.     public int numInequalityConstraint()
  196.     {
  197.         return null == _aRdToR1InequalityConstraint ? 0 : _aRdToR1InequalityConstraint.length;
  198.     }

  199.     /**
  200.      * Indicate if the Optimizer Framework is Lagrangian
  201.      *
  202.      * @return TRUE - The Optimizer Framework is Lagrangian
  203.      */

  204.     public boolean isLagrangian()
  205.     {
  206.         return 0 == numInequalityConstraint() && 0 != numEqualityConstraint();
  207.     }

  208.     /**
  209.      * Indicate if the Optimizer Framework is Unconstrained
  210.      *
  211.      * @return TRUE - The Optimizer Framework is Unconstrained
  212.      */

  213.     public boolean isUnconstrained()
  214.     {
  215.         return 0 == numInequalityConstraint() && 0 == numEqualityConstraint();
  216.     }

  217.     /**
  218.      * Indicate if the specified Fritz John Multipliers are compatible with the Optimization Framework
  219.      *
  220.      * @param fjm The specified FJM Multipliers
  221.      *
  222.      * @return TRUE - The specified Fritz John Multipliers are compatible with the Optimization Framework
  223.      */

  224.     public boolean isCompatible (
  225.         final org.drip.optimization.constrained.FritzJohnMultipliers fjm)
  226.     {
  227.         int iNumEqualityConstraint = numEqualityConstraint();

  228.         int iNumInequalityConstraint = numInequalityConstraint();

  229.         int iNumEqualityFJMMultiplier = null == fjm ? 0 : fjm.numEqualityCoefficients();

  230.         if (iNumEqualityConstraint != iNumEqualityFJMMultiplier) return false;

  231.         int iNumInequalityFJMMultiplier = null == fjm ? 0 : fjm.numInequalityCoefficients();

  232.         return iNumInequalityConstraint == iNumInequalityFJMMultiplier;
  233.     }

  234.     /**
  235.      * Check the Candidate Point for Primal Feasibility
  236.      *
  237.      * @param adblVariate The Candidate R^d Variate
  238.      *
  239.      * @return TRUE - The Candidate Point has passed the Primal Feasibility Test
  240.      *
  241.      * @throws java.lang.Exception Thrown if the Input in Invalid
  242.      */

  243.     public boolean primalFeasibilityCheck (
  244.         final double[] adblVariate)
  245.         throws java.lang.Exception
  246.     {
  247.         int iNumEqualityConstraint = numEqualityConstraint();

  248.         int iNumInequalityConstraint = numInequalityConstraint();

  249.         for (int i = 0; i < iNumEqualityConstraint; ++i) {
  250.             if (0. != _aRdToR1EqualityConstraint[i].evaluate (adblVariate)) return false;
  251.         }

  252.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  253.             if (0. < _aRdToR1InequalityConstraint[i].evaluate (adblVariate)) return false;
  254.         }

  255.         return true;
  256.     }

  257.     /**
  258.      * Check for Complementary Slackness across the Inequality Constraints
  259.      *
  260.      * @param fjm The specified Fritz John Multipliers
  261.      * @param adblVariate The Candidate R^d Variate
  262.      *
  263.      * @return TRUE - The Complementary Slackness Test passed
  264.      *
  265.      * @throws java.lang.Exception Thrown if the Input in Invalid
  266.      */

  267.     public boolean complementarySlacknessCheck (
  268.         final org.drip.optimization.constrained.FritzJohnMultipliers fjm,
  269.         final double[] adblVariate)
  270.         throws java.lang.Exception
  271.     {
  272.         if (!isCompatible (fjm))
  273.             throw new java.lang.Exception
  274.                 ("OptimizationFramework::complementarySlacknessCheck => Invalid Inputs");

  275.         int iNumInequalityConstraint = numInequalityConstraint();

  276.         double[] adblInequalityConstraintCoefficient = null == fjm ? null :
  277.             fjm.inequalityConstraintCoefficient();

  278.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  279.             if (0. != _aRdToR1InequalityConstraint[i].evaluate (adblVariate) *
  280.                 adblInequalityConstraintCoefficient[i])
  281.                 return false;
  282.         }

  283.         return true;
  284.     }

  285.     /**
  286.      * Check the Candidate Point for First Order Necessary Condition
  287.      *
  288.      * @param fjm The specified Fritz John Multipliers
  289.      * @param adblVariate The Candidate R^d Variate
  290.      *
  291.      * @return TRUE - The Candidate Point satisfied the First Order Necessary Condition
  292.      *
  293.      * @throws java.lang.Exception Thrown if the Input in Invalid
  294.      */

  295.     public boolean isFONC (
  296.         final org.drip.optimization.constrained.FritzJohnMultipliers fjm,
  297.         final double[] adblVariate)
  298.         throws java.lang.Exception
  299.     {
  300.         if (!isCompatible (fjm))
  301.             throw new java.lang.Exception ("OptimizationFramework::isFONC => Invalid Inputs");

  302.         double[] adblFONCJacobian = _rdToR1Objective.jacobian (adblVariate);

  303.         if (null == adblFONCJacobian)
  304.             throw new java.lang.Exception ("OptimizationFramework::isFONC => Cannot calculate Jacobian");

  305.         int iNumEqualityConstraint = numEqualityConstraint();

  306.         int iNumInequalityConstraint = numInequalityConstraint();

  307.         double[] adblEqualityConstraintCoefficient = null == fjm ? null :
  308.             fjm.equalityConstraintCoefficient();

  309.         double[] adblInequalityConstraintCoefficient = null == fjm ? null :
  310.             fjm.inequalityConstraintCoefficient();

  311.         int iDimension = _rdToR1Objective.dimension();

  312.         for (int i = 0; i < iNumEqualityConstraint; ++i) {
  313.             double[] adblJacobian = _aRdToR1EqualityConstraint[i].jacobian (adblVariate);

  314.             if (null == adblJacobian)
  315.                 throw new java.lang.Exception ("OptimizationFramework::isFONC => Cannot calculate Jacobian");

  316.             for (int j = 0; j < iDimension; ++j)
  317.                 adblFONCJacobian[j] = adblFONCJacobian[j] + adblEqualityConstraintCoefficient[j] *
  318.                     adblJacobian[j];
  319.         }

  320.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  321.             double[] adblJacobian = _aRdToR1InequalityConstraint[i].jacobian (adblVariate);

  322.             if (null == adblJacobian)
  323.                 throw new java.lang.Exception ("OptimizationFramework::isFONC => Cannot calculate Jacobian");

  324.             for (int j = 0; j < iDimension; ++j)
  325.                 adblFONCJacobian[j] = adblFONCJacobian[j] + adblInequalityConstraintCoefficient[j] *
  326.                     adblJacobian[j];
  327.         }

  328.         for (int j = 0; j < iDimension; ++j) {
  329.             if (0. != adblFONCJacobian[j]) return false;
  330.         }

  331.         return true;
  332.     }

  333.     /**
  334.      * Check the Candidate Point for Second Order Sufficiency Condition
  335.      *
  336.      * @param fjm The specified Fritz John Multipliers
  337.      * @param adblVariate The Candidate R^d Variate
  338.      * @param bCheckForMinima TRUE - Check whether the R^d Variate corresponds to the SOSC Minimum
  339.      *
  340.      * @return TRUE - The Candidate Point satisfies the Second Order Sufficiency Condition
  341.      *
  342.      * @throws java.lang.Exception Thrown if the Input in Invalid
  343.      */

  344.     public boolean isSOSC (
  345.         final org.drip.optimization.constrained.FritzJohnMultipliers fjm,
  346.         final double[] adblVariate,
  347.         final boolean bCheckForMinima)
  348.         throws java.lang.Exception
  349.     {
  350.         if (!isFONC (fjm, adblVariate)) return false;

  351.         double[][] aadblSOSCHessian = _rdToR1Objective.hessian (adblVariate);

  352.         if (null == aadblSOSCHessian)
  353.             throw new java.lang.Exception ("OptimizationFramework::isSOSC => Cannot calculate Jacobian");

  354.         int iNumEqualityConstraint = numEqualityConstraint();

  355.         int iNumInequalityConstraint = numInequalityConstraint();

  356.         double[] adblEqualityConstraintCoefficient = null == fjm ? null :
  357.             fjm.equalityConstraintCoefficient();

  358.         double[] adblInequalityConstraintCoefficient = null == fjm ? null :
  359.             fjm.inequalityConstraintCoefficient();

  360.         int iDimension = _rdToR1Objective.dimension();

  361.         for (int i = 0; i < iNumEqualityConstraint; ++i) {
  362.             double[][] aadblHessian = _aRdToR1EqualityConstraint[i].hessian (adblVariate);

  363.             if (null == aadblHessian)
  364.                 throw new java.lang.Exception ("OptimizationFramework::isSOSC => Cannot calculate Jacobian");

  365.             for (int j = 0; j < iDimension; ++j) {
  366.                 for (int k = 0; k < iDimension; ++k)
  367.                     aadblSOSCHessian[j][k] = aadblSOSCHessian[j][k] + adblEqualityConstraintCoefficient[j] *
  368.                         aadblHessian[j][k];
  369.             }
  370.         }

  371.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  372.             double[][] aadblHessian = _aRdToR1InequalityConstraint[i].hessian (adblVariate);

  373.             if (null == aadblHessian)
  374.                 throw new java.lang.Exception ("OptimizationFramework::isSOSC => Cannot calculate Jacobian");

  375.             for (int j = 0; j < iDimension; ++j) {
  376.                 for (int k = 0; k < iDimension; ++k)
  377.                     aadblSOSCHessian[j][k] = aadblSOSCHessian[j][k] + adblInequalityConstraintCoefficient[j]
  378.                         * aadblHessian[j][k];
  379.             }
  380.         }

  381.         double dblSOSC = org.drip.numerical.linearalgebra.Matrix.DotProduct (adblVariate,
  382.             org.drip.numerical.linearalgebra.Matrix.Product (aadblSOSCHessian, adblVariate));

  383.         return (bCheckForMinima && dblSOSC > 0.) || (!bCheckForMinima && dblSOSC < 0.);
  384.     }

  385.     /**
  386.      * Generate the Battery of Necessary and Sufficient Qualification Tests
  387.      *
  388.      * @param fjm The specified Fritz John Multipliers
  389.      * @param adblVariate The Candidate R^d Variate
  390.      * @param bCheckForMinima TRUE - Check whether the R^d Variate corresponds to the SOSC Minimum
  391.      *
  392.      * @return The Necessary and Sufficient Conditions Qualifier Instance
  393.      */

  394.     public org.drip.optimization.constrained.NecessarySufficientConditions necessarySufficientQualifier (
  395.         final org.drip.optimization.constrained.FritzJohnMultipliers fjm,
  396.         final double[] adblVariate,
  397.         final boolean bCheckForMinima)
  398.     {
  399.         try {
  400.             return org.drip.optimization.constrained.NecessarySufficientConditions.Standard (adblVariate, fjm,
  401.                 bCheckForMinima, primalFeasibilityCheck (adblVariate), fjm.dualFeasibilityCheck(),
  402.                     complementarySlacknessCheck (fjm, adblVariate), isFONC (fjm, adblVariate), isSOSC (fjm,
  403.                         adblVariate, bCheckForMinima));
  404.         } catch (java.lang.Exception e) {
  405.             e.printStackTrace();
  406.         }

  407.         return null;
  408.     }

  409.     /**
  410.      * Retrieve the Array of Active Constraints
  411.      *
  412.      * @param adblVariate The R^d Variate
  413.      *
  414.      * @return The Array of Active Constraints
  415.      */

  416.     public org.drip.function.definition.RdToR1[] activeConstraints (
  417.         final double[] adblVariate)
  418.     {
  419.         int iNumEqualityConstraint = numEqualityConstraint();

  420.         int iNumInequalityConstraint = numInequalityConstraint();

  421.         java.util.List<org.drip.function.definition.RdToR1> lsActiveConstraint = new
  422.             java.util.ArrayList<org.drip.function.definition.RdToR1>();

  423.         for (int i = 0; i < iNumEqualityConstraint; ++i)
  424.             lsActiveConstraint.add (_aRdToR1EqualityConstraint[i]);

  425.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  426.             try {
  427.                 if (0. == _aRdToR1InequalityConstraint[i].evaluate (adblVariate))
  428.                     lsActiveConstraint.add (_aRdToR1InequalityConstraint[i]);
  429.             } catch (java.lang.Exception e) {
  430.                 e.printStackTrace();

  431.                 return null;
  432.             }
  433.         }

  434.         int iNumActiveConstraint = lsActiveConstraint.size();

  435.         org.drip.function.definition.RdToR1[] aRdToR1ActiveConstraint = new
  436.             org.drip.function.definition.RdToR1[iNumActiveConstraint];

  437.         for (int i = 0; i < iNumActiveConstraint; ++i)
  438.             aRdToR1ActiveConstraint[i] = lsActiveConstraint.get (i);

  439.         return aRdToR1ActiveConstraint;
  440.     }

  441.     /**
  442.      * Active Constraint Set Rank Computation
  443.      *
  444.      * @param adblVariate The Candidate R^d Variate
  445.      *
  446.      * @return The Active Constraint Set Rank
  447.      *
  448.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  449.      */

  450.     public int activeConstraintRank (
  451.         final double[] adblVariate)
  452.         throws java.lang.Exception
  453.     {
  454.         int iNumEqualityConstraint = numEqualityConstraint();

  455.         int iNumInequalityConstraint = numInequalityConstraint();

  456.         java.util.List<double[]> lsJacobian = new java.util.ArrayList<double[]>();

  457.         double[] adblJacobian = _rdToR1Objective.jacobian (adblVariate);

  458.         if (null == adblJacobian)
  459.             throw new java.lang.Exception ("OptimizationFramework::activeConstraintRank => Cannot Compute");

  460.         lsJacobian.add (adblJacobian);

  461.         for (int i = 0; i < iNumEqualityConstraint; ++i) {
  462.             if (null == (adblJacobian = _aRdToR1EqualityConstraint[i].jacobian (adblVariate)))
  463.                 throw new java.lang.Exception
  464.                     ("OptimizationFramework::activeConstraintRank => Cannot Compute");

  465.             lsJacobian.add (adblJacobian);
  466.         }

  467.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  468.             if (0. == _aRdToR1InequalityConstraint[i].evaluate (adblVariate)) {
  469.                 if (null == (adblJacobian = _aRdToR1InequalityConstraint[i].jacobian (adblVariate)))
  470.                     throw new java.lang.Exception
  471.                         ("OptimizationFramework::activeConstraintRank => Cannot Compute");

  472.                 lsJacobian.add (adblJacobian);
  473.             }
  474.         }

  475.         int iNumJacobian = lsJacobian.size();

  476.         double[][] aadblJacobian = new double[iNumJacobian][];

  477.         for (int i = 0; i < iNumJacobian; ++i)
  478.             aadblJacobian[i] = lsJacobian.get (i);

  479.         return org.drip.numerical.linearalgebra.Matrix.Rank (aadblJacobian);
  480.     }

  481.     /**
  482.      * Compare the Active Constraint Set Rank at the specified against the specified Rank
  483.      *
  484.      * @param adblVariate The Candidate R^d Variate
  485.      * @param iRank The specified Rank
  486.      *
  487.      * @return TRUE - Active Constraint Set Rank matches the specified Rank
  488.      *
  489.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  490.      */

  491.     public boolean activeConstraintRankComparison (
  492.         final double[] adblVariate,
  493.         final int iRank)
  494.         throws java.lang.Exception
  495.     {
  496.         return activeConstraintRank (adblVariate) == iRank;
  497.     }

  498.     /**
  499.      * Active Constraint Set Linear Dependence Check
  500.      *
  501.      * @param adblVariate The Candidate R^d Variate
  502.      * @param bPositiveLinearDependenceCheck TRUE - Perform an Additional Positive Dependence Check
  503.      *
  504.      * @return TRUE - Active Constraint Set Linear Dependence Check is satisfied
  505.      *
  506.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  507.      */

  508.     public boolean activeConstraintLinearDependence (
  509.         final double[] adblVariate,
  510.         final boolean bPositiveLinearDependenceCheck)
  511.         throws java.lang.Exception
  512.     {
  513.         int iNumEqualityConstraint = numEqualityConstraint();

  514.         int iNumInequalityConstraint = numInequalityConstraint();

  515.         int iNumConstraint = iNumEqualityConstraint + iNumInequalityConstraint;
  516.         double[][] aadblJacobian = new double[iNumConstraint][];

  517.         for (int i = 0; i < iNumEqualityConstraint; ++i) {
  518.             if (null == (aadblJacobian[i] = _aRdToR1EqualityConstraint[i].jacobian (adblVariate)))
  519.                 return false;
  520.         }

  521.         for (int i = iNumEqualityConstraint; i < iNumConstraint; ++i) {
  522.             aadblJacobian[i] = null;
  523.             org.drip.function.definition.RdToR1 rdToR1InequalityConstraint =
  524.                 _aRdToR1InequalityConstraint[i - iNumEqualityConstraint];

  525.             if (0. == rdToR1InequalityConstraint.evaluate (adblVariate)) {
  526.                 if (null == (aadblJacobian[i] = rdToR1InequalityConstraint.jacobian (adblVariate)))
  527.                     return false;
  528.             }
  529.         }

  530.         for (int i = 0; i < iNumConstraint; ++i) {
  531.             if (null != aadblJacobian[i]) {
  532.                 for (int j = i + 1; j < iNumConstraint; ++j) {
  533.                     if (null != aadblJacobian[j] && 0. != org.drip.numerical.linearalgebra.Matrix.DotProduct
  534.                         (aadblJacobian[i], aadblJacobian[j]))
  535.                         return false;
  536.                 }
  537.             }
  538.         }

  539.         if (bPositiveLinearDependenceCheck) {
  540.             for (int i = 0; i < iNumConstraint; ++i) {
  541.                 if (null != aadblJacobian[i] &&
  542.                     !org.drip.numerical.linearalgebra.Matrix.PositiveLinearlyIndependent (aadblJacobian[i]))
  543.                     return false;
  544.             }
  545.         }

  546.         return true;
  547.     }

  548.     /**
  549.      * Compute the Along/Away "Naturally" Incremented Variates
  550.      *
  551.      * @param adblVariate The Candidate R^d Variate
  552.      *
  553.      * @return The Along/Away "Natural" Incremented Variates
  554.      */

  555.     public double[][] alongAwayVariate (
  556.         final double[] adblVariate)
  557.     {
  558.         double[] adblVariateIncrement = org.drip.numerical.linearalgebra.Matrix.Product
  559.             (org.drip.numerical.linearalgebra.Matrix.InvertUsingGaussianElimination (_rdToR1Objective.hessian
  560.                 (adblVariate)), _rdToR1Objective.jacobian (adblVariate));

  561.         if (null == adblVariateIncrement) return null;

  562.         int iVariateDimension = adblVariate.length;
  563.         double[] adblVariateAway = new double[iVariateDimension];
  564.         double[] adblVariateAlong = new double[iVariateDimension];

  565.         for (int i = 0; i < iVariateDimension; ++i) {
  566.             adblVariateAway[i] = adblVariate[i] - adblVariateIncrement[i];
  567.             adblVariateAlong[i] = adblVariate[i] + adblVariateIncrement[i];
  568.         }

  569.         return new double[][] {adblVariateAlong, adblVariateAway};
  570.     }

  571.     /**
  572.      * Check for Linearity Constraint Qualification
  573.      *
  574.      * @return TRUE - Linearity Constraint Qualification is satisfied
  575.      */

  576.     public boolean isLCQ()
  577.     {
  578.         int iNumEqualityConstraint = numEqualityConstraint();

  579.         int iNumInequalityConstraint = numInequalityConstraint();

  580.         for (int i = 0; i < iNumEqualityConstraint; ++i) {
  581.             if (!(_aRdToR1EqualityConstraint[i] instanceof org.drip.function.rdtor1.AffineMultivariate))
  582.                 return false;
  583.         }

  584.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  585.             if (!(_aRdToR1InequalityConstraint[i] instanceof org.drip.function.rdtor1.AffineMultivariate))
  586.                 return false;
  587.         }

  588.         return true;
  589.     }

  590.     /**
  591.      * Check for Linearity Independent Constraint Qualification
  592.      *
  593.      * @param adblVariate The Candidate R^d Variate
  594.      *
  595.      * @return TRUE - Linearity Independent Constraint Qualification is satisfied
  596.      *
  597.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  598.      */

  599.     public boolean isLICQ (
  600.         final double[] adblVariate)
  601.         throws java.lang.Exception
  602.     {
  603.         return activeConstraintLinearDependence (adblVariate, false);
  604.     }

  605.     /**
  606.      * Check for Mangasarian Fromovitz Constraint Qualification
  607.      *
  608.      * @param adblVariate The Candidate R^d Variate
  609.      *
  610.      * @return TRUE - The Mangasarian Fromovitz Constraint Qualification is satisfied
  611.      *
  612.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  613.      */

  614.     public boolean isMFCQ (
  615.         final double[] adblVariate)
  616.         throws java.lang.Exception
  617.     {
  618.         return activeConstraintLinearDependence (adblVariate, true);
  619.     }

  620.     /**
  621.      * Check for Constant Rank Constraint Qualification
  622.      *
  623.      * @param adblVariate The Candidate R^d Variate
  624.      *
  625.      * @return TRUE - The Constant Rank Constraint Qualification is satisfied
  626.      *
  627.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  628.      */

  629.     public boolean isCRCQ (
  630.         final double[] adblVariate)
  631.         throws java.lang.Exception
  632.     {
  633.         int iRank = activeConstraintRank (adblVariate);

  634.         double[][] aadblAlongAwayVariatePair = alongAwayVariate (adblVariate);

  635.         if (null == aadblAlongAwayVariatePair)
  636.             throw new java.lang.Exception ("OptimizationFramework::isCRCQ => Cannot generate along/away");

  637.         return iRank == activeConstraintRank (aadblAlongAwayVariatePair[0]) && iRank == activeConstraintRank
  638.             (aadblAlongAwayVariatePair[1]);
  639.     }

  640.     /**
  641.      * Check for Constant Positive Linear Dependence Constraint Qualification
  642.      *
  643.      * @param adblVariate The Candidate R^d Variate
  644.      *
  645.      * @return TRUE - The Constant Positive Linear Dependence Constraint Qualification is satisfied
  646.      *
  647.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  648.      */

  649.     public boolean isCPLDCQ (
  650.         final double[] adblVariate)
  651.         throws java.lang.Exception
  652.     {
  653.         if (!isMFCQ (adblVariate)) return false;

  654.         double[][] aadblAlongAwayVariatePair = alongAwayVariate (adblVariate);

  655.         if (null == aadblAlongAwayVariatePair)
  656.             throw new java.lang.Exception ("OptimizationFramework::isCPLDCQ => Cannot generate along/away");

  657.         return isMFCQ (aadblAlongAwayVariatePair[0]) && isMFCQ (aadblAlongAwayVariatePair[1]);
  658.     }

  659.     /**
  660.      * Check for Quasi Normal Constraint Qualification
  661.      *
  662.      * @param fjm The specified Fritz John Multipliers
  663.      * @param adblVariate The Candidate R^d Variate
  664.      *
  665.      * @return TRUE - The Quasi Normal Constraint Qualification is satisfied
  666.      *
  667.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  668.      */

  669.     public boolean isQNCQ (
  670.         final org.drip.optimization.constrained.FritzJohnMultipliers fjm,
  671.         final double[] adblVariate)
  672.         throws java.lang.Exception
  673.     {
  674.         if (!isCompatible (fjm))
  675.             throw new java.lang.Exception ("OptimizationFramework::isQNCQ => Invalid Inputs");

  676.         if (!isMFCQ (adblVariate)) return false;

  677.         int iNumEqualityConstraint = numEqualityConstraint();

  678.         double[] adblEqualityConstraintCoefficient = null == fjm ? null :
  679.             fjm.equalityConstraintCoefficient();

  680.         for (int i = 0; i < iNumEqualityConstraint; ++i) {
  681.             if (0. != adblEqualityConstraintCoefficient[i] && 0. <= _aRdToR1EqualityConstraint[i].evaluate
  682.                 (adblVariate) * adblEqualityConstraintCoefficient[i])
  683.                 return false;
  684.         }

  685.         int iNumInequalityConstraint = numInequalityConstraint();

  686.         double[] adblInequalityConstraintCoefficient = null == fjm ? null :
  687.             fjm.inequalityConstraintCoefficient();

  688.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  689.             if (0. != adblInequalityConstraintCoefficient[i] && 0. <=
  690.                 _aRdToR1InequalityConstraint[i].evaluate (adblVariate) *
  691.                     adblInequalityConstraintCoefficient[i])
  692.                 return false;
  693.         }

  694.         return true;
  695.     }

  696.     /**
  697.      * Check for Slater Condition Constraint Qualification
  698.      *
  699.      * @param adblVariate The Candidate R^d Variate
  700.      *
  701.      * @return TRUE - The Slater Condition Constraint Qualification is satisfied
  702.      *
  703.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  704.      */

  705.     public boolean isSCCQ (
  706.         final double[] adblVariate)
  707.         throws java.lang.Exception
  708.     {
  709.         if (!(_rdToR1Objective instanceof org.drip.function.rdtor1.ConvexMultivariate)) return false;

  710.         int iNumEqualityConstraint = numEqualityConstraint();

  711.         int iNumInequalityConstraint = numInequalityConstraint();

  712.         for (int i = 0; i < iNumEqualityConstraint; ++i) {
  713.             if (0. != _aRdToR1EqualityConstraint[i].evaluate (adblVariate)) return false;
  714.         }

  715.         for (int i = 0; i < iNumInequalityConstraint; ++i) {
  716.             if (0. <= _aRdToR1InequalityConstraint[i].evaluate (adblVariate)) return false;
  717.         }

  718.         return true;
  719.     }

  720.     /**
  721.      * Generate the Battery of Regularity Constraint Qualification Tests
  722.      *
  723.      * @param fjm The specified Fritz John Multipliers
  724.      * @param adblVariate The Candidate R^d Variate
  725.      *
  726.      * @return The Regularity Constraint Qualifier Instance
  727.      */

  728.     public org.drip.optimization.constrained.RegularityConditions regularityQualifier (
  729.         final org.drip.optimization.constrained.FritzJohnMultipliers fjm,
  730.         final double[] adblVariate)
  731.     {
  732.         try {
  733.             return org.drip.optimization.constrained.RegularityConditions.Standard (adblVariate, fjm,
  734.                 isLCQ(), isLICQ (adblVariate), isMFCQ (adblVariate), isCRCQ (adblVariate), isCPLDCQ
  735.                     (adblVariate), isQNCQ (fjm, adblVariate), isSCCQ (adblVariate));
  736.         } catch (java.lang.Exception e) {
  737.             e.printStackTrace();
  738.         }

  739.         return null;
  740.     }
  741. }