    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017
    018    package org.apache.commons.math3.analysis;
    019
    020    import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
    021    import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableFunction;
    022    import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableVectorFunction;
    023    import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
    024    import org.apache.commons.math3.analysis.function.Identity;
    025    import org.apache.commons.math3.exception.DimensionMismatchException;
    026    import org.apache.commons.math3.exception.NotStrictlyPositiveException;
    027    import org.apache.commons.math3.exception.NumberIsTooLargeException;
    028    import org.apache.commons.math3.exception.util.LocalizedFormats;
    029
    030    /**
    031     * Utilities for manipulating function objects.
    032     *
    033     * @version $Id: FunctionUtils.java 1401837 2012-10-24 19:39:45Z luc $
    034     * @since 3.0
    035     */
    036    public class FunctionUtils {
    037        /**
    038         * Class only contains static methods.
    039         */
    040        private FunctionUtils() {}
    041
    042        /**
    043         * Composes functions.
    044         * <br/>
    045         * The functions in the argument list are composed sequentially, in the
    046         * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
    047         *
    048         * @param f List of functions.
    049         * @return the composite function.
    050         */
    051        public static UnivariateFunction compose(final UnivariateFunction ... f) {
    052            return new UnivariateFunction() {
    053                /** {@inheritDoc} */
    054                public double value(double x) {
    055                    double r = x;
    056                    for (int i = f.length - 1; i >= 0; i--) {
    057                        r = f[i].value(r);
    058                    }
    059                    return r;
    060                }
    061            };
    062        }
    063
    064        /**
    065         * Composes functions.
    066         * <br/>
    067         * The functions in the argument list are composed sequentially, in the
    068         * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
    069         *
    070         * @param f List of functions.
    071         * @return the composite function.
    072         * @since 3.1
    073         */
    074        public static UnivariateDifferentiableFunction compose(final UnivariateDifferentiableFunction ... f) {
    075            return new UnivariateDifferentiableFunction() {
    076
    077                /** {@inheritDoc} */
    078                public double value(final double t) {
    079                    double r = t;
    080                    for (int i = f.length - 1; i >= 0; i--) {
    081                        r = f[i].value(r);
    082                    }
    083                    return r;
    084                }
    085
    086                /** {@inheritDoc} */
    087                public DerivativeStructure value(final DerivativeStructure t) {
    088                    DerivativeStructure r = t;
    089                    for (int i = f.length - 1; i >= 0; i--) {
    090                        r = f[i].value(r);
    091                    }
    092                    return r;
    093                }
    094
    095            };
    096        }
    097
    098        /**
    099         * Composes functions.
    100         * <br/>
    101         * The functions in the argument list are composed sequentially, in the
    102         * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
    103         *
    104         * @param f List of functions.
    105         * @return the composite function.
    106         * @deprecated as of 3.1 replaced by {@link #compose(UnivariateDifferentiableFunction...)}
    107         */
    108        public static DifferentiableUnivariateFunction compose(final DifferentiableUnivariateFunction ... f) {
    109            return new DifferentiableUnivariateFunction() {
    110                /** {@inheritDoc} */
    111                public double value(double x) {
    112                    double r = x;
    113                    for (int i = f.length - 1; i >= 0; i--) {
    114                        r = f[i].value(r);
    115                    }
    116                    return r;
    117                }
    118
    119                /** {@inheritDoc} */
    120                public UnivariateFunction derivative() {
    121                    return new UnivariateFunction() {
    122                        /** {@inheritDoc} */
    123                        public double value(double x) {
    124                            double p = 1;
    125                            double r = x;
    126                            for (int i = f.length - 1; i >= 0; i--) {
    127                                p *= f[i].derivative().value(r);
    128                                r = f[i].value(r);
    129                            }
    130                            return p;
    131                        }
    132                    };
    133                }
    134            };
    135        }
    136
    137        /**
    138         * Adds functions.
    139         *
    140         * @param f List of functions.
    141         * @return a function that computes the sum of the functions.
    142         */
    143        public static UnivariateFunction add(final UnivariateFunction ... f) {
    144            return new UnivariateFunction() {
    145                /** {@inheritDoc} */
    146                public double value(double x) {
    147                    double r = f[0].value(x);
    148                    for (int i = 1; i < f.length; i++) {
    149                        r += f[i].value(x);
    150                    }
    151                    return r;
    152                }
    153            };
    154        }
    155
    156        /**
    157         * Adds functions.
    158         *
    159         * @param f List of functions.
    160         * @return a function that computes the sum of the functions.
    161         * @since 3.1
    162         */
    163        public static UnivariateDifferentiableFunction add(final UnivariateDifferentiableFunction ... f) {
    164            return new UnivariateDifferentiableFunction() {
    165
    166                /** {@inheritDoc} */
    167                public double value(final double t) {
    168                    double r = f[0].value(t);
    169                    for (int i = 1; i < f.length; i++) {
    170                        r += f[i].value(t);
    171                    }
    172                    return r;
    173                }
    174
    175                /** {@inheritDoc} */
    176                public DerivativeStructure value(final DerivativeStructure t) {
    177                    DerivativeStructure r = f[0].value(t);
    178                    for (int i = 1; i < f.length; i++) {
    179                        r = r.add(f[i].value(t));
    180                    }
    181                    return r;
    182                }
    183
    184            };
    185        }
    186
    187        /**
    188         * Adds functions.
    189         *
    190         * @param f List of functions.
    191         * @return a function that computes the sum of the functions.
    192         * @deprecated as of 3.1 replaced by {@link #add(UnivariateDifferentiableFunction...)}
    193         */
    194        @Deprecated
    195        public static DifferentiableUnivariateFunction add(final DifferentiableUnivariateFunction ... f) {
    196            return new DifferentiableUnivariateFunction() {
    197                /** {@inheritDoc} */
    198                public double value(double x) {
    199                    double r = f[0].value(x);
    200                    for (int i = 1; i < f.length; i++) {
    201                        r += f[i].value(x);
    202                    }
    203                    return r;
    204                }
    205
    206                /** {@inheritDoc} */
    207                public UnivariateFunction derivative() {
    208                    return new UnivariateFunction() {
    209                        /** {@inheritDoc} */
    210                        public double value(double x) {
    211                            double r = f[0].derivative().value(x);
    212                            for (int i = 1; i < f.length; i++) {
    213                                r += f[i].derivative().value(x);
    214                            }
    215                            return r;
    216                        }
    217                    };
    218                }
    219            };
    220        }
    221
    222        /**
    223         * Multiplies functions.
    224         *
    225         * @param f List of functions.
    226         * @return a function that computes the product of the functions.
    227         */
    228        public static UnivariateFunction multiply(final UnivariateFunction ... f) {
    229            return new UnivariateFunction() {
    230                /** {@inheritDoc} */
    231                public double value(double x) {
    232                    double r = f[0].value(x);
    233                    for (int i = 1; i < f.length; i++) {
    234                        r *= f[i].value(x);
    235                    }
    236                    return r;
    237                }
    238            };
    239        }
    240
    241        /**
    242         * Multiplies functions.
    243         *
    244         * @param f List of functions.
    245         * @return a function that computes the product of the functions.
    246         * @since 3.1
    247         */
    248        public static UnivariateDifferentiableFunction multiply(final UnivariateDifferentiableFunction ... f) {
    249            return new UnivariateDifferentiableFunction() {
    250
    251                /** {@inheritDoc} */
    252                public double value(final double t) {
    253                    double r = f[0].value(t);
    254                    for (int i = 1; i < f.length; i++) {
    255                        r  *= f[i].value(t);
    256                    }
    257                    return r;
    258                }
    259
    260                /** {@inheritDoc} */
    261                public DerivativeStructure value(final DerivativeStructure t) {
    262                    DerivativeStructure r = f[0].value(t);
    263                    for (int i = 1; i < f.length; i++) {
    264                        r = r.multiply(f[i].value(t));
    265                    }
    266                    return r;
    267                }
    268
    269            };
    270        }
    271
    272        /**
    273         * Multiplies functions.
    274         *
    275         * @param f List of functions.
    276         * @return a function that computes the product of the functions.
    277         * @deprecated as of 3.1 replaced by {@link #multiply(UnivariateDifferentiableFunction...)}
    278         */
    279        public static DifferentiableUnivariateFunction multiply(final DifferentiableUnivariateFunction ... f) {
    280            return new DifferentiableUnivariateFunction() {
    281                /** {@inheritDoc} */
    282                public double value(double x) {
    283                    double r = f[0].value(x);
    284                    for (int i = 1; i < f.length; i++) {
    285                        r *= f[i].value(x);
    286                    }
    287                    return r;
    288                }
    289
    290                /** {@inheritDoc} */
    291                public UnivariateFunction derivative() {
    292                    return new UnivariateFunction() {
    293                        /** {@inheritDoc} */
    294                        public double value(double x) {
    295                            double sum = 0;
    296                            for (int i = 0; i < f.length; i++) {
    297                                double prod = f[i].derivative().value(x);
    298                                for (int j = 0; j < f.length; j++) {
    299                                    if (i != j) {
    300                                        prod *= f[j].value(x);
    301                                    }
    302                                }
    303                                sum += prod;
    304                            }
    305                            return sum;
    306                        }
    307                    };
    308                }
    309            };
    310        }
    311
    312        /**
    313         * Returns the univariate function <br/>
    314         * {@code h(x) = combiner(f(x), g(x))}.
    315         *
    316         * @param combiner Combiner function.
    317         * @param f Function.
    318         * @param g Function.
    319         * @return the composite function.
    320         */
    321        public static UnivariateFunction combine(final BivariateFunction combiner,
    322                                                 final UnivariateFunction f,
    323                                                 final UnivariateFunction g) {
    324            return new UnivariateFunction() {
    325                /** {@inheritDoc} */
    326                public double value(double x) {
    327                    return combiner.value(f.value(x), g.value(x));
    328                }
    329            };
    330        }
    331
    332        /**
    333         * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
    334         * h(x[]) = combiner(...combiner(combiner(initialValue,f(x[0])),f(x[1]))...),f(x[x.length-1]))
    335         * </code></pre>
    336         *
    337         * @param combiner Combiner function.
    338         * @param f Function.
    339         * @param initialValue Initial value.
    340         * @return a collector function.
    341         */
    342        public static MultivariateFunction collector(final BivariateFunction combiner,
    343                                                     final UnivariateFunction f,
    344                                                     final double initialValue) {
    345            return new MultivariateFunction() {
    346                /** {@inheritDoc} */
    347                public double value(double[] point) {
    348                    double result = combiner.value(initialValue, f.value(point[0]));
    349                    for (int i = 1; i < point.length; i++) {
    350                        result = combiner.value(result, f.value(point[i]));
    351                    }
    352                    return result;
    353                }
    354            };
    355        }
    356
    357        /**
    358         * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
    359         * h(x[]) = combiner(...combiner(combiner(initialValue,x[0]),x[1])...),x[x.length-1])
    360         * </code></pre>
    361         *
    362         * @param combiner Combiner function.
    363         * @param initialValue Initial value.
    364         * @return a collector function.
    365         */
    366        public static MultivariateFunction collector(final BivariateFunction combiner,
    367                                                     final double initialValue) {
    368            return collector(combiner, new Identity(), initialValue);
    369        }
    370
    371        /**
    372         * Creates a unary function by fixing the first argument of a binary function.
    373         *
    374         * @param f Binary function.
    375         * @param fixed Value to which the first argument of {@code f} is set.
    376         * @return the unary function h(x) = f(fixed, x)
    377         */
    378        public static UnivariateFunction fix1stArgument(final BivariateFunction f,
    379                                                        final double fixed) {
    380            return new UnivariateFunction() {
    381                /** {@inheritDoc} */
    382                public double value(double x) {
    383                    return f.value(fixed, x);
    384                }
    385            };
    386        }
    387        /**
    388         * Creates a unary function by fixing the second argument of a binary function.
    389         *
    390         * @param f Binary function.
    391         * @param fixed Value to which the second argument of {@code f} is set.
    392         * @return the unary function h(x) = f(x, fixed)
    393         */
    394        public static UnivariateFunction fix2ndArgument(final BivariateFunction f,
    395                                                        final double fixed) {
    396            return new UnivariateFunction() {
    397                /** {@inheritDoc} */
    398                public double value(double x) {
    399                    return f.value(x, fixed);
    400                }
    401            };
    402        }
    403
    404        /**
    405         * Samples the specified univariate real function on the specified interval.
    406         * <br/>
    407         * The interval is divided equally into {@code n} sections and sample points
    408         * are taken from {@code min} to {@code max - (max - min) / n}; therefore
    409         * {@code f} is not sampled at the upper bound {@code max}.
    410         *
    411         * @param f Function to be sampled
    412         * @param min Lower bound of the interval (included).
    413         * @param max Upper bound of the interval (excluded).
    414         * @param n Number of sample points.
    415         * @return the array of samples.
    416         * @throws NumberIsTooLargeException if the lower bound {@code min} is
    417         * greater than, or equal to the upper bound {@code max}.
    418         * @throws NotStrictlyPositiveException if the number of sample points
    419         * {@code n} is negative.
    420         */
    421        public static double[] sample(UnivariateFunction f,
    422                                      double min, double max, int n) {
    423
    424            if (n <= 0) {
    425                throw new NotStrictlyPositiveException(
    426                        LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES,
    427                        Integer.valueOf(n));
    428            }
    429            if (min >= max) {
    430                throw new NumberIsTooLargeException(min, max, false);
    431            }
    432
    433            final double[] s = new double[n];
    434            final double h = (max - min) / n;
    435            for (int i = 0; i < n; i++) {
    436                s[i] = f.value(min + i * h);
    437            }
    438            return s;
    439        }
    440
    441        /** Convert a {@link UnivariateDifferentiableFunction} into a {@link DifferentiableUnivariateFunction}.
    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 DifferentiableUnivariateFunction toDifferentiableUnivariateFunction(final UnivariateDifferentiableFunction f) {
    449            return new DifferentiableUnivariateFunction() {
    450
    451                /** {@inheritDoc} */
    452                public double value(final double x) {
    453                    return f.value(x);
    454                }
    455
    456                /** {@inheritDoc} */
    457                public UnivariateFunction derivative() {
    458                    return new UnivariateFunction() {
    459                        /** {@inheritDoc} */
    460                        public double value(final double x) {
    461                            return f.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1);
    462                        }
    463                    };
    464                }
    465
    466            };
    467        }
    468
    469        /** Convert a {@link DifferentiableUnivariateFunction} into a {@link UnivariateDifferentiableFunction}.
    470         * <p>
    471         * Note that the converted function is able to handle {@link DerivativeStructure} up to order one.
    472         * If the function is called with higher order, a {@link NumberIsTooLargeException} will be thrown.
    473         * </p>
    474         * @param f function to convert
    475         * @return converted function
    476         * @deprecated this conversion method is temporary in version 3.1, as the {@link
    477         * DifferentiableUnivariateFunction} interface itself is deprecated
    478         */
    479        @Deprecated
    480        public static UnivariateDifferentiableFunction toUnivariateDifferential(final DifferentiableUnivariateFunction f) {
    481            return new UnivariateDifferentiableFunction() {
    482
    483                /** {@inheritDoc} */
    484                public double value(final double x) {
    485                    return f.value(x);
    486                }
    487
    488                /** {@inheritDoc}
    489                 * @exception NumberIsTooLargeException if derivation order is greater than 1
    490                 */
    491                public DerivativeStructure value(final DerivativeStructure t)
    492                    throws NumberIsTooLargeException {
    493                    switch (t.getOrder()) {
    494                        case 0 :
    495                            return new DerivativeStructure(t.getFreeParameters(), 0, f.value(t.getValue()));
    496                        case 1 : {
    497                            final int parameters = t.getFreeParameters();
    498                            final double[] derivatives = new double[parameters + 1];
    499                            derivatives[0] = f.value(t.getValue());
    500                            final double fPrime = f.derivative().value(t.getValue());
    501                            int[] orders = new int[parameters];
    502                            for (int i = 0; i < parameters; ++i) {
    503                                orders[i] = 1;
    504                                derivatives[i + 1] = fPrime * t.getPartialDerivative(orders);
    505                                orders[i] = 0;
    506                            }
    507                            return new DerivativeStructure(parameters, 1, derivatives);
    508                        }
    509                        default :
    510                            throw new NumberIsTooLargeException(t.getOrder(), 1, true);
    511                    }
    512                }
    513
    514            };
    515        }
    516
    517        /** Convert a {@link MultivariateDifferentiableFunction} into a {@link DifferentiableMultivariateFunction}.
    518         * @param f function to convert
    519         * @return converted function
    520         * @deprecated this conversion method is temporary in version 3.1, as the {@link
    521         * DifferentiableMultivariateFunction} interface itself is deprecated
    522         */
    523        @Deprecated
    524        public static DifferentiableMultivariateFunction toDifferentiableMultivariateFunction(final MultivariateDifferentiableFunction f) {
    525            return new DifferentiableMultivariateFunction() {
    526
    527                /** {@inheritDoc} */
    528                public double value(final double[] x) {
    529                    return f.value(x);
    530                }
    531
    532                /** {@inheritDoc} */
    533                public MultivariateFunction partialDerivative(final int k) {
    534                    return new MultivariateFunction() {
    535                        /** {@inheritDoc} */
    536                        public double value(final double[] x) {
    537
    538                            final int n = x.length;
    539
    540                            // delegate computation to underlying function
    541                            final DerivativeStructure[] dsX = new DerivativeStructure[n];
    542                            for (int i = 0; i < n; ++i) {
    543                                if (i == k) {
    544                                    dsX[i] = new DerivativeStructure(1, 1, 0, x[i]);
    545                                } else {
    546                                    dsX[i] = new DerivativeStructure(1, 1, x[i]);
    547                                }
    548                            }
    549                            final DerivativeStructure y = f.value(dsX);
    550
    551                            // extract partial derivative
    552                            return y.getPartialDerivative(1);
    553
    554                        }
    555                    };
    556                }
    557
    558                public MultivariateVectorFunction gradient() {
    559                    return new MultivariateVectorFunction() {
    560                        /** {@inheritDoc} */
    561                        public double[] value(final double[] x) {
    562
    563                            final int n = x.length;
    564
    565                            // delegate computation to underlying function
    566                            final DerivativeStructure[] dsX = new DerivativeStructure[n];
    567                            for (int i = 0; i < n; ++i) {
    568                                dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
    569                            }
    570                            final DerivativeStructure y = f.value(dsX);
    571
    572                            // extract gradient
    573                            final double[] gradient = new double[n];
    574                            final int[] orders = new int[n];
    575                            for (int i = 0; i < n; ++i) {
    576                                orders[i]   = 1;
    577                                gradient[i] = y.getPartialDerivative(orders);
    578                                orders[i]   = 0;
    579                            }
    580
    581                            return gradient;
    582
    583                        }
    584                    };
    585                }
    586
    587            };
    588        }
    589
    590        /** Convert a {@link DifferentiableMultivariateFunction} into a {@link MultivariateDifferentiableFunction}.
    591         * <p>
    592         * Note that the converted function is able to handle {@link DerivativeStructure} elements
    593         * that all have the same number of free parameters and order, and with order at most 1.
    594         * If the function is called with inconsistent numbers of free parameters or higher order, a
    595         * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
    596         * </p>
    597         * @param f function to convert
    598         * @return converted function
    599         * @deprecated this conversion method is temporary in version 3.1, as the {@link
    600         * DifferentiableMultivariateFunction} interface itself is deprecated
    601         */
    602        @Deprecated
    603        public static MultivariateDifferentiableFunction toMultivariateDifferentiableFunction(final DifferentiableMultivariateFunction f) {
    604            return new MultivariateDifferentiableFunction() {
    605
    606                /** {@inheritDoc} */
    607                public double value(final double[] x) {
    608                    return f.value(x);
    609                }
    610
    611                /** {@inheritDoc}
    612                 * @exception DimensionMismatchException if number of parameters or derivation
    613                 * order are higher than 1
    614                 */
    615                public DerivativeStructure value(final DerivativeStructure[] t)
    616                    throws DimensionMismatchException, NumberIsTooLargeException {
    617
    618                    // check parameters and orders limits
    619                    final int parameters = t[0].getFreeParameters();
    620                    final int order      = t[0].getOrder();
    621                    final int n          = t.length;
    622                    if (order > 1) {
    623                        throw new NumberIsTooLargeException(order, 1, true);
    624                    }
    625
    626                    // check all elements in the array are consistent
    627                    for (int i = 0; i < n; ++i) {
    628                        if (t[i].getFreeParameters() != parameters) {
    629                            throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
    630                        }
    631
    632                        if (t[i].getOrder() != order) {
    633                            throw new DimensionMismatchException(t[i].getOrder(), order);
    634                        }
    635                    }
    636
    637                    // delegate computation to underlying function
    638                    final double[] point = new double[n];
    639                    for (int i = 0; i < n; ++i) {
    640                        point[i] = t[i].getValue();
    641                    }
    642                    final double value      = f.value(point);
    643                    final double[] gradient = f.gradient().value(point);
    644
    645                    // merge value and gradient into one DerivativeStructure
    646                    final double[] derivatives = new double[parameters + 1];
    647                    derivatives[0] = value;
    648                    final int[] orders = new int[parameters];
    649                    for (int i = 0; i < parameters; ++i) {
    650                        orders[i] = 1;
    651                        for (int j = 0; j < n; ++j) {
    652                            derivatives[i + 1] += gradient[j] * t[j].getPartialDerivative(orders);
    653                        }
    654                        orders[i] = 0;
    655                    }
    656
    657                    return new DerivativeStructure(parameters, order, derivatives);
    658
    659                }
    660
    661            };
    662        }
    663
    664        /** Convert a {@link MultivariateDifferentiableVectorFunction} into a {@link DifferentiableMultivariateVectorFunction}.
    665         * @param f function to convert
    666         * @return converted function
    667         * @deprecated this conversion method is temporary in version 3.1, as the {@link
    668         * DifferentiableMultivariateVectorFunction} interface itself is deprecated
    669         */
    670        @Deprecated
    671        public static DifferentiableMultivariateVectorFunction toDifferentiableMultivariateVectorFunction(final MultivariateDifferentiableVectorFunction f) {
    672            return new DifferentiableMultivariateVectorFunction() {
    673
    674                /** {@inheritDoc} */
    675                public double[] value(final double[] x) {
    676                    return f.value(x);
    677                }
    678
    679                public MultivariateMatrixFunction jacobian() {
    680                    return new MultivariateMatrixFunction() {
    681                        /** {@inheritDoc} */
    682                        public double[][] value(final double[] x) {
    683
    684                            final int n = x.length;
    685
    686                            // delegate computation to underlying function
    687                            final DerivativeStructure[] dsX = new DerivativeStructure[n];
    688                            for (int i = 0; i < n; ++i) {
    689                                dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
    690                            }
    691                            final DerivativeStructure[] y = f.value(dsX);
    692
    693                            // extract Jacobian
    694                            final double[][] jacobian = new double[y.length][n];
    695                            final int[] orders = new int[n];
    696                            for (int i = 0; i < y.length; ++i) {
    697                                for (int j = 0; j < n; ++j) {
    698                                    orders[j]      = 1;
    699                                    jacobian[i][j] = y[i].getPartialDerivative(orders);
    700                                    orders[j]      = 0;
    701                                }
    702                            }
    703
    704                            return jacobian;
    705
    706                        }
    707                    };
    708                }
    709
    710            };
    711        }
    712
    713        /** Convert a {@link DifferentiableMultivariateVectorFunction} into a {@link MultivariateDifferentiableVectorFunction}.
    714         * <p>
    715         * Note that the converted function is able to handle {@link DerivativeStructure} elements
    716         * that all have the same number of free parameters and order, and with order at most 1.
    717         * If the function is called with inconsistent numbers of free parameters or higher order, a
    718         * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
    719         * </p>
    720         * @param f function to convert
    721         * @return converted function
    722         * @deprecated this conversion method is temporary in version 3.1, as the {@link
    723         * DifferentiableMultivariateFunction} interface itself is deprecated
    724         */
    725        @Deprecated
    726        public static MultivariateDifferentiableVectorFunction toMultivariateDifferentiableVectorFunction(final DifferentiableMultivariateVectorFunction f) {
    727            return new MultivariateDifferentiableVectorFunction() {
    728
    729                /** {@inheritDoc} */
    730                public double[] value(final double[] x) {
    731                    return f.value(x);
    732                }
    733
    734                /** {@inheritDoc}
    735                 * @exception DimensionMismatchException if number of parameters or derivation
    736                 * order are higher than 1
    737                 */
    738                public DerivativeStructure[] value(final DerivativeStructure[] t)
    739                    throws DimensionMismatchException, NumberIsTooLargeException {
    740
    741                    // check parameters and orders limits
    742                    final int parameters = t[0].getFreeParameters();
    743                    final int order      = t[0].getOrder();
    744                    final int n          = t.length;
    745                    if (order > 1) {
    746                        throw new NumberIsTooLargeException(order, 1, true);
    747                    }
    748
    749                    // check all elements in the array are consistent
    750                    for (int i = 0; i < n; ++i) {
    751                        if (t[i].getFreeParameters() != parameters) {
    752                            throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
    753                        }
    754
    755                        if (t[i].getOrder() != order) {
    756                            throw new DimensionMismatchException(t[i].getOrder(), order);
    757                        }
    758                    }
    759
    760                    // delegate computation to underlying function
    761                    final double[] point = new double[n];
    762                    for (int i = 0; i < n; ++i) {
    763                        point[i] = t[i].getValue();
    764                    }
    765                    final double[] value      = f.value(point);
    766                    final double[][] jacobian = f.jacobian().value(point);
    767
    768                    // merge value and Jacobian into a DerivativeStructure array
    769                    final DerivativeStructure[] merged = new DerivativeStructure[value.length];
    770                    for (int k = 0; k < merged.length; ++k) {
    771                        final double[] derivatives = new double[parameters + 1];
    772                        derivatives[0] = value[k];
    773                        final int[] orders = new int[parameters];
    774                        for (int i = 0; i < parameters; ++i) {
    775                            orders[i] = 1;
    776                            for (int j = 0; j < n; ++j) {
    777                                derivatives[i + 1] += jacobian[k][j] * t[j].getPartialDerivative(orders);
    778                            }
    779                            orders[i] = 0;
    780                        }
    781                        merged[k] = new DerivativeStructure(parameters, order, derivatives);
    782                    }
    783
    784                    return merged;
    785
    786                }
    787
    788            };
    789        }
    790
    791    }