I would like to forward this to the list so that others can look at it and comment as well. Please do try to use the Developers List as I am not always available, others may have more experience with a particular class or implementation in the package.

I will do an initial commit of the code into experimental, and once the code has been deemed acceptable by the group, we can migrate the solver into src/java and the Test into src/test.

Cheers,
-Mark


Hello Mark,

to extend the jakarta-math.linear-package I've implemented the Cholesky-algorithm.

The attached Zip-file contains
* CholeskySolver.java (the algorithm)
* CholeskySolverTest.java (JUnit-TestCase)
* BugfixAndSuggestions.txt (to impove RealMatrixImpl.java)

If you okay this contribution, I will volunteer for
Householder decomposition (QR), Gauss-Seidel iteration and
Jacobi iteration. Since this will become some work, I would like to see a positive reaction first.


I think we will find theres lots of room to move forward with implementing these algorithms. I would suggest to continue with your approach. Much of my own interest is currently in architecture and reusability, so we could always use a hand in algorithm development. If we do make any architectural decisions, it may effect what you've submitted through refactoring.

Frankfurt a. M., 23.11.2003
Stefan Koeberle

[EMAIL PROTECTED]

I'm going to include the recommendation to RealMatrix in this email so we can get comments from the group.

1. RealMatrixImpl.multiply
Method RealMatrixImpl.multiply is broken. It can't multiply a Matrix of dimension n*k with a matrix of dimension k*m for k<>n<>m. I append a correct implementation of this method and an additional test for RealMatrixImplTest.multiply somewhere below.


Sensible. I will apply this to RealMatrix and test it.

2. RealMatrixImpl.getData
Method RealMatrixImpl.getData returns a copy of the stored data. Every call of this method will require the allocation of a new double[][]-object and the
corresponding copy-operation. Since it is called in RealMatrixImpl.add,
RealMatrixImpl.subtract, ... this behaviour will wreck performance. It's completely unnecessary, too.
Suggestion: RealMatrixImpl.getData should return a reference to the stored array. Method RealMatrixImpl.getDataRef is unnecessary and should be removed.


I suspect this is an area where discussions concerning encapsulation and exposure of internal datastructures can get heated. Yes, unnecessary copying should be avoided when performing Matrix operations.

Traditionally, we should possibly consider the usage of methods like Object[] toArray() of the collections API as a model. Does this publically exposed method always create a copy of the Collections internal datastructure? Yes, infact it does:

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collection.html#toArray()

But, well documented behaviors should be made because an Object[] simply holds references to the same Objects that are referenced in the Collection, and not a new copy of that object. If the same concept is applied to

public double[][] toDoubleArray()

and it actually returns a copy, changing a value at foo.toDoubleArray()[x][y] doesn't change the double stored in the internal double[][] as well. The primitive case can't be made behaviorally equivalent to the Collection case.


I think we should maintain methods that return a copy and methods that return a reference, I would recommend that methods that return a reference be protected and used internally for processing methods like RealMatrixImpl.subtract. your correct about the copying, simply replacing all the getData() methods with getDataRef() methods solves this however.

public RealMatrix subtract(RealMatrix m) throws IllegalArgumentException {
...
*double[][] mData = m.getDataRef();*
for (int row = 0; row < rowCount; row++) {
for (int col = 0; col < columnCount; col++) {
outData[row][col] = data[row][col] - mData[row][col];
}
}
return new RealMatrixImpl(outData);
}



3. RealMatrixImpl.getIdentity
Method RealMatrixImpl.getIdentity doesn't GET an internal value of RealMatrixImpl.
It creates a new matrix and should be named "createIdentity" or "newIdentity".
The code can be simplified. A new implementation is appended below.


Yes, descriptive method names should be appropriate.


4. RealMatrixImpl.toString
For debugging and testing there should be an easy way to print the elements of the matrix. I suggest to use the toString method. For a possible implementation just scroll down.


good.

public static RealMatrix newIdentity(int dimension) {
double[][] val = new double[dimension][dimension]; //here: All elements of val are zero. That is guaranteed by the
//Java language specification.
for (int i=0; i<val.length; i++) val[i][i] = 1.0d;
return new RealMatrixImpl(val);
}//newIdentity

public String toString() {
StringBuffer res = new StringBuffer();
res.append("RealMatrixImpl{");
for (int i=0; i<data.length; i++) {
if (i>0) res.append(",");
res.append("{");
for (int j=0; j<data[0].length; j++) {
if (j>0) res.append(",");
res.append(data[i][j]);
}//for
res.append("}");
}//for
res.append("}");
return res.toString();
}//toString


    /**
     * Returns the result postmultiplying this by <code>m</code>.
     * @param m    matrix to postmultiply by
     * @return     this*m
     * @throws     IllegalArgumentException
     *             if columnDimension(this) != rowDimension(m)
     */
    public RealMatrix multiply(RealMatrix m) throws IllegalArgumentException {
        if (this.getColumnDimension() != m.getRowDimension()) {
            throw new IllegalArgumentException
            ("Matrices are not multiplication compatible.");
        }
        int nRows = this.getRowDimension();
        int nCols = m.getColumnDimension();
        int nSum = this.getColumnDimension();
        double[][] mData = m.getData();
        double[][] outData = new double[nRows][nCols];
        double sum = 0;
        for (int row = 0; row < nRows; row++) {
            for (int col = 0; col < nCols; col++) {
                sum = 0;
                for (int i = 0; i < nSum; i++) {
                    sum += data[row][i] * mData[i][col];
                }
                outData[row][col] = sum;
            }
        }
        return new RealMatrixImpl(outData);
    }


//Additional Test for RealMatrixImplTest.testMultiply

private double[][] d3 = new double[][] {{1,2,3,4},{5,6,7,8}};
private double[][] d4 = new double[][] {{1},{2},{3},{4}};
private double[][] d5 = new double[][] {{30},{70}};
public void testMultiply1() { RealMatrix m3 = new RealMatrixImpl(d3); RealMatrix m4 = new RealMatrixImpl(d4);
RealMatrix m5 = new RealMatrixImpl(d5);
assertClose("m3*m4=m5", m3.multiply(m4), m5, entryTolerance);
}





--
Mark Diggory
Software Developer
Harvard MIT Data Center
http://www.hmdc.harvard.edu

Attachment: Cholesky.zip
Description: Zip compressed data

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to