|
Java example source code file (DerivativeStructure.java)
The DerivativeStructure.java Java example source code/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.math3.analysis.differentiation; import java.io.Serializable; import org.apache.commons.math3.Field; import org.apache.commons.math3.FieldElement; import org.apache.commons.math3.RealFieldElement; import org.apache.commons.math3.exception.DimensionMismatchException; import org.apache.commons.math3.exception.MathArithmeticException; import org.apache.commons.math3.exception.NumberIsTooLargeException; import org.apache.commons.math3.util.FastMath; import org.apache.commons.math3.util.MathArrays; import org.apache.commons.math3.util.MathUtils; /** Class representing both the value and the differentials of a function. * <p>This class is the workhorse of the differentiation package. * <p>This class is an implementation of the extension to Rall's * numbers described in Dan Kalman's paper <a * href="http://www1.american.edu/cas/mathstat/People/kalman/pdffiles/mmgautodiff.pdf">Doubly * Recursive Multivariate Automatic Differentiation</a>, Mathematics Magazine, vol. 75, * no. 3, June 2002. Rall's numbers are an extension to the real numbers used * throughout mathematical expressions; they hold the derivative together with the * value of a function. Dan Kalman's derivative structures hold all partial derivatives * up to any specified order, with respect to any number of free parameters. Rall's * numbers therefore can be seen as derivative structures for order one derivative and * one free parameter, and real numbers can be seen as derivative structures with zero * order derivative and no free parameters.</p> * <p>{@link DerivativeStructure} instances can be used directly thanks to * the arithmetic operators to the mathematical functions provided as * methods by this class (+, -, *, /, %, sin, cos ...).</p> * <p>Implementing complex expressions by hand using these classes is * a tedious and error-prone task but has the advantage of having no limitation * on the derivation order despite no requiring users to compute the derivatives by * themselves. Implementing complex expression can also be done by developing computation * code using standard primitive double values and to use {@link * UnivariateFunctionDifferentiator differentiators} to create the {@link * DerivativeStructure}-based instances. This method is simpler but may be limited in * the accuracy and derivation orders and may be computationally intensive (this is * typically the case for {@link FiniteDifferencesDifferentiator finite differences * differentiator}.</p> * <p>Instances of this class are guaranteed to be immutable. * @see DSCompiler * @since 3.1 */ public class DerivativeStructure implements RealFieldElement<DerivativeStructure>, Serializable { /** Serializable UID. */ private static final long serialVersionUID = 20120730L; /** Compiler for the current dimensions. */ private transient DSCompiler compiler; /** Combined array holding all values. */ private final double[] data; /** Build an instance with all values and derivatives set to 0. * @param compiler compiler to use for computation */ private DerivativeStructure(final DSCompiler compiler) { this.compiler = compiler; this.data = new double[compiler.getSize()]; } /** Build an instance with all values and derivatives set to 0. * @param parameters number of free parameters * @param order derivation order * @throws NumberIsTooLargeException if order is too large */ public DerivativeStructure(final int parameters, final int order) throws NumberIsTooLargeException { this(DSCompiler.getCompiler(parameters, order)); } /** Build an instance representing a constant value. * @param parameters number of free parameters * @param order derivation order * @param value value of the constant * @throws NumberIsTooLargeException if order is too large * @see #DerivativeStructure(int, int, int, double) */ public DerivativeStructure(final int parameters, final int order, final double value) throws NumberIsTooLargeException { this(parameters, order); this.data[0] = value; } /** Build an instance representing a variable. * <p>Instances built using this constructor are considered * to be the free variables with respect to which differentials * are computed. As such, their differential with respect to * themselves is +1.</p> * @param parameters number of free parameters * @param order derivation order * @param index index of the variable (from 0 to {@code parameters - 1}) * @param value value of the variable * @exception NumberIsTooLargeException if {@code index >= parameters}. * @see #DerivativeStructure(int, int, double) */ public DerivativeStructure(final int parameters, final int order, final int index, final double value) throws NumberIsTooLargeException { this(parameters, order, value); if (index >= parameters) { throw new NumberIsTooLargeException(index, parameters, false); } if (order > 0) { // the derivative of the variable with respect to itself is 1. data[DSCompiler.getCompiler(index, order).getSize()] = 1.0; } } /** Linear combination constructor. * The derivative structure built will be a1 * ds1 + a2 * ds2 * @param a1 first scale factor * @param ds1 first base (unscaled) derivative structure * @param a2 second scale factor * @param ds2 second base (unscaled) derivative structure * @exception DimensionMismatchException if number of free parameters or orders are inconsistent */ public DerivativeStructure(final double a1, final DerivativeStructure ds1, final double a2, final DerivativeStructure ds2) throws DimensionMismatchException { this(ds1.compiler); compiler.checkCompatibility(ds2.compiler); compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, data, 0); } /** Linear combination constructor. * The derivative structure built will be a1 * ds1 + a2 * ds2 + a3 * ds3 * @param a1 first scale factor * @param ds1 first base (unscaled) derivative structure * @param a2 second scale factor * @param ds2 second base (unscaled) derivative structure * @param a3 third scale factor * @param ds3 third base (unscaled) derivative structure * @exception DimensionMismatchException if number of free parameters or orders are inconsistent */ public DerivativeStructure(final double a1, final DerivativeStructure ds1, final double a2, final DerivativeStructure ds2, final double a3, final DerivativeStructure ds3) throws DimensionMismatchException { this(ds1.compiler); compiler.checkCompatibility(ds2.compiler); compiler.checkCompatibility(ds3.compiler); compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, a3, ds3.data, 0, data, 0); } /** Linear combination constructor. * The derivative structure built will be a1 * ds1 + a2 * ds2 + a3 * ds3 + a4 * ds4 * @param a1 first scale factor * @param ds1 first base (unscaled) derivative structure * @param a2 second scale factor * @param ds2 second base (unscaled) derivative structure * @param a3 third scale factor * @param ds3 third base (unscaled) derivative structure * @param a4 fourth scale factor * @param ds4 fourth base (unscaled) derivative structure * @exception DimensionMismatchException if number of free parameters or orders are inconsistent */ public DerivativeStructure(final double a1, final DerivativeStructure ds1, final double a2, final DerivativeStructure ds2, final double a3, final DerivativeStructure ds3, final double a4, final DerivativeStructure ds4) throws DimensionMismatchException { this(ds1.compiler); compiler.checkCompatibility(ds2.compiler); compiler.checkCompatibility(ds3.compiler); compiler.checkCompatibility(ds4.compiler); compiler.linearCombination(a1, ds1.data, 0, a2, ds2.data, 0, a3, ds3.data, 0, a4, ds4.data, 0, data, 0); } /** Build an instance from all its derivatives. * @param parameters number of free parameters * @param order derivation order * @param derivatives derivatives sorted according to * {@link DSCompiler#getPartialDerivativeIndex(int...)} * @exception DimensionMismatchException if derivatives array does not match the * {@link DSCompiler#getSize() size} expected by the compiler * @throws NumberIsTooLargeException if order is too large * @see #getAllDerivatives() */ public DerivativeStructure(final int parameters, final int order, final double ... derivatives) throws DimensionMismatchException, NumberIsTooLargeException { this(parameters, order); if (derivatives.length != data.length) { throw new DimensionMismatchException(derivatives.length, data.length); } System.arraycopy(derivatives, 0, data, 0, data.length); } /** Copy constructor. * @param ds instance to copy */ private DerivativeStructure(final DerivativeStructure ds) { this.compiler = ds.compiler; this.data = ds.data.clone(); } /** Get the number of free parameters. * @return number of free parameters */ public int getFreeParameters() { return compiler.getFreeParameters(); } /** Get the derivation order. * @return derivation order */ public int getOrder() { return compiler.getOrder(); } /** Create a constant compatible with instance order and number of parameters. * <p> * This method is a convenience factory method, it simply calls * {@code new DerivativeStructure(getFreeParameters(), getOrder(), c)} * </p> * @param c value of the constant * @return a constant compatible with instance order and number of parameters * @see #DerivativeStructure(int, int, double) * @since 3.3 */ public DerivativeStructure createConstant(final double c) { return new DerivativeStructure(getFreeParameters(), getOrder(), c); } /** {@inheritDoc} * @since 3.2 */ public double getReal() { return data[0]; } /** Get the value part of the derivative structure. * @return value part of the derivative structure * @see #getPartialDerivative(int...) */ public double getValue() { return data[0]; } /** Get a partial derivative. * @param orders derivation orders with respect to each variable (if all orders are 0, * the value is returned) * @return partial derivative * @see #getValue() * @exception DimensionMismatchException if the numbers of variables does not * match the instance * @exception NumberIsTooLargeException if sum of derivation orders is larger * than the instance limits */ public double getPartialDerivative(final int ... orders) throws DimensionMismatchException, NumberIsTooLargeException { return data[compiler.getPartialDerivativeIndex(orders)]; } /** Get all partial derivatives. * @return a fresh copy of partial derivatives, in an array sorted according to * {@link DSCompiler#getPartialDerivativeIndex(int...)} */ public double[] getAllDerivatives() { return data.clone(); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure add(final double a) { final DerivativeStructure ds = new DerivativeStructure(this); ds.data[0] += a; return ds; } /** {@inheritDoc} * @exception DimensionMismatchException if number of free parameters * or orders do not match */ public DerivativeStructure add(final DerivativeStructure a) throws DimensionMismatchException { compiler.checkCompatibility(a.compiler); final DerivativeStructure ds = new DerivativeStructure(this); compiler.add(data, 0, a.data, 0, ds.data, 0); return ds; } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure subtract(final double a) { return add(-a); } /** {@inheritDoc} * @exception DimensionMismatchException if number of free parameters * or orders do not match */ public DerivativeStructure subtract(final DerivativeStructure a) throws DimensionMismatchException { compiler.checkCompatibility(a.compiler); final DerivativeStructure ds = new DerivativeStructure(this); compiler.subtract(data, 0, a.data, 0, ds.data, 0); return ds; } /** {@inheritDoc} */ public DerivativeStructure multiply(final int n) { return multiply((double) n); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure multiply(final double a) { final DerivativeStructure ds = new DerivativeStructure(this); for (int i = 0; i < ds.data.length; ++i) { ds.data[i] *= a; } return ds; } /** {@inheritDoc} * @exception DimensionMismatchException if number of free parameters * or orders do not match */ public DerivativeStructure multiply(final DerivativeStructure a) throws DimensionMismatchException { compiler.checkCompatibility(a.compiler); final DerivativeStructure result = new DerivativeStructure(compiler); compiler.multiply(data, 0, a.data, 0, result.data, 0); return result; } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure divide(final double a) { final DerivativeStructure ds = new DerivativeStructure(this); for (int i = 0; i < ds.data.length; ++i) { ds.data[i] /= a; } return ds; } /** {@inheritDoc} * @exception DimensionMismatchException if number of free parameters * or orders do not match */ public DerivativeStructure divide(final DerivativeStructure a) throws DimensionMismatchException { compiler.checkCompatibility(a.compiler); final DerivativeStructure result = new DerivativeStructure(compiler); compiler.divide(data, 0, a.data, 0, result.data, 0); return result; } /** {@inheritDoc} */ public DerivativeStructure remainder(final double a) { final DerivativeStructure ds = new DerivativeStructure(this); ds.data[0] = FastMath.IEEEremainder(ds.data[0], a); return ds; } /** {@inheritDoc} * @exception DimensionMismatchException if number of free parameters * or orders do not match * @since 3.2 */ public DerivativeStructure remainder(final DerivativeStructure a) throws DimensionMismatchException { compiler.checkCompatibility(a.compiler); final DerivativeStructure result = new DerivativeStructure(compiler); compiler.remainder(data, 0, a.data, 0, result.data, 0); return result; } /** {@inheritDoc} */ public DerivativeStructure negate() { final DerivativeStructure ds = new DerivativeStructure(compiler); for (int i = 0; i < ds.data.length; ++i) { ds.data[i] = -data[i]; } return ds; } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure abs() { if (Double.doubleToLongBits(data[0]) < 0) { // we use the bits representation to also handle -0.0 return negate(); } else { return this; } } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure ceil() { return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), FastMath.ceil(data[0])); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure floor() { return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), FastMath.floor(data[0])); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure rint() { return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), FastMath.rint(data[0])); } /** {@inheritDoc} */ public long round() { return FastMath.round(data[0]); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure signum() { return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), FastMath.signum(data[0])); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure copySign(final DerivativeStructure sign){ long m = Double.doubleToLongBits(data[0]); long s = Double.doubleToLongBits(sign.data[0]); if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK return this; } return negate(); // flip sign } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure copySign(final double sign) { long m = Double.doubleToLongBits(data[0]); long s = Double.doubleToLongBits(sign); if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK return this; } return negate(); // flip sign } /** * Return the exponent of the instance value, removing the bias. * <p> * For double numbers of the form 2<sup>x, the unbiased * exponent is exactly x. * </p> * @return exponent for instance in IEEE754 representation, without bias */ public int getExponent() { return FastMath.getExponent(data[0]); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure scalb(final int n) { final DerivativeStructure ds = new DerivativeStructure(compiler); for (int i = 0; i < ds.data.length; ++i) { ds.data[i] = FastMath.scalb(data[i], n); } return ds; } /** {@inheritDoc} * @exception DimensionMismatchException if number of free parameters * or orders do not match * @since 3.2 */ public DerivativeStructure hypot(final DerivativeStructure y) throws DimensionMismatchException { compiler.checkCompatibility(y.compiler); if (Double.isInfinite(data[0]) || Double.isInfinite(y.data[0])) { return new DerivativeStructure(compiler.getFreeParameters(), compiler.getFreeParameters(), Double.POSITIVE_INFINITY); } else if (Double.isNaN(data[0]) || Double.isNaN(y.data[0])) { return new DerivativeStructure(compiler.getFreeParameters(), compiler.getFreeParameters(), Double.NaN); } else { final int expX = getExponent(); final int expY = y.getExponent(); if (expX > expY + 27) { // y is neglectible with respect to x return abs(); } else if (expY > expX + 27) { // x is neglectible with respect to y return y.abs(); } else { // find an intermediate scale to avoid both overflow and underflow final int middleExp = (expX + expY) / 2; // scale parameters without losing precision final DerivativeStructure scaledX = scalb(-middleExp); final DerivativeStructure scaledY = y.scalb(-middleExp); // compute scaled hypotenuse final DerivativeStructure scaledH = scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt(); // remove scaling return scaledH.scalb(middleExp); } } } /** * Returns the hypotenuse of a triangle with sides {@code x} and {@code y} * - sqrt(<i>x2 +y2) * avoiding intermediate overflow or underflow. * * <ul> * <li> If either argument is infinite, then the result is positive infinity. * <li> else, if either argument is NaN then the result is NaN. * </ul> * * @param x a value * @param y a value * @return sqrt(<i>x2 +y2) * @exception DimensionMismatchException if number of free parameters * or orders do not match * @since 3.2 */ public static DerivativeStructure hypot(final DerivativeStructure x, final DerivativeStructure y) throws DimensionMismatchException { return x.hypot(y); } /** Compute composition of the instance by a univariate function. * @param f array of value and derivatives of the function at * the current point (i.e. [f({@link #getValue()}), * f'({@link #getValue()}), f''({@link #getValue()})...]). * @return f(this) * @exception DimensionMismatchException if the number of derivatives * in the array is not equal to {@link #getOrder() order} + 1 */ public DerivativeStructure compose(final double ... f) throws DimensionMismatchException { if (f.length != getOrder() + 1) { throw new DimensionMismatchException(f.length, getOrder() + 1); } final DerivativeStructure result = new DerivativeStructure(compiler); compiler.compose(data, 0, f, result.data, 0); return result; } /** {@inheritDoc} */ public DerivativeStructure reciprocal() { final DerivativeStructure result = new DerivativeStructure(compiler); compiler.pow(data, 0, -1, result.data, 0); return result; } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure sqrt() { return rootN(2); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure cbrt() { return rootN(3); } /** {@inheritDoc} * @since 3.2 */ public DerivativeStructure rootN(final int n) { final DerivativeStructure result = new DerivativeStructure(compiler); compiler.rootN(data, 0, n, result.data, 0); return result; } /** {@inheritDoc} */ public Field<DerivativeStructure> getField() { return new Field<DerivativeStructure>() { /** {@inheritDoc} */ public DerivativeStructure getZero() { return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), 0.0); } /** {@inheritDoc} */ public DerivativeStructure getOne() { return new DerivativeStructure(compiler.getFreeParameters(), compiler.getOrder(), 1.0); } /** {@inheritDoc} */ public Class<? extends FieldElement Other Java examples (source code examples)Here is a short list of links related to this Java DerivativeStructure.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.