Added a way to create DerivativeStructure from all derivatives.

In some cases, users may already have all the derivatives available at
once. It was impossible to use this knowledge and create the object, so
users had to user dirty tricks like adding together variables holding
value and zero derivative with variables holding derivatives and zero
value.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1386743 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2012-09-17 17:42:19 +00:00
parent be26e43b98
commit 3876bd9bc4
3 changed files with 86 additions and 3 deletions

View File

@ -507,10 +507,24 @@ public class DSCompiler {
/** Get the index of a partial derivative in the array.
* <p>
* If all orders are set to 0, then the 0<sup>th</sup> order derivative
* is returned, which is the value of the function. The index for this
* 0<sup>th</sup> order derivative is always 0. the indices of higher
* order derivatives is between 1 and {@link #getSize() - 1)}.
* is returned, which is the value of the function.
* </p>
* <p>The indices of derivatives are between 0 and {@link #getSize() getSize()} - 1.
* Their specific order is fixed for a given compiler, but otherwise not
* publicly specified. There are however some simple cases which have guaranteed
* indices:
* </p>
* <ul>
* <li>the index of 0<sup>th</sup> order derivative is always 0</li>
* <li>if there is only 1 {@link #getFreeParameters() free parameter}, then the
* derivatives are sorted in increasing derivation order (i.e. f at index 0, df/dp
* at index 1, d<sup>2</sup>f/dp<sup>2</sup> at index 2 ...
* d<sup>k</sup>f/dp<sup>k</sup> at index k),</li>
* <li>if the {@link #getOrder() derivation order} is 1, then the derivatives
* are sorted in incresing free parameter order (i.e. f at index 0, df/dx<sub>1</sub>
* at index 1, df/dx<sub>2</sub> at index 2 ... df/dx<sub>k</sub> at index k),</li>
* <li>all other cases are not publicly specified</li>
* </ul>
* <p>
* This method is the inverse of method {@link #getPartialDerivativeOrders(int)}
* </p>

View File

@ -183,6 +183,24 @@ public class DerivativeStructure implements FieldElement<DerivativeStructure>, S
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
* @see #getAllDerivatives()
*/
public DerivativeStructure(final int parameters, final int order, final double ... derivatives)
throws DimensionMismatchException {
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
*/
@ -228,6 +246,14 @@ public class DerivativeStructure implements FieldElement<DerivativeStructure>, S
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();
}
/** '+' operator.
* @param a right hand side parameter of the operator
* @return this+a

View File

@ -20,6 +20,7 @@ package org.apache.commons.math3.analysis.differentiation;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.math3.TestUtils;
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math3.exception.DimensionMismatchException;
import org.apache.commons.math3.exception.NumberIsTooLargeException;
@ -1022,6 +1023,48 @@ public class DerivativeStructureTest {
}
}
@Test
public void testOneParameterConstructor() {
double x = 1.2;
double cos = FastMath.cos(x);
double sin = FastMath.sin(x);
DerivativeStructure yRef = new DerivativeStructure(1, 4, 0, x).cos();
try {
new DerivativeStructure(1, 4, 0.0, 0.0);
Assert.fail("an exception should have been thrown");
} catch (DimensionMismatchException dme) {
// expected
} catch (Exception e) {
Assert.fail("wrong exceptionc caught " + e.getClass().getName());
}
double[] derivatives = new double[] { cos, -sin, -cos, sin, cos };
DerivativeStructure y = new DerivativeStructure(1, 4, derivatives);
checkEquals(yRef, y, 1.0e-15);
TestUtils.assertEquals(derivatives, y.getAllDerivatives(), 1.0e-15);
}
@Test
public void testOneOrderConstructor() {
double x = 1.2;
double y = 2.4;
double z = 12.5;
DerivativeStructure xRef = new DerivativeStructure(3, 1, 0, x);
DerivativeStructure yRef = new DerivativeStructure(3, 1, 1, y);
DerivativeStructure zRef = new DerivativeStructure(3, 1, 2, z);
try {
new DerivativeStructure(3, 1, x + y - z, 1.0, 1.0);
Assert.fail("an exception should have been thrown");
} catch (DimensionMismatchException dme) {
// expected
} catch (Exception e) {
Assert.fail("wrong exceptionc caught " + e.getClass().getName());
}
double[] derivatives = new double[] { x + y - z, 1.0, 1.0, -1.0 };
DerivativeStructure t = new DerivativeStructure(3, 1, derivatives);
checkEquals(xRef.add(yRef.subtract(zRef)), t, 1.0e-15);
TestUtils.assertEquals(derivatives, xRef.add(yRef.subtract(zRef)).getAllDerivatives(), 1.0e-15);
}
private void checkF0F1(DerivativeStructure ds, double value, double...derivatives) {
// check dimension