"add", "multiply", "compose" instances of "DifferentiableUnivariateRealFunction".

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1185351 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2011-10-17 20:03:50 +00:00
parent 9227754177
commit 976c85755d
2 changed files with 168 additions and 0 deletions

View File

@ -52,6 +52,43 @@ public class FunctionUtils {
};
}
/**
* Compose functions. The functions in the argument list are composed
* sequentially, in the order given. For example, compose(f1,f2,f3)
* acts like f1(f2(f3(x))).
*
* @param f List of functions.
* @return the composite function.
*/
public static DifferentiableUnivariateRealFunction compose(final DifferentiableUnivariateRealFunction ... f) {
return new DifferentiableUnivariateRealFunction() {
/** {@inheritDoc} */
public double value(double x) {
double r = x;
for (int i = f.length - 1; i >= 0; i--) {
r = f[i].value(r);
}
return r;
}
/** {@inheritDoc} */
public UnivariateRealFunction derivative() {
return new UnivariateRealFunction() {
/** {@inheritDoc} */
public double value(double x) {
double p = 1;
double r = x;
for (int i = f.length - 1; i >= 0; i--) {
p *= f[i].derivative().value(r);
r = f[i].value(r);
}
return p;
}
};
}
};
}
/**
* Add functions.
*
@ -71,6 +108,39 @@ public class FunctionUtils {
};
}
/**
* Add functions.
*
* @param f List of functions.
* @return a function that computes the sum of the functions.
*/
public static DifferentiableUnivariateRealFunction add(final DifferentiableUnivariateRealFunction ... f) {
return new DifferentiableUnivariateRealFunction() {
/** {@inheritDoc} */
public double value(double x) {
double r = f[0].value(x);
for (int i = 1; i < f.length; i++) {
r += f[i].value(x);
}
return r;
}
/** {@inheritDoc} */
public UnivariateRealFunction derivative() {
return new UnivariateRealFunction() {
/** {@inheritDoc} */
public double value(double x) {
double r = f[0].derivative().value(x);
for (int i = 1; i < f.length; i++) {
r += f[i].derivative().value(x);
}
return r;
}
};
}
};
}
/**
* Multiply functions.
*
@ -90,6 +160,45 @@ public class FunctionUtils {
};
}
/**
* Multiply functions.
*
* @param f List of functions.
* @return a function that computes the product of the functions.
*/
public static DifferentiableUnivariateRealFunction multiply(final DifferentiableUnivariateRealFunction ... f) {
return new DifferentiableUnivariateRealFunction() {
/** {@inheritDoc} */
public double value(double x) {
double r = f[0].value(x);
for (int i = 1; i < f.length; i++) {
r *= f[i].value(x);
}
return r;
}
/** {@inheritDoc} */
public UnivariateRealFunction derivative() {
return new UnivariateRealFunction() {
/** {@inheritDoc} */
public double value(double x) {
double sum = 0;
for (int i = 0; i < f.length; i++) {
double prod = f[i].derivative().value(x);
for (int j = 0; j < f.length; j++) {
if (i != j) {
prod *= f[j].value(x);
}
}
sum += prod;
}
return sum;
}
};
}
};
}
/**
* Returns the univariate function <br/>
* {@code h(x) = combiner(f(x), g(x))}.

View File

@ -25,6 +25,8 @@ import org.apache.commons.math.analysis.function.Inverse;
import org.apache.commons.math.analysis.function.Power;
import org.apache.commons.math.analysis.function.Sin;
import org.apache.commons.math.analysis.function.Sinc;
import org.apache.commons.math.analysis.function.Cos;
import org.apache.commons.math.analysis.function.Cosh;
import org.apache.commons.math.analysis.BivariateRealFunction;
import org.apache.commons.math.analysis.function.Add;
import org.apache.commons.math.analysis.function.Multiply;
@ -32,6 +34,7 @@ import org.apache.commons.math.analysis.function.Divide;
import org.apache.commons.math.analysis.function.Min;
import org.apache.commons.math.analysis.function.Max;
import org.apache.commons.math.analysis.function.Pow;
import org.apache.commons.math.analysis.function.Log;
import org.apache.commons.math.analysis.MultivariateRealFunction;
import org.junit.Assert;
@ -63,6 +66,31 @@ public class FunctionUtilsTest {
Assert.assertEquals(81, FunctionUtils.compose(pow, pow).value(3), EPS);
}
@Test
public void testComposeDifferentiable() {
DifferentiableUnivariateRealFunction id = new Identity();
Assert.assertEquals(1, FunctionUtils.compose(id, id, id).derivative().value(3), EPS);
DifferentiableUnivariateRealFunction c = new Constant(4);
Assert.assertEquals(0, FunctionUtils.compose(id, c).derivative().value(3), EPS);
Assert.assertEquals(0, FunctionUtils.compose(c, id).derivative().value(3), EPS);
DifferentiableUnivariateRealFunction m = new Minus();
Assert.assertEquals(-1, FunctionUtils.compose(m).derivative().value(3), EPS);
Assert.assertEquals(1, FunctionUtils.compose(m, m).derivative().value(3), EPS);
DifferentiableUnivariateRealFunction inv = new Inverse();
Assert.assertEquals(0.25, FunctionUtils.compose(inv, m, id).derivative().value(2), EPS);
DifferentiableUnivariateRealFunction pow = new Power(2);
Assert.assertEquals(108, FunctionUtils.compose(pow, pow).derivative().value(3), EPS);
DifferentiableUnivariateRealFunction log = new Log();
double a = 9876.54321;
Assert.assertEquals(pow.derivative().value(a) / pow.value(a),
FunctionUtils.compose(log, pow).derivative().value(a), EPS);
}
@Test
public void testAdd() {
UnivariateRealFunction id = new Identity();
@ -75,6 +103,19 @@ public class FunctionUtilsTest {
Assert.assertEquals(4 - 2, FunctionUtils.add(c, FunctionUtils.compose(m, id)).value(2), EPS);
}
@Test
public void testAddDifferentiable() {
DifferentiableUnivariateRealFunction sin = new Sin();
DifferentiableUnivariateRealFunction c = new Constant(4);
DifferentiableUnivariateRealFunction m = new Minus();
DifferentiableUnivariateRealFunction inv = new Inverse();
final double a = 123.456;
Assert.assertEquals(- 1 / (a * a) -1 + Math.cos(a),
FunctionUtils.add(inv, m, c, sin).derivative().value(a),
EPS);
}
@Test
public void testMultiply() {
UnivariateRealFunction c = new Constant(4);
@ -85,6 +126,24 @@ public class FunctionUtilsTest {
Assert.assertEquals(1, FunctionUtils.multiply(FunctionUtils.compose(inv, pow), pow).value(3.5), EPS);
}
@Test
public void testMultiplyDifferentiable() {
DifferentiableUnivariateRealFunction c = new Constant(4);
DifferentiableUnivariateRealFunction id = new Identity();
final double a = 1.2345678;
Assert.assertEquals(8 * a, FunctionUtils.multiply(c, id, id).derivative().value(a), EPS);
DifferentiableUnivariateRealFunction inv = new Inverse();
DifferentiableUnivariateRealFunction pow = new Power(2.5);
DifferentiableUnivariateRealFunction cos = new Cos();
Assert.assertEquals(1.5 * Math.sqrt(a) * Math.cos(a) - Math.pow(a, 1.5) * Math.sin(a),
FunctionUtils.multiply(inv, pow, cos).derivative().value(a), EPS);
DifferentiableUnivariateRealFunction cosh = new Cosh();
Assert.assertEquals(1.5 * Math.sqrt(a) * Math.cosh(a) + Math.pow(a, 1.5) * Math.sinh(a),
FunctionUtils.multiply(inv, pow, cosh).derivative().value(a), 8 * EPS);
}
@Test
public void testCombine() {
BivariateRealFunction bi = new Add();