FunctionUtils.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.math3.analysis;

  18. import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
  19. import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableFunction;
  20. import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableVectorFunction;
  21. import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
  22. import org.apache.commons.math3.analysis.function.Identity;
  23. import org.apache.commons.math3.exception.DimensionMismatchException;
  24. import org.apache.commons.math3.exception.NotStrictlyPositiveException;
  25. import org.apache.commons.math3.exception.NumberIsTooLargeException;
  26. import org.apache.commons.math3.exception.util.LocalizedFormats;

  27. /**
  28.  * Utilities for manipulating function objects.
  29.  *
  30.  * @since 3.0
  31.  */
  32. public class FunctionUtils {
  33.     /**
  34.      * Class only contains static methods.
  35.      */
  36.     private FunctionUtils() {}

  37.     /**
  38.      * Composes functions.
  39.      * <br/>
  40.      * The functions in the argument list are composed sequentially, in the
  41.      * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
  42.      *
  43.      * @param f List of functions.
  44.      * @return the composite function.
  45.      */
  46.     public static UnivariateFunction compose(final UnivariateFunction ... f) {
  47.         return new UnivariateFunction() {
  48.             /** {@inheritDoc} */
  49.             public double value(double x) {
  50.                 double r = x;
  51.                 for (int i = f.length - 1; i >= 0; i--) {
  52.                     r = f[i].value(r);
  53.                 }
  54.                 return r;
  55.             }
  56.         };
  57.     }

  58.     /**
  59.      * Composes functions.
  60.      * <br/>
  61.      * The functions in the argument list are composed sequentially, in the
  62.      * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
  63.      *
  64.      * @param f List of functions.
  65.      * @return the composite function.
  66.      * @since 3.1
  67.      */
  68.     public static UnivariateDifferentiableFunction compose(final UnivariateDifferentiableFunction ... f) {
  69.         return new UnivariateDifferentiableFunction() {

  70.             /** {@inheritDoc} */
  71.             public double value(final double t) {
  72.                 double r = t;
  73.                 for (int i = f.length - 1; i >= 0; i--) {
  74.                     r = f[i].value(r);
  75.                 }
  76.                 return r;
  77.             }

  78.             /** {@inheritDoc} */
  79.             public DerivativeStructure value(final DerivativeStructure t) {
  80.                 DerivativeStructure r = t;
  81.                 for (int i = f.length - 1; i >= 0; i--) {
  82.                     r = f[i].value(r);
  83.                 }
  84.                 return r;
  85.             }

  86.         };
  87.     }

  88.     /**
  89.      * Composes functions.
  90.      * <br/>
  91.      * The functions in the argument list are composed sequentially, in the
  92.      * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
  93.      *
  94.      * @param f List of functions.
  95.      * @return the composite function.
  96.      * @deprecated as of 3.1 replaced by {@link #compose(UnivariateDifferentiableFunction...)}
  97.      */
  98.     @Deprecated
  99.     public static DifferentiableUnivariateFunction compose(final DifferentiableUnivariateFunction ... f) {
  100.         return new DifferentiableUnivariateFunction() {
  101.             /** {@inheritDoc} */
  102.             public double value(double x) {
  103.                 double r = x;
  104.                 for (int i = f.length - 1; i >= 0; i--) {
  105.                     r = f[i].value(r);
  106.                 }
  107.                 return r;
  108.             }

  109.             /** {@inheritDoc} */
  110.             public UnivariateFunction derivative() {
  111.                 return new UnivariateFunction() {
  112.                     /** {@inheritDoc} */
  113.                     public double value(double x) {
  114.                         double p = 1;
  115.                         double r = x;
  116.                         for (int i = f.length - 1; i >= 0; i--) {
  117.                             p *= f[i].derivative().value(r);
  118.                             r = f[i].value(r);
  119.                         }
  120.                         return p;
  121.                     }
  122.                 };
  123.             }
  124.         };
  125.     }

  126.     /**
  127.      * Adds functions.
  128.      *
  129.      * @param f List of functions.
  130.      * @return a function that computes the sum of the functions.
  131.      */
  132.     public static UnivariateFunction add(final UnivariateFunction ... f) {
  133.         return new UnivariateFunction() {
  134.             /** {@inheritDoc} */
  135.             public double value(double x) {
  136.                 double r = f[0].value(x);
  137.                 for (int i = 1; i < f.length; i++) {
  138.                     r += f[i].value(x);
  139.                 }
  140.                 return r;
  141.             }
  142.         };
  143.     }

  144.     /**
  145.      * Adds functions.
  146.      *
  147.      * @param f List of functions.
  148.      * @return a function that computes the sum of the functions.
  149.      * @since 3.1
  150.      */
  151.     public static UnivariateDifferentiableFunction add(final UnivariateDifferentiableFunction ... f) {
  152.         return new UnivariateDifferentiableFunction() {

  153.             /** {@inheritDoc} */
  154.             public double value(final double t) {
  155.                 double r = f[0].value(t);
  156.                 for (int i = 1; i < f.length; i++) {
  157.                     r += f[i].value(t);
  158.                 }
  159.                 return r;
  160.             }

  161.             /** {@inheritDoc}
  162.              * @throws DimensionMismatchException if functions are not consistent with each other
  163.              */
  164.             public DerivativeStructure value(final DerivativeStructure t)
  165.                 throws DimensionMismatchException {
  166.                 DerivativeStructure r = f[0].value(t);
  167.                 for (int i = 1; i < f.length; i++) {
  168.                     r = r.add(f[i].value(t));
  169.                 }
  170.                 return r;
  171.             }

  172.         };
  173.     }

  174.     /**
  175.      * Adds functions.
  176.      *
  177.      * @param f List of functions.
  178.      * @return a function that computes the sum of the functions.
  179.      * @deprecated as of 3.1 replaced by {@link #add(UnivariateDifferentiableFunction...)}
  180.      */
  181.     @Deprecated
  182.     public static DifferentiableUnivariateFunction add(final DifferentiableUnivariateFunction ... f) {
  183.         return new DifferentiableUnivariateFunction() {
  184.             /** {@inheritDoc} */
  185.             public double value(double x) {
  186.                 double r = f[0].value(x);
  187.                 for (int i = 1; i < f.length; i++) {
  188.                     r += f[i].value(x);
  189.                 }
  190.                 return r;
  191.             }

  192.             /** {@inheritDoc} */
  193.             public UnivariateFunction derivative() {
  194.                 return new UnivariateFunction() {
  195.                     /** {@inheritDoc} */
  196.                     public double value(double x) {
  197.                         double r = f[0].derivative().value(x);
  198.                         for (int i = 1; i < f.length; i++) {
  199.                             r += f[i].derivative().value(x);
  200.                         }
  201.                         return r;
  202.                     }
  203.                 };
  204.             }
  205.         };
  206.     }

  207.     /**
  208.      * Multiplies functions.
  209.      *
  210.      * @param f List of functions.
  211.      * @return a function that computes the product of the functions.
  212.      */
  213.     public static UnivariateFunction multiply(final UnivariateFunction ... f) {
  214.         return new UnivariateFunction() {
  215.             /** {@inheritDoc} */
  216.             public double value(double x) {
  217.                 double r = f[0].value(x);
  218.                 for (int i = 1; i < f.length; i++) {
  219.                     r *= f[i].value(x);
  220.                 }
  221.                 return r;
  222.             }
  223.         };
  224.     }

  225.     /**
  226.      * Multiplies functions.
  227.      *
  228.      * @param f List of functions.
  229.      * @return a function that computes the product of the functions.
  230.      * @since 3.1
  231.      */
  232.     public static UnivariateDifferentiableFunction multiply(final UnivariateDifferentiableFunction ... f) {
  233.         return new UnivariateDifferentiableFunction() {

  234.             /** {@inheritDoc} */
  235.             public double value(final double t) {
  236.                 double r = f[0].value(t);
  237.                 for (int i = 1; i < f.length; i++) {
  238.                     r  *= f[i].value(t);
  239.                 }
  240.                 return r;
  241.             }

  242.             /** {@inheritDoc} */
  243.             public DerivativeStructure value(final DerivativeStructure t) {
  244.                 DerivativeStructure r = f[0].value(t);
  245.                 for (int i = 1; i < f.length; i++) {
  246.                     r = r.multiply(f[i].value(t));
  247.                 }
  248.                 return r;
  249.             }

  250.         };
  251.     }

  252.     /**
  253.      * Multiplies functions.
  254.      *
  255.      * @param f List of functions.
  256.      * @return a function that computes the product of the functions.
  257.      * @deprecated as of 3.1 replaced by {@link #multiply(UnivariateDifferentiableFunction...)}
  258.      */
  259.     @Deprecated
  260.     public static DifferentiableUnivariateFunction multiply(final DifferentiableUnivariateFunction ... f) {
  261.         return new DifferentiableUnivariateFunction() {
  262.             /** {@inheritDoc} */
  263.             public double value(double x) {
  264.                 double r = f[0].value(x);
  265.                 for (int i = 1; i < f.length; i++) {
  266.                     r *= f[i].value(x);
  267.                 }
  268.                 return r;
  269.             }

  270.             /** {@inheritDoc} */
  271.             public UnivariateFunction derivative() {
  272.                 return new UnivariateFunction() {
  273.                     /** {@inheritDoc} */
  274.                     public double value(double x) {
  275.                         double sum = 0;
  276.                         for (int i = 0; i < f.length; i++) {
  277.                             double prod = f[i].derivative().value(x);
  278.                             for (int j = 0; j < f.length; j++) {
  279.                                 if (i != j) {
  280.                                     prod *= f[j].value(x);
  281.                                 }
  282.                             }
  283.                             sum += prod;
  284.                         }
  285.                         return sum;
  286.                     }
  287.                 };
  288.             }
  289.         };
  290.     }

  291.     /**
  292.      * Returns the univariate function <br/>
  293.      * {@code h(x) = combiner(f(x), g(x))}.
  294.      *
  295.      * @param combiner Combiner function.
  296.      * @param f Function.
  297.      * @param g Function.
  298.      * @return the composite function.
  299.      */
  300.     public static UnivariateFunction combine(final BivariateFunction combiner,
  301.                                              final UnivariateFunction f,
  302.                                              final UnivariateFunction g) {
  303.         return new UnivariateFunction() {
  304.             /** {@inheritDoc} */
  305.             public double value(double x) {
  306.                 return combiner.value(f.value(x), g.value(x));
  307.             }
  308.         };
  309.     }

  310.     /**
  311.      * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
  312.      * h(x[]) = combiner(...combiner(combiner(initialValue,f(x[0])),f(x[1]))...),f(x[x.length-1]))
  313.      * </code></pre>
  314.      *
  315.      * @param combiner Combiner function.
  316.      * @param f Function.
  317.      * @param initialValue Initial value.
  318.      * @return a collector function.
  319.      */
  320.     public static MultivariateFunction collector(final BivariateFunction combiner,
  321.                                                  final UnivariateFunction f,
  322.                                                  final double initialValue) {
  323.         return new MultivariateFunction() {
  324.             /** {@inheritDoc} */
  325.             public double value(double[] point) {
  326.                 double result = combiner.value(initialValue, f.value(point[0]));
  327.                 for (int i = 1; i < point.length; i++) {
  328.                     result = combiner.value(result, f.value(point[i]));
  329.                 }
  330.                 return result;
  331.             }
  332.         };
  333.     }

  334.     /**
  335.      * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
  336.      * h(x[]) = combiner(...combiner(combiner(initialValue,x[0]),x[1])...),x[x.length-1])
  337.      * </code></pre>
  338.      *
  339.      * @param combiner Combiner function.
  340.      * @param initialValue Initial value.
  341.      * @return a collector function.
  342.      */
  343.     public static MultivariateFunction collector(final BivariateFunction combiner,
  344.                                                  final double initialValue) {
  345.         return collector(combiner, new Identity(), initialValue);
  346.     }

  347.     /**
  348.      * Creates a unary function by fixing the first argument of a binary function.
  349.      *
  350.      * @param f Binary function.
  351.      * @param fixed Value to which the first argument of {@code f} is set.
  352.      * @return the unary function h(x) = f(fixed, x)
  353.      */
  354.     public static UnivariateFunction fix1stArgument(final BivariateFunction f,
  355.                                                     final double fixed) {
  356.         return new UnivariateFunction() {
  357.             /** {@inheritDoc} */
  358.             public double value(double x) {
  359.                 return f.value(fixed, x);
  360.             }
  361.         };
  362.     }
  363.     /**
  364.      * Creates a unary function by fixing the second argument of a binary function.
  365.      *
  366.      * @param f Binary function.
  367.      * @param fixed Value to which the second argument of {@code f} is set.
  368.      * @return the unary function h(x) = f(x, fixed)
  369.      */
  370.     public static UnivariateFunction fix2ndArgument(final BivariateFunction f,
  371.                                                     final double fixed) {
  372.         return new UnivariateFunction() {
  373.             /** {@inheritDoc} */
  374.             public double value(double x) {
  375.                 return f.value(x, fixed);
  376.             }
  377.         };
  378.     }

  379.     /**
  380.      * Samples the specified univariate real function on the specified interval.
  381.      * <br/>
  382.      * The interval is divided equally into {@code n} sections and sample points
  383.      * are taken from {@code min} to {@code max - (max - min) / n}; therefore
  384.      * {@code f} is not sampled at the upper bound {@code max}.
  385.      *
  386.      * @param f Function to be sampled
  387.      * @param min Lower bound of the interval (included).
  388.      * @param max Upper bound of the interval (excluded).
  389.      * @param n Number of sample points.
  390.      * @return the array of samples.
  391.      * @throws NumberIsTooLargeException if the lower bound {@code min} is
  392.      * greater than, or equal to the upper bound {@code max}.
  393.      * @throws NotStrictlyPositiveException if the number of sample points
  394.      * {@code n} is negative.
  395.      */
  396.     public static double[] sample(UnivariateFunction f, double min, double max, int n)
  397.        throws NumberIsTooLargeException, NotStrictlyPositiveException {

  398.         if (n <= 0) {
  399.             throw new NotStrictlyPositiveException(
  400.                     LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES,
  401.                     Integer.valueOf(n));
  402.         }
  403.         if (min >= max) {
  404.             throw new NumberIsTooLargeException(min, max, false);
  405.         }

  406.         final double[] s = new double[n];
  407.         final double h = (max - min) / n;
  408.         for (int i = 0; i < n; i++) {
  409.             s[i] = f.value(min + i * h);
  410.         }
  411.         return s;
  412.     }

  413.     /** Convert a {@link UnivariateDifferentiableFunction} into a {@link DifferentiableUnivariateFunction}.
  414.      * @param f function to convert
  415.      * @return converted function
  416.      * @deprecated this conversion method is temporary in version 3.1, as the {@link
  417.      * DifferentiableUnivariateFunction} interface itself is deprecated
  418.      */
  419.     @Deprecated
  420.     public static DifferentiableUnivariateFunction toDifferentiableUnivariateFunction(final UnivariateDifferentiableFunction f) {
  421.         return new DifferentiableUnivariateFunction() {

  422.             /** {@inheritDoc} */
  423.             public double value(final double x) {
  424.                 return f.value(x);
  425.             }

  426.             /** {@inheritDoc} */
  427.             public UnivariateFunction derivative() {
  428.                 return new UnivariateFunction() {
  429.                     /** {@inheritDoc} */
  430.                     public double value(final double x) {
  431.                         return f.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1);
  432.                     }
  433.                 };
  434.             }

  435.         };
  436.     }

  437.     /** Convert a {@link DifferentiableUnivariateFunction} into a {@link UnivariateDifferentiableFunction}.
  438.      * <p>
  439.      * Note that the converted function is able to handle {@link DerivativeStructure} up to order one.
  440.      * If the function is called with higher order, a {@link NumberIsTooLargeException} will be thrown.
  441.      * </p>
  442.      * @param f function to convert
  443.      * @return converted function
  444.      * @deprecated this conversion method is temporary in version 3.1, as the {@link
  445.      * DifferentiableUnivariateFunction} interface itself is deprecated
  446.      */
  447.     @Deprecated
  448.     public static UnivariateDifferentiableFunction toUnivariateDifferential(final DifferentiableUnivariateFunction f) {
  449.         return new UnivariateDifferentiableFunction() {

  450.             /** {@inheritDoc} */
  451.             public double value(final double x) {
  452.                 return f.value(x);
  453.             }

  454.             /** {@inheritDoc}
  455.              * @exception NumberIsTooLargeException if derivation order is greater than 1
  456.              */
  457.             public DerivativeStructure value(final DerivativeStructure t)
  458.                 throws NumberIsTooLargeException {
  459.                 switch (t.getOrder()) {
  460.                     case 0 :
  461.                         return new DerivativeStructure(t.getFreeParameters(), 0, f.value(t.getValue()));
  462.                     case 1 : {
  463.                         final int parameters = t.getFreeParameters();
  464.                         final double[] derivatives = new double[parameters + 1];
  465.                         derivatives[0] = f.value(t.getValue());
  466.                         final double fPrime = f.derivative().value(t.getValue());
  467.                         int[] orders = new int[parameters];
  468.                         for (int i = 0; i < parameters; ++i) {
  469.                             orders[i] = 1;
  470.                             derivatives[i + 1] = fPrime * t.getPartialDerivative(orders);
  471.                             orders[i] = 0;
  472.                         }
  473.                         return new DerivativeStructure(parameters, 1, derivatives);
  474.                     }
  475.                     default :
  476.                         throw new NumberIsTooLargeException(t.getOrder(), 1, true);
  477.                 }
  478.             }

  479.         };
  480.     }

  481.     /** Convert a {@link MultivariateDifferentiableFunction} into a {@link DifferentiableMultivariateFunction}.
  482.      * @param f function to convert
  483.      * @return converted function
  484.      * @deprecated this conversion method is temporary in version 3.1, as the {@link
  485.      * DifferentiableMultivariateFunction} interface itself is deprecated
  486.      */
  487.     @Deprecated
  488.     public static DifferentiableMultivariateFunction toDifferentiableMultivariateFunction(final MultivariateDifferentiableFunction f) {
  489.         return new DifferentiableMultivariateFunction() {

  490.             /** {@inheritDoc} */
  491.             public double value(final double[] x) {
  492.                 return f.value(x);
  493.             }

  494.             /** {@inheritDoc} */
  495.             public MultivariateFunction partialDerivative(final int k) {
  496.                 return new MultivariateFunction() {
  497.                     /** {@inheritDoc} */
  498.                     public double value(final double[] x) {

  499.                         final int n = x.length;

  500.                         // delegate computation to underlying function
  501.                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
  502.                         for (int i = 0; i < n; ++i) {
  503.                             if (i == k) {
  504.                                 dsX[i] = new DerivativeStructure(1, 1, 0, x[i]);
  505.                             } else {
  506.                                 dsX[i] = new DerivativeStructure(1, 1, x[i]);
  507.                             }
  508.                         }
  509.                         final DerivativeStructure y = f.value(dsX);

  510.                         // extract partial derivative
  511.                         return y.getPartialDerivative(1);

  512.                     }
  513.                 };
  514.             }

  515.             public MultivariateVectorFunction gradient() {
  516.                 return new MultivariateVectorFunction() {
  517.                     /** {@inheritDoc} */
  518.                     public double[] value(final double[] x) {

  519.                         final int n = x.length;

  520.                         // delegate computation to underlying function
  521.                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
  522.                         for (int i = 0; i < n; ++i) {
  523.                             dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
  524.                         }
  525.                         final DerivativeStructure y = f.value(dsX);

  526.                         // extract gradient
  527.                         final double[] gradient = new double[n];
  528.                         final int[] orders = new int[n];
  529.                         for (int i = 0; i < n; ++i) {
  530.                             orders[i]   = 1;
  531.                             gradient[i] = y.getPartialDerivative(orders);
  532.                             orders[i]   = 0;
  533.                         }

  534.                         return gradient;

  535.                     }
  536.                 };
  537.             }

  538.         };
  539.     }

  540.     /** Convert a {@link DifferentiableMultivariateFunction} into a {@link MultivariateDifferentiableFunction}.
  541.      * <p>
  542.      * Note that the converted function is able to handle {@link DerivativeStructure} elements
  543.      * that all have the same number of free parameters and order, and with order at most 1.
  544.      * If the function is called with inconsistent numbers of free parameters or higher order, a
  545.      * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
  546.      * </p>
  547.      * @param f function to convert
  548.      * @return converted function
  549.      * @deprecated this conversion method is temporary in version 3.1, as the {@link
  550.      * DifferentiableMultivariateFunction} interface itself is deprecated
  551.      */
  552.     @Deprecated
  553.     public static MultivariateDifferentiableFunction toMultivariateDifferentiableFunction(final DifferentiableMultivariateFunction f) {
  554.         return new MultivariateDifferentiableFunction() {

  555.             /** {@inheritDoc} */
  556.             public double value(final double[] x) {
  557.                 return f.value(x);
  558.             }

  559.             /** {@inheritDoc}
  560.              * @exception NumberIsTooLargeException if derivation order is higher than 1
  561.              * @exception DimensionMismatchException if numbers of free parameters are inconsistent
  562.              */
  563.             public DerivativeStructure value(final DerivativeStructure[] t)
  564.                 throws DimensionMismatchException, NumberIsTooLargeException {

  565.                 // check parameters and orders limits
  566.                 final int parameters = t[0].getFreeParameters();
  567.                 final int order      = t[0].getOrder();
  568.                 final int n          = t.length;
  569.                 if (order > 1) {
  570.                     throw new NumberIsTooLargeException(order, 1, true);
  571.                 }

  572.                 // check all elements in the array are consistent
  573.                 for (int i = 0; i < n; ++i) {
  574.                     if (t[i].getFreeParameters() != parameters) {
  575.                         throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
  576.                     }

  577.                     if (t[i].getOrder() != order) {
  578.                         throw new DimensionMismatchException(t[i].getOrder(), order);
  579.                     }
  580.                 }

  581.                 // delegate computation to underlying function
  582.                 final double[] point = new double[n];
  583.                 for (int i = 0; i < n; ++i) {
  584.                     point[i] = t[i].getValue();
  585.                 }
  586.                 final double value      = f.value(point);
  587.                 final double[] gradient = f.gradient().value(point);

  588.                 // merge value and gradient into one DerivativeStructure
  589.                 final double[] derivatives = new double[parameters + 1];
  590.                 derivatives[0] = value;
  591.                 final int[] orders = new int[parameters];
  592.                 for (int i = 0; i < parameters; ++i) {
  593.                     orders[i] = 1;
  594.                     for (int j = 0; j < n; ++j) {
  595.                         derivatives[i + 1] += gradient[j] * t[j].getPartialDerivative(orders);
  596.                     }
  597.                     orders[i] = 0;
  598.                 }

  599.                 return new DerivativeStructure(parameters, order, derivatives);

  600.             }

  601.         };
  602.     }

  603.     /** Convert a {@link MultivariateDifferentiableVectorFunction} into a {@link DifferentiableMultivariateVectorFunction}.
  604.      * @param f function to convert
  605.      * @return converted function
  606.      * @deprecated this conversion method is temporary in version 3.1, as the {@link
  607.      * DifferentiableMultivariateVectorFunction} interface itself is deprecated
  608.      */
  609.     @Deprecated
  610.     public static DifferentiableMultivariateVectorFunction toDifferentiableMultivariateVectorFunction(final MultivariateDifferentiableVectorFunction f) {
  611.         return new DifferentiableMultivariateVectorFunction() {

  612.             /** {@inheritDoc} */
  613.             public double[] value(final double[] x) {
  614.                 return f.value(x);
  615.             }

  616.             public MultivariateMatrixFunction jacobian() {
  617.                 return new MultivariateMatrixFunction() {
  618.                     /** {@inheritDoc} */
  619.                     public double[][] value(final double[] x) {

  620.                         final int n = x.length;

  621.                         // delegate computation to underlying function
  622.                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
  623.                         for (int i = 0; i < n; ++i) {
  624.                             dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
  625.                         }
  626.                         final DerivativeStructure[] y = f.value(dsX);

  627.                         // extract Jacobian
  628.                         final double[][] jacobian = new double[y.length][n];
  629.                         final int[] orders = new int[n];
  630.                         for (int i = 0; i < y.length; ++i) {
  631.                             for (int j = 0; j < n; ++j) {
  632.                                 orders[j]      = 1;
  633.                                 jacobian[i][j] = y[i].getPartialDerivative(orders);
  634.                                 orders[j]      = 0;
  635.                             }
  636.                         }

  637.                         return jacobian;

  638.                     }
  639.                 };
  640.             }

  641.         };
  642.     }

  643.     /** Convert a {@link DifferentiableMultivariateVectorFunction} into a {@link MultivariateDifferentiableVectorFunction}.
  644.      * <p>
  645.      * Note that the converted function is able to handle {@link DerivativeStructure} elements
  646.      * that all have the same number of free parameters and order, and with order at most 1.
  647.      * If the function is called with inconsistent numbers of free parameters or higher order, a
  648.      * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
  649.      * </p>
  650.      * @param f function to convert
  651.      * @return converted function
  652.      * @deprecated this conversion method is temporary in version 3.1, as the {@link
  653.      * DifferentiableMultivariateFunction} interface itself is deprecated
  654.      */
  655.     @Deprecated
  656.     public static MultivariateDifferentiableVectorFunction toMultivariateDifferentiableVectorFunction(final DifferentiableMultivariateVectorFunction f) {
  657.         return new MultivariateDifferentiableVectorFunction() {

  658.             /** {@inheritDoc} */
  659.             public double[] value(final double[] x) {
  660.                 return f.value(x);
  661.             }

  662.             /** {@inheritDoc}
  663.              * @exception NumberIsTooLargeException if derivation order is higher than 1
  664.              * @exception DimensionMismatchException if numbers of free parameters are inconsistent
  665.              */
  666.             public DerivativeStructure[] value(final DerivativeStructure[] t)
  667.                 throws DimensionMismatchException, NumberIsTooLargeException {

  668.                 // check parameters and orders limits
  669.                 final int parameters = t[0].getFreeParameters();
  670.                 final int order      = t[0].getOrder();
  671.                 final int n          = t.length;
  672.                 if (order > 1) {
  673.                     throw new NumberIsTooLargeException(order, 1, true);
  674.                 }

  675.                 // check all elements in the array are consistent
  676.                 for (int i = 0; i < n; ++i) {
  677.                     if (t[i].getFreeParameters() != parameters) {
  678.                         throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
  679.                     }

  680.                     if (t[i].getOrder() != order) {
  681.                         throw new DimensionMismatchException(t[i].getOrder(), order);
  682.                     }
  683.                 }

  684.                 // delegate computation to underlying function
  685.                 final double[] point = new double[n];
  686.                 for (int i = 0; i < n; ++i) {
  687.                     point[i] = t[i].getValue();
  688.                 }
  689.                 final double[] value      = f.value(point);
  690.                 final double[][] jacobian = f.jacobian().value(point);

  691.                 // merge value and Jacobian into a DerivativeStructure array
  692.                 final DerivativeStructure[] merged = new DerivativeStructure[value.length];
  693.                 for (int k = 0; k < merged.length; ++k) {
  694.                     final double[] derivatives = new double[parameters + 1];
  695.                     derivatives[0] = value[k];
  696.                     final int[] orders = new int[parameters];
  697.                     for (int i = 0; i < parameters; ++i) {
  698.                         orders[i] = 1;
  699.                         for (int j = 0; j < n; ++j) {
  700.                             derivatives[i + 1] += jacobian[k][j] * t[j].getPartialDerivative(orders);
  701.                         }
  702.                         orders[i] = 0;
  703.                     }
  704.                     merged[k] = new DerivativeStructure(parameters, order, derivatives);
  705.                 }

  706.                 return merged;

  707.             }

  708.         };
  709.     }

  710. }