Sunday, March 22, 2015

Porting Matrix and Vector Algorithms using Java-OO and CFR

Porting algorithms between Java and other languages can be quite cumbersome. Different languages have different features, some of which may be difficult to port. When dealing with vectors and matrices, in my experience important differences in languages are:
  • Language support for matrices/vectors
  • Operator-overloading
  • Mutable or immutable matrices/vectors
  • Zero or one based indices
In this post I will discuss operator-overloading when porting algorithms to Java.
Operator overloading is not a feature supported by the Java language. Java-OO is a project that provides basic operator overloading support to the Java language. In this post I will discuss the use of this software in combination with the Matrix and  Vector classes in the thorwin-math library.

Before you can execute the example, set-up your IDE:
  • Download thorwin-math.*.jar and add it as library to your project. This file can be downloaded from thorwin.nl.
  • Download and install Java-OO for your compiler/IDE of choice. The Java-OO site is located here. It may be a good idea to check over the features of Java-OO before continuing.

Constructors

Ok, lets take a look at constructors first. As thorwin-math is designed to be used with Java-OO, the Matrix and Vector classes provide static valueOf methods for constructing instances. Using Java-OO, these constructors are automatically found and used when assigning arrays or strings. Take a look at the following code:


double[] vectorArray = {1, 2, 3};
Vector v1 = vectorArray;
Vector v2 = "4 5 6";

double[][] matrixArray = {{1, 2, 3}, {4, 5, 6}};
Matrix m1 = matrixArray;
Matrix m2 = "1 2; 3 4; 5 6";

The first line contains the conversion of an array of doubles to a Vector. Although the valueOf method itself is very clear, this automatic conversion is quite nice when mixing the Vector class with existing code that uses arrays, when porting C code to Java for instance.

The conversion from a string is not the fastest way to construct a vector, but it is very clear and consise. When writing unit tests this notation is very nice, as I can cut and paste values between MATLAB and Java.

The conversion for the Matrix class are very similar. Again, the main use here is conversion of 2D arrays to matrices and interoperability with MATLAB.

Operators

The following code shows some examples of vector and matrix calculations, when using Java-OO.

Vector v3 = v1 + v2;
Vector v4 = v1 - v2;
Vector v5 = -v1;

Matrix m3 = m1 + m1;
Matrix m4 = m1 - m1;
Matrix m5 = -m1;
Matrix m6 = m1 * m2;
Vector v6 = m1 * v1;

double dot = v1 * v2;

This is all pretty much what you expect when using operator overloading. Java-OO really helps to implement algorithms from pseudo-code or porting from languages such as C#, C++ or MATLAB.

Element Access

Java-OO even provides array-like element access, which is really helpful to port code that uses arrays for vector values (C) or code that also has support for this (C++).

double element = v1[2];

Array-like assignment is also possible in Java-OO, but not with thorwin-math vectors, as these are immutable.

Note that Java code uses zero based indices. Special care must be taken when porting code that is has 1-based indices (MATLAB).

Removing Java-OO

Java-OO is very helpful for creating and maintaining math code.  Current support for compilers and integrated development environments is very good. There may still, however, be a good reason for not wanting a build dependency to Java-OO.

This is where a good Java decompiler is a valuable tool. I currently use CFR, which is a nice decompiler with Java 8 support. You can find it here.

Take, for example, the following piece of Java code that uses Java-OO:

Matrix m = (a + b) * (c - d);

This code can be compiled as part of some Java class. The resulting class file can be decompiled to regular Java code using CFR. The code snippet above is decompiled to:

Matrix m = a.add(b).multiply(c.subtract(d));

We end up with regular Java code.


Tuesday, March 03, 2015

Trend Curve/Line in JavaFX Chart

JavaFX provides some nice components for displaying various kinds of charts. Displaying sample data in a line or scatter chart is quite easy. Interpreting sample data to display trends is more challenging. In this post I will show how to create a chart showing sample data and and a trend curve.

The following illustration shows the end result. It shows both the samples in red and an orange trend curve.



The Java Code

To create the trend curve, I've used a polynomial fitting algorithm to calculate the best fitting polynomial coefficients. The sample code uses the polyfit and polynomial methods from thorwin.math.Math, which can be downloaded here.

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;

import static thorwin.math.Math.polyfit;
import static thorwin.math.Math.polynomial;

public class Demo extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{

        // stup the chart
        XYChart.Series<Number,Number> series1 = new XYChart.Series<>();
        XYChart.Series<Number,Number> series2 = new XYChart.Series<>();

        NumberAxis xAxis = new NumberAxis();
        NumberAxis yAxis = new NumberAxis();

        LineChart<Number,Number> chart = 
            new LineChart<Number, Number>(xAxis, yAxis);

        chart.getData().add(series1);
        chart.getData().add(series2);
        chart.getStylesheets().add(Demo.class.getResource("style.css")
             .toExternalForm());

        // setup chart series
        double[] xs = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
        double[] ys = {0.5, 1.3, 2.4, 5.6, 8.8, 9.1};

        for (int i = 0; i < xs.length; i++) {
            series1.getData().add(new XYChart.Data<>(xs[i], ys[i]));
        }

        // calculate the polynomial coefficients and calculate trend points
        double[] coefficients = polyfit(xs, ys, 2);

        for (double x = 0; x <= 5.0; x += 0.05) {
            double y = polynomial(x, coefficients);
            series2.getData().add(new XYChart.Data<>(x,y));
        }

        // setup scene and stage
        Scene scene = new Scene( chart );

        primaryStage.setScene(scene);
        primaryStage.sizeToScene();
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(Demo.class, args);
    }
}

The polyfit method calculates the polynomial coefficients the the polynomial that fits the sample points best. I've chosen a 2nd order polynomial, which is a curve. If you want a trend line instead of a curve, use a first order polynomial. Higher order polynomials are also possible, just experiment a little.

Stylesheet

The chart we're creating looks like a combination of a scatter chart and a line chart. We could use two charts and try to combine them into one, but applying some styling to the line chart seems to work as well.

The code refers to a file 'style.css', which contains the following stylesheet:
.default-color0.chart-series-line {
    -fx-stroke: transparent;
}

.default-color1.chart-line-symbol {
    -fx-background-color: transparent;
}

This stylesheet will hide lines of the sample data (first data series). It also hides the sample points of the trend curve (second data series).