public final class DSCompiler extends Object
This class implements the computation rules described in Dan Kalman's paper Doubly Recursive Multivariate Automatic Differentiation, Mathematics Magazine, vol. 75, no. 3, June 2002. However, in order to avoid performances bottlenecks, the recursive rules are "compiled" once in an unfold form. This class does this recursion unrolling and stores the computation rules as simple loops with pre-computed indirection arrays.
This class maps all derivative computation into single dimension arrays that hold the value and partial derivatives. The class does not hold these arrays, which remains under the responsibility of the caller. For each combination of number of free parameters and derivation order, only one compiler is necessary, and this compiler will be used to perform computations on all arrays provided to it, which can represent hundreds or thousands of different parameters kept together with all theur partial derivatives.
The arrays on which compilers operate contain only the partial derivatives together with the 0th
derivative, i.e. the value. The partial derivatives are stored in a compiler-specific order, which can be retrieved
using methods getPartialDerivativeIndex
and
getPartialDerivativeOrders(int)
. The value is guaranteed to be stored as the first element (i.e. the
getPartialDerivativeIndex
method returns 0 when called with 0 for all
derivation orders and getPartialDerivativeOrders
returns an array filled with 0 when called with 0 as the index).
Note that the ordering changes with number of parameters and derivation order. For example given 2 parameters x and y, df/dy is stored at index 2 when derivation order is set to 1 (in this case the array has three elements: f, df/dx and df/dy). If derivation order is set to 2, then df/dy will be stored at index 3 (in this case the array has six elements: f, df/dx, df/dxdx, df/dy, df/dxdy and df/dydy).
Given this structure, users can perform some simple operations like adding, subtracting or multiplying constants and negating the elements by themselves, knowing if they want to mutate their array or create a new array. These simple operations are not provided by the compiler. The compiler provides only the more complex operations between several arrays.
This class is mainly used as the engine for scalar variable DerivativeStructure
. It can also be used directly
to hold several variables in arrays for more complex data structures. User can for example store a vector of n
variables depending on three x, y and z free parameters in one array as follows:
// parameter 0 is x, parameter 1 is y, parameter 2 is z int parameters = 3; DSCompiler compiler = DSCompiler.getCompiler(parameters, order); int size = compiler.getSize(); // pack all elements in a single array double[] array = new double[n * size]; for (int i = 0; i < n; ++i) { // we know value is guaranteed to be the first element array[i * size] = v[i]; // we don't know where first derivatives are stored, so we ask the compiler array[i * size + compiler.getPartialDerivativeIndex(1, 0, 0) = dvOnDx[i][0]; array[i * size + compiler.getPartialDerivativeIndex(0, 1, 0) = dvOnDy[i][0]; array[i * size + compiler.getPartialDerivativeIndex(0, 0, 1) = dvOnDz[i][0]; // we let all higher order derivatives set to 0 }Then in another function, user can perform some operations on all elements stored in the single array, such as a simple product of all variables:
// compute the product of all elements double[] product = new double[size]; prod[0] = 1.0; for (int i = 0; i < n; ++i) { double[] tmp = product.clone(); compiler.multiply(tmp, 0, array, i * size, product, 0); } // value double p = product[0]; // first derivatives double dPdX = product[compiler.getPartialDerivativeIndex(1, 0, 0)]; double dPdY = product[compiler.getPartialDerivativeIndex(0, 1, 0)]; double dPdZ = product[compiler.getPartialDerivativeIndex(0, 0, 1)]; // cross derivatives (assuming order was at least 2) double dPdXdX = product[compiler.getPartialDerivativeIndex(2, 0, 0)]; double dPdXdY = product[compiler.getPartialDerivativeIndex(1, 1, 0)]; double dPdXdZ = product[compiler.getPartialDerivativeIndex(1, 0, 1)]; double dPdYdY = product[compiler.getPartialDerivativeIndex(0, 2, 0)]; double dPdYdZ = product[compiler.getPartialDerivativeIndex(0, 1, 1)]; double dPdZdZ = product[compiler.getPartialDerivativeIndex(0, 0, 2)];
DerivativeStructure
Modifier and Type | Method and Description |
---|---|
void |
acos(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute arc cosine of a derivative structure.
|
void |
acosh(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute inverse hyperbolic cosine of a derivative structure.
|
void |
add(double[] lhs,
int lhsOffset,
double[] rhs,
int rhsOffset,
double[] result,
int resultOffset)
Perform addition of two derivative structures.
|
void |
asin(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute arc sine of a derivative structure.
|
void |
asinh(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute inverse hyperbolic sine of a derivative structure.
|
void |
atan(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute arc tangent of a derivative structure.
|
void |
atan2(double[] y,
int yOffset,
double[] x,
int xOffset,
double[] result,
int resultOffset)
Compute two arguments arc tangent of a derivative structure.
|
void |
atanh(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute inverse hyperbolic tangent of a derivative structure.
|
void |
checkCompatibility(DSCompiler compiler)
Check rules set compatibility.
|
void |
compose(double[] operand,
int operandOffset,
double[] f,
double[] result,
int resultOffset)
Compute composition of a derivative structure by a function.
|
void |
cos(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute cosine of a derivative structure.
|
void |
cosh(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute hyperbolic cosine of a derivative structure.
|
void |
divide(double[] lhs,
int lhsOffset,
double[] rhs,
int rhsOffset,
double[] result,
int resultOffset)
Perform division of two derivative structures.
|
void |
exp(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute exponential of a derivative structure.
|
void |
expm1(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute exp(x) - 1 of a derivative structure.
|
static DSCompiler |
getCompiler(int parameters,
int order)
Get the compiler for number of free parameters and order.
|
protected int[][][] |
getCompIndirection()
Returns indirection arrays for function composition.
|
int |
getFreeParameters()
Get the number of free parameters.
|
protected int[][][] |
getMultIndirection()
Returns indirection arrays for multiplication.
|
int |
getOrder()
Get the derivation order.
|
int |
getPartialDerivativeIndex(int... orders)
Get the index of a partial derivative in the array.
|
int[] |
getPartialDerivativeOrders(int index)
Get the derivation orders for a specific index in the array.
|
int |
getSize()
Get the array size required for holding partial derivatives data.
|
void |
linearCombination(double a1,
double[] c1,
int offset1,
double a2,
double[] c2,
int offset2,
double[] result,
int resultOffset)
Compute linear combination.
|
void |
linearCombination(double a1,
double[] c1,
int offset1,
double a2,
double[] c2,
int offset2,
double a3,
double[] c3,
int offset3,
double[] result,
int resultOffset)
Compute linear combination.
|
void |
linearCombination(double a1,
double[] c1,
int offset1,
double a2,
double[] c2,
int offset2,
double a3,
double[] c3,
int offset3,
double a4,
double[] c4,
int offset4,
double[] result,
int resultOffset)
Compute linear combination.
|
void |
log(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute natural logarithm of a derivative structure.
|
void |
log10(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Computes base 10 logarithm of a derivative structure.
|
void |
log1p(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Computes shifted logarithm of a derivative structure.
|
void |
multiply(double[] lhs,
int lhsOffset,
double[] rhs,
int rhsOffset,
double[] result,
int resultOffset)
Perform multiplication of two derivative structures.
|
void |
pow(double[] x,
int xOffset,
double[] y,
int yOffset,
double[] result,
int resultOffset)
Compute power of a derivative structure.
|
void |
pow(double[] operand,
int operandOffset,
double p,
double[] result,
int resultOffset)
Compute power of a derivative structure.
|
void |
pow(double[] operand,
int operandOffset,
int n,
double[] result,
int resultOffset)
Compute integer power of a derivative structure.
|
void |
pow(double a,
double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute power of a double to a derivative structure.
|
void |
remainder(double[] lhs,
int lhsOffset,
double[] rhs,
int rhsOffset,
double[] result,
int resultOffset)
Perform remainder of two derivative structures.
|
void |
rootN(double[] operand,
int operandOffset,
int n,
double[] result,
int resultOffset)
Compute nth root of a derivative structure.
|
void |
sin(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute sine of a derivative structure.
|
void |
sinh(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute hyperbolic sine of a derivative structure.
|
void |
subtract(double[] lhs,
int lhsOffset,
double[] rhs,
int rhsOffset,
double[] result,
int resultOffset)
Perform subtraction of two derivative structures.
|
void |
tan(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute tangent of a derivative structure.
|
void |
tanh(double[] operand,
int operandOffset,
double[] result,
int resultOffset)
Compute hyperbolic tangent of a derivative structure.
|
double |
taylor(double[] ds,
int dsOffset,
double... delta)
Evaluate Taylor expansion of a derivative structure.
|
public static DSCompiler getCompiler(int parameters, int order)
parameters
- number of free parametersorder
- derivation orderpublic int getPartialDerivativeIndex(int... orders)
If all orders are set to 0, then the 0th order derivative is returned, which is the value of the function.
The indices of derivatives are between 0 and 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:
free parameter
, then the derivatives are sorted in increasing
derivation order (i.e. f at index 0, df/dp at index 1, d2f/dp2 at index 2 ...
dkf/dpk at index k),derivation order
is 1, then the derivatives are sorted in incresing free parameter
order (i.e. f at index 0, df/dx1 at index 1, df/dx2 at index 2 ... df/dxk at
index k),
This method is the inverse of method getPartialDerivativeOrders(int)
orders
- derivation orders with respect to each parameterDimensionMismatchException
- if the numbers of parameters does not
match the instanceNumberIsTooLargeException
- if sum of derivation orders is larger
than the instance limitsgetPartialDerivativeOrders(int)
public int[] getPartialDerivativeOrders(int index)
This method is the inverse of getPartialDerivativeIndex(int...)
.
index
- of the partial derivativegetPartialDerivativeIndex(int...)
public int getFreeParameters()
public int getOrder()
public int getSize()
This number includes the single 0 order derivative element, which is guaranteed to be stored in the first element of the array.
public void linearCombination(double a1, double[] c1, int offset1, double a2, double[] c2, int offset2, double[] result, int resultOffset)
a1
- first scale factorc1
- first base (unscaled) componentoffset1
- offset of first operand in its arraya2
- second scale factorc2
- second base (unscaled) componentoffset2
- offset of second operand in its arrayresult
- array where result must be stored (it may be
one of the input arrays)resultOffset
- offset of the result in its arraypublic void linearCombination(double a1, double[] c1, int offset1, double a2, double[] c2, int offset2, double a3, double[] c3, int offset3, double[] result, int resultOffset)
a1
- first scale factorc1
- first base (unscaled) componentoffset1
- offset of first operand in its arraya2
- second scale factorc2
- second base (unscaled) componentoffset2
- offset of second operand in its arraya3
- third scale factorc3
- third base (unscaled) componentoffset3
- offset of third operand in its arrayresult
- array where result must be stored (it may be
one of the input arrays)resultOffset
- offset of the result in its arraypublic void linearCombination(double a1, double[] c1, int offset1, double a2, double[] c2, int offset2, double a3, double[] c3, int offset3, double a4, double[] c4, int offset4, double[] result, int resultOffset)
a1
- first scale factorc1
- first base (unscaled) componentoffset1
- offset of first operand in its arraya2
- second scale factorc2
- second base (unscaled) componentoffset2
- offset of second operand in its arraya3
- third scale factorc3
- third base (unscaled) componentoffset3
- offset of third operand in its arraya4
- fourth scale factorc4
- fourth base (unscaled) componentoffset4
- offset of fourth operand in its arrayresult
- array where result must be stored (it may be
one of the input arrays)resultOffset
- offset of the result in its arraypublic void add(double[] lhs, int lhsOffset, double[] rhs, int rhsOffset, double[] result, int resultOffset)
lhs
- array holding left hand side of additionlhsOffset
- offset of the left hand side in its arrayrhs
- array right hand side of additionrhsOffset
- offset of the right hand side in its arrayresult
- array where result must be stored (it may be
one of the input arrays)resultOffset
- offset of the result in its arraypublic void subtract(double[] lhs, int lhsOffset, double[] rhs, int rhsOffset, double[] result, int resultOffset)
lhs
- array holding left hand side of subtractionlhsOffset
- offset of the left hand side in its arrayrhs
- array right hand side of subtractionrhsOffset
- offset of the right hand side in its arrayresult
- array where result must be stored (it may be
one of the input arrays)resultOffset
- offset of the result in its arraypublic void multiply(double[] lhs, int lhsOffset, double[] rhs, int rhsOffset, double[] result, int resultOffset)
lhs
- array holding left hand side of multiplicationlhsOffset
- offset of the left hand side in its arrayrhs
- array right hand side of multiplicationrhsOffset
- offset of the right hand side in its arrayresult
- array where result must be stored (for
multiplication the result array cannot be one of
the input arrays)resultOffset
- offset of the result in its arraypublic void divide(double[] lhs, int lhsOffset, double[] rhs, int rhsOffset, double[] result, int resultOffset)
lhs
- array holding left hand side of divisionlhsOffset
- offset of the left hand side in its arrayrhs
- array right hand side of divisionrhsOffset
- offset of the right hand side in its arrayresult
- array where result must be stored (for
division the result array cannot be one of
the input arrays)resultOffset
- offset of the result in its arraypublic void remainder(double[] lhs, int lhsOffset, double[] rhs, int rhsOffset, double[] result, int resultOffset)
lhs
- array holding left hand side of remainderlhsOffset
- offset of the left hand side in its arrayrhs
- array right hand side of remainderrhsOffset
- offset of the right hand side in its arrayresult
- array where result must be stored (it may be
one of the input arrays)resultOffset
- offset of the result in its arraypublic void pow(double a, double[] operand, int operandOffset, double[] result, int resultOffset)
a
- number to exponentiateoperand
- array holding the poweroperandOffset
- offset of the power in its arrayresult
- array where result must be stored (for
power the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void pow(double[] operand, int operandOffset, double p, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayp
- power to applyresult
- array where result must be stored (for
power the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void pow(double[] operand, int operandOffset, int n, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayn
- power to applyresult
- array where result must be stored (for
power the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void pow(double[] x, int xOffset, double[] y, int yOffset, double[] result, int resultOffset)
x
- array holding the basexOffset
- offset of the base in its arrayy
- array holding the exponentyOffset
- offset of the exponent in its arrayresult
- array where result must be stored (for
power the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void rootN(double[] operand, int operandOffset, int n, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayn
- order of the rootresult
- array where result must be stored (for
nth root the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void exp(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
exponential the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void expm1(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
exponential the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void log(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
logarithm the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void log1p(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
shifted logarithm the result array cannot be the input array)resultOffset
- offset of the result in its arraypublic void log10(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
base 10 logarithm the result array cannot be the input array)resultOffset
- offset of the result in its arraypublic void cos(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
cosine the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void sin(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
sine the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void tan(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
tangent the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void acos(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
arc cosine the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void asin(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
arc sine the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void atan(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
arc tangent the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void atan2(double[] y, int yOffset, double[] x, int xOffset, double[] result, int resultOffset)
y
- array holding the first operandyOffset
- offset of the first operand in its arrayx
- array holding the second operandxOffset
- offset of the second operand in its arrayresult
- array where result must be stored (for
two arguments arc tangent the result array cannot be the input array)resultOffset
- offset of the result in its arraypublic void cosh(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
hyperbolic cosine the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void sinh(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
hyperbolic sine the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void tanh(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
hyperbolic tangent the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void acosh(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
inverse hyperbolic cosine the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void asinh(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
inverse hyperbolic sine the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void atanh(double[] operand, int operandOffset, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayresult
- array where result must be stored (for
inverse hyperbolic tangent the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic void compose(double[] operand, int operandOffset, double[] f, double[] result, int resultOffset)
operand
- array holding the operandoperandOffset
- offset of the operand in its arrayf
- array of value and derivatives of the function at
the current point (i.e. at operand[operandOffset]
).result
- array where result must be stored (for
composition the result array cannot be the input
array)resultOffset
- offset of the result in its arraypublic double taylor(double[] ds, int dsOffset, double... delta)
ds
- array holding the derivative structuredsOffset
- offset of the derivative structure in its arraydelta
- parameters offsets (Δx, Δy, ...)public void checkCompatibility(DSCompiler compiler)
compiler
- other compiler to check against instanceDimensionMismatchException
- if number of free parameters or orders are inconsistentprotected int[][][] getMultIndirection()
protected int[][][] getCompIndirection()
Copyright © 2023 CNES. All rights reserved.