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