To be a little clearer, I think that RealMatrix shouldn't neccessarily be an Interface, it may be more logical to use an Abstract Class as the basis for this. Then a RealMatrix could have both public, protected, and private methods well defined and usable in its implementations.

public abstract class RealMatrix{

    public static newInstance(double[][] values){
         /* instantiates a RealMatrix of a
          * generic underlying implementation
          */
    }

    /* nice generic implementation of subtraction
     * that could be overiden in the implementing
     * class. Promotes polymorphism.
     */
    public RealMatrix subtract(RealMatrix m){
        /*...*/
        int rowCount = this.getRowDimension();
        int columnCount = this.getColumnDimension();
        double[][] outData = new double[rowCount][columnCount];
        *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 RealMatrix.newInstance(outData);*
    }

...

protected abstract double[][] getDataRef();

protected abstract double[][] getData();

   ...
}

I think this is really much more usefull in the long run and can be more easily adapted to different underlying implementations in the future. The important features are the abstract implementation of the protected and public getData/Ref methods plus the Factory style RealMatrix.newInstance(outData) method.

-Mark

Mark R. Diggory wrote:

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);
}






------------------------------------------------------------------------

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

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

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



Reply via email to