-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Getting a more functional Style for Cholesky #33
Comments
Note: This should hopefully make the Cholesky decomposition easier to understand and use for users.... stateful interfaces are always trickier to use because it isn't obvious what order you need to set values etc. |
If the result is returned as a |
I mean,
or maybe a |
I also removed the setExpectedMaxSize function from CholeskyLDU. Now it just assigns new arrays when the decompose method is called. public class CholeskyLDU implements ICholeskyLDU {
// it can decompose a matrix up to this width
private int maxWidth;
// width and height of the matrix
private int n;
// the decomposed matrix
private Matrix L;
private double[] el;
// the D vector
private double[] d;
// tempoary variable used by various functions
double vv[];
public CholeskyResult decompose( AMatrix mat ) {
if( mat.rowCount() != mat.columnCount() ) {
throw new RuntimeException("Can only decompose square matrices");
}
n = mat.rowCount();
this.vv = new double[n];
this.d = new double[n];
L = mat.toMatrix();
this.el = L.data;
double d_inv=0;
for( int i = 0; i < n; i++ ) {
for( int j = i; j < n; j++ ) {
double sum = el[i*n+j];
for( int k = 0; k < i; k++ ) {
sum -= el[i*n+k]*el[j*n+k]*d[k];
}
if( i == j ) {
// is it positive-definate?
if( sum <= 0.0 )
return null;
d[i] = sum;
d_inv = 1.0/sum;
el[i*n+i] = 1;
} else {
el[j*n+i] = sum*d_inv;
}
}
}
// zero the top right corner.
for( int i = 0; i < n; i++ ) {
for( int j = i+1; j < n; j++ ) {
el[i*n+j] = 0.0;
}
}
return new CholeskyResult(L, DiagonalMatrix.create(d), L.getTranspose());
}
public ADiagonalMatrix getD() {
return DiagonalMatrix.create(d);
}
public AMatrix getL() {
return L;
}
public double[] _getVV() {
return vv;
}
@Override
public AMatrix getU() {
return L.getTranspose();
}
} |
This looks like it is going in the right direction, though I think we can simplify it further. The object that represents the result ( This is an example of the "Single Responsibility Principle" - each object / function should have one and only one reason for existing. So we should ideally separate:
Does that make sense? There's some more reading on the SRP here if you are interested, in general I find it to be a very useful technique: http://en.wikipedia.org/wiki/Single_responsibility_principle Originally the SRP applied to mutable objects, but it also works well in functional programming - each entity should have one function / reason for existing. |
Hi @prasant94 - The initial Cholesky stuff looks good, but I think we should try to convert this to a more "functional" interface.
By which I mean:
setExpectedMaxSize
) - any such values should be set as final fields when objects are constructed. It's OK to mutate as an implementation detail of courseAs an example, I've converted the old Cholesky code to return a CholeskyResult in this style
The text was updated successfully, but these errors were encountered: