Added a wrapper class to compute Jacobian from differentiable function.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1383886 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
88678b58a4
commit
84f92e1928
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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 org.apache.commons.math3.analysis.MultivariateMatrixFunction;
|
||||||
|
|
||||||
|
/** Class representing the Jacobian of a multivariate vector function.
|
||||||
|
* <p>
|
||||||
|
* The rows iterate on the model functions while the columns iterate on the parameters; thus,
|
||||||
|
* the numbers of rows is equal to the dimension of the underlying function vector
|
||||||
|
* value and the number of columns is equal to the number of free parameters of
|
||||||
|
* the underlying function.
|
||||||
|
* </p>
|
||||||
|
* @version $Id$
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
public class JacobianFunction implements MultivariateMatrixFunction {
|
||||||
|
|
||||||
|
/** Underlying vector-valued function. */
|
||||||
|
private final MultivariateDifferentiableVectorFunction f;
|
||||||
|
|
||||||
|
/** Simple constructor.
|
||||||
|
* @param f underlying vector-valued function
|
||||||
|
*/
|
||||||
|
public JacobianFunction(final MultivariateDifferentiableVectorFunction f) {
|
||||||
|
this.f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public double[][] value(double[] point)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
|
||||||
|
// set up parameters
|
||||||
|
final DerivativeStructure[] dsX = new DerivativeStructure[point.length];
|
||||||
|
for (int i = 0; i < point.length; ++i) {
|
||||||
|
dsX[i] = new DerivativeStructure(point.length, 1, i, point[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the derivatives
|
||||||
|
final DerivativeStructure[] dsY = f.value(dsX);
|
||||||
|
|
||||||
|
// extract the Jacobian
|
||||||
|
final double[][] y = new double[dsY.length][point.length];
|
||||||
|
final int[] orders = new int[point.length];
|
||||||
|
for (int i = 0; i < dsY.length; ++i) {
|
||||||
|
for (int j = 0; j < point.length; ++j) {
|
||||||
|
orders[j] = 1;
|
||||||
|
y[i][j] = dsY[i].getPartialDerivative(orders);
|
||||||
|
orders[j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return y;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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 junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.apache.commons.math3.TestUtils;
|
||||||
|
import org.apache.commons.math3.util.FastMath;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for class {@link JacobianFunction}.
|
||||||
|
*/
|
||||||
|
public class JacobianFunctionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSphere() {
|
||||||
|
SphereMapping f = new SphereMapping(10.0);
|
||||||
|
JacobianFunction j = new JacobianFunction(f);
|
||||||
|
for (double latitude = -1.5; latitude < 1.5; latitude += 0.1) {
|
||||||
|
for (double longitude = -3.1; longitude < 3.1; longitude += 0.1) {
|
||||||
|
double[] point = new double[] { latitude, longitude };
|
||||||
|
double[][] referenceJacobian = f.jacobian(point);
|
||||||
|
double[][] testJacobian = j.value(point);
|
||||||
|
Assert.assertEquals(referenceJacobian.length, testJacobian.length);
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
TestUtils.assertEquals(referenceJacobian[i], testJacobian[i], 2.0e-15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maps (latitude, longitude) to (x, y, z) */
|
||||||
|
private static class SphereMapping implements MultivariateDifferentiableVectorFunction {
|
||||||
|
|
||||||
|
private final double radius;
|
||||||
|
|
||||||
|
public SphereMapping(final double radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] value(double[] point) {
|
||||||
|
final double cLat = FastMath.cos(point[0]);
|
||||||
|
final double sLat = FastMath.sin(point[0]);
|
||||||
|
final double cLon = FastMath.cos(point[1]);
|
||||||
|
final double sLon = FastMath.sin(point[1]);
|
||||||
|
return new double[] {
|
||||||
|
radius * cLon * cLat,
|
||||||
|
radius * sLon * cLat,
|
||||||
|
radius * sLat
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public DerivativeStructure[] value(DerivativeStructure[] point) {
|
||||||
|
final DerivativeStructure cLat = point[0].cos();
|
||||||
|
final DerivativeStructure sLat = point[0].sin();
|
||||||
|
final DerivativeStructure cLon = point[1].cos();
|
||||||
|
final DerivativeStructure sLon = point[1].sin();
|
||||||
|
return new DerivativeStructure[] {
|
||||||
|
cLon.multiply(cLat).multiply(radius),
|
||||||
|
sLon.multiply(cLat).multiply(radius),
|
||||||
|
sLat.multiply(radius)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[][] jacobian(double[] point) {
|
||||||
|
final double cLat = FastMath.cos(point[0]);
|
||||||
|
final double sLat = FastMath.sin(point[0]);
|
||||||
|
final double cLon = FastMath.cos(point[1]);
|
||||||
|
final double sLon = FastMath.sin(point[1]);
|
||||||
|
return new double[][] {
|
||||||
|
{ -radius * cLon * sLat, -radius * sLon * cLat },
|
||||||
|
{ -radius * sLon * sLat, radius * cLon * cLat },
|
||||||
|
{ radius * cLat, 0 }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue