Lecture 4: Some libraries

Balasubramanian Narasimhan
Department of Statistics
Stanford University
Stanford, CA 94305

Revision of Date

Table of Contents

Abstract

In this lecture, we touch upon a few libraries, which are necessary for any non-trivial statistical computing. This lecture is a short one.

Some Libraries

[*]

For any serious statistical computing, one needs a good linear algebra package and some core numerical methods for computing distribution values and generating random variables.

When I first started using Java, I spent some time transcribing some of the C routines in Tierney's Lisp-Stat for use. The resulting library has been downloaded a lot and used for quite some time now. The documentation for this library is available here.

I am going to use this library to get you jump started as to how one can create libraries or use ones created by others.

Libraries distributed by others are typically distributed in two forms.

  1. As a bunch of class files in a package or
  2. As a package in Java ARchive, also called a jar file.

In either case, if one is going to use a library, the library must be available to the Java Development as well as Runtime environment. To illustrate this, consider the following program.

<TestProb.java>=
import java.text.*;
import java.io.*;
import java.util.*;
import probability.*;

public class TestProb {
    public static void main(String[] args) {
        NumberFormat formatter = java.text.NumberFormat.getNumberInstance();
        formatter.setMinimumFractionDigits(5);
        formatter.setMaximumFractionDigits(5);
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String line;
            while ((line = br.readLine()) != null) {
                StringTokenizer st = new StringTokenizer(line);
                while (st.hasMoreTokens()) {
                    String token = st.nextToken();
                    double d = new Double(token).doubleValue();
                    double cdf = Probability.normalCDF(d);
                    System.out.println("Normal CDF at " + formatter.format(d) + 
                                       " is " + formatter.format(cdf));
                }
            }
        } catch (NumberFormatException nfe) {
            System.err.println(nfe.getMessage());
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
        }
    }
} // TestProb

Here are the points to note.

Compiling Running the program

[*]

Let us consider case 1 first. In this case, one can either make sure that the entire package is available in the current directory. So, for example, the lec4 directory contains a subdirectory called probability which is where the probability package resides. Because, it is under my current directory, the following should work.

<Compiling and Running TestProb.java>=
javac TestProb.java
java TestProb

Now suppose that the probability package is installed as a subdirectory in a system area, say /usr/local/lib, rather than my current directory. Then I have to use the following invocation.

<Compiling and Running TestProb.java with package in another directory>=
javac -classpath /usr/local/lib:. TestProb.java
java -classpath /usr/local/lib:. TestProb

The -classpath option tells the compiler and runtime to look for the classes in the colon separated list of directories that follows. Don't forget to include the current directory as well.

Next, let us consider case 2. Sometimes, it is far more convenient to distribute a library as a jar file, essentially a single file containing all the classes. Suppose the jar file resides in the /usr/local/lib directory. Then the following command should be used.

<Compiling and Running TestProb.java with package as jar file>=
javac -classpath /usr/local/lib/probability.jar:. TestProb.java
java -classpath /usr/local/lib/probability.jar:. TestProb

If the jar file is in the directory where you are running the program, of course, one can omit the absolute path information.

Creating JAR files

[*]

To create JAR files, one uses the jar command, which works exactly like the tar command on unix systems. For example, to create probability.jar I used the command:

<Creating probability.jar>=
jar cvf probability.jar probability/*.class

That's it.

The JNL library

[*]

Visual Numerics has a Java Numerics Library that one can download. You can see the API here. I cannot put it online since they seem to have some conditions for download. You can download this is http://www.visualnumerics.com.

The JAMPACK library

[*]

The JAMPACK library is available from ftp://math.nist.gov/pub/Jampack/Jampack/AboutJampack.html.

This is a matrix package and is designed to deal with complex matrices. For statisticians, I think that JAMA package is more useful.

The JAMA library

[*]

The JAMA library is available from http://math.nist.gov/javanumerics/jama/

This matrix package provides useful things for us statisticians.

<TestMat.java>=
import Jama.*;
public class TestMat {
    public static void main(String[] args) {
        double[][] vals = {{1.,2.,3},{4.,5.,6.},{7.,8.,10.}};
        Matrix A = new Matrix(vals);
        System.out.println("The Matrix A is ");
        A.print(5, 1);
        System.out.println();

        Matrix b = Matrix.random(3,1);
        System.out.println("The vector b is ");
        b.print(5, 1);
        System.out.println();

        Matrix x = A.solve(b);
        System.out.println("The solution to Ax = b is ");
        x.print(5, 1);
        System.out.println();

        Matrix r = A.times(x).minus(b);
        double rnorm = r.normInf();
        System.out.println("Infinity norm of residual is " + rnorm);

        System.out.println("The SVD of A is ");
        SingularValueDecomposition svd = A.svd();
        Matrix S = svd.getS();
        System.out.println("S is ");
        S.print(5, 5);
        System.out.println();
        Matrix U = svd.getU();
        System.out.println("U is ");
        U.print(5, 5);
        System.out.println();
        Matrix V = svd.getV();
        System.out.println("V is ");
        V.print(5, 5);
        System.out.println();
        
        Matrix W = (U.times(S)).times(V.transpose());
        System.out.println("W = U*S*V' is ");
        W.print(5, 1);
        System.out.println();
    }
} // TestMat
This gives the following output
The Matrix A is 

    1.0    2.0    3.0
    4.0    5.0    6.0
    7.0    8.0   10.0


The vector b is 

    0.8
    0.7
    0.5


The solution to Ax = b is 

   -0.9
    0.9
   -0.0


Infinity norm of residual is 4.440892098500626E-16

The SVD of A is 

S is 

 17.41251 0.00000 0.00000
 0.00000 0.87516 0.00000
 0.00000 0.00000 0.19687


U is 

 0.20934 0.96439 -0.16168
 0.50385 0.03532 0.86307
 0.83804 -0.26213 -0.47851


V is 

 0.46467 -0.83329 -0.29953
 0.55375 0.00950 0.83263
 0.69097 0.55276 -0.46585


w is 

    1.0    2.0    3.0
    4.0    5.0    6.0
    7.0    8.0   10.0

Indices

[*]

Code Chunks

[*] This index is generated automatically. The numeral is that of the first definition of the chunk.

Index of Identifiers

[*] Here is a list of the identifiers used, and where they appear. Underlined entries indicate the place of definition. This index is generated automatically.