cern.colt.matrix.doc-files.function1.html Maven / Gradle / Ivy
Function Objects
Example 1: Transformation
The following examples will often use prefabricated function objects from the
library cern.jet.math.Functions
But you need not yet know all about that library, only that it exists. Let's
stay focused and browse through the examples.
Frequently Used Scaling
Operation
Method
Comment
elementwise scaling
assign(f) where f is one of {F.mult(a),F.div(a)}
x[i] = x[i] {*,/} a
x[i,j] = x[i,j] {*,/} a
elementwise scaling
assign(y,f) where f is one of {F.plus,F.minus, F.mult,F.div,
F.plusMult(a),F.minusMult(a)}
x[i] = x[i] {+,-,*,/} y[i]
x[i] = x[i] {+,-} y[i] {*,/} a
x[i,j] = x[i,j] {+,-,*,/} y[i,j]
x[i,j] = x[i,j] {+,-} y[i,j] {*,/} a
Usually, assign operations are heavily optimized for function objects implementing
frequently used numerical scaling like plus,minus,mult,div,plusMult,minusMult,
etc. Here are idioms that make numerical codes efficient:
cern.jet.math.Functions F = cern.jet.math.Functions.functions; // naming shortcut (alias) saves some keystrokes:
double a = 2;
// x and y are 1,2 or 3-d matrices
x.assign(F.mult(a)); // x[i] = x[i] * a
x.assign(F.div(a)); // x[i] = x[i] / a
x.assign(F.plus(a)); // x[i] = x[i] + a
x.assign(F.minus(a)); // x[i] = x[i] - a
x.assign(y, F.mult); // x[i] = x[i] * y[i]
x.assign(y, F.div); // x[i] = x[i] / y[i]
x.assign(y, F.plus); // x[i] = x[i] + y[i]
x.assign(y, F.minus); // x[i] = x[i] - y[i]
x.assign(y, F.plusMult(a)); // x[i] = x[i] + y[i]*a
x.assign(y, F.plusMult(a)); // x[i,j] = x[i,j] + y[i,j]*a
x.assign(y, F.minusMult(1/a)); // x[i,j] = x[i,j] - y[i,j]/a
Try the examples also on 2-d or 3-d matrices. They work without changes regardless
of dimensionality.
Transformation over one matrix
To prepare with, let's construct a 1-d matrix:
double[] v1 = {0, 1, 2, 3};
DoubleMatrix1D x = new DenseDoubleMatrix1D(v1);
Using a mult function object, we multiply the matrix with a scalar
c
// x[i] = x[i] * c
double c = 2;
x.assign(cern.jet.math.Functions.mult(c));
System.out.println(x);
--> 0 2 4 6
It would be equivalent but more clumsy to write
x.assign(
new DoubleFunction() {
public final double apply(double a) { return a*c); }
}
);
Similarly, the sin function object is used to transform the matrix
to hold in each cell the sine of the former corresponding cell value:
// set each cell to its sine
System.out.println(x.assign(cern.jet.math.Functions.sin));
// set each cell to random state uniform in (0,1)
x.assign(cern.jet.math.Functions.random()));
--> 0.002489 0.793068 0.620307 0.35774
// set each cell to random state uniform in (0,1)
System.out.println(x.assign(cern.jet.math.Functions.random()));
--> 0.002489 0.793068 0.620307 0.35774
// set each cell to random state uniform in (-0.5, 0.5)
int seed = 12345;
System.out.println(x.assign(new cern.jet.random.Uniform(-0.5, 0.5, seed)));
--> 0.31733 0.499061 0.010354 -0.368467
// set each cell to random state from Poisson distribution with mean=2
System.out.println(x.assign(new cern.jet.random.Poisson(2, cern.jet.random.Poisson.makeDefaultGenerator())));
--> 9 6 2 2
Transformation over two matrices
To prepare with, let's construct two 1-d matrices:
double[] v1 = {0, 1, 2, 3};
double[] v2 = {0, 2, 4, 6};
DoubleMatrix1D x = new DenseDoubleMatrix1D(v1);
DoubleMatrix1D y = new DenseDoubleMatrix1D(v2);
x = xy <==> x[i] = x[i]y[i]
for all i
A prefabricated pow function object is used to compute the power transformation:
// x[i] = Math.pow(x[i], y[i])
System.out.println(x.assign(y, cern.jet.math.Functions.pow));
--> 1 1 16 729
A prefabricated mult function does something similar:
// x[i] = x[i] * y[i]
System.out.println(x.assign(y, cern.jet.math.Functions.mult));
--> 0 2 8 18
The naming shortcut (alias) saves some keystrokes:
cern.jet.math.Functions F = cern.jet.math.Functions.functions;
Chaining function objects yields more complex functions:
// x[i] = x[i] * y[i] * 3
System.out.println(x.assign(y, F.chain(F.mult,F.mult(3))));
--> 0 6 24 54
More complex transformation functions need to be written by hand:
m1.assign(m2,
new DoubleDoubleFunction() {
public double apply(double a, double b) { return Math.PI*Math.log(a-5)*Math.pow(a,b); }
}
);
If we want to generate a third matrix holding the result of the power transformation,
and leave both source matrices unaffected, we make a copy first and then apply
the transformation on the copy:
// z[i] = Math.pow(x[i],y[i])
DoubleMatrix2D z = x.copy().assign(y, F.pow);
System.out.println(z);