root / tmp / org.txm.analec.rcp / src / JamaPlus / CholeskyDecomposition.java @ 673
Historique | Voir | Annoter | Télécharger (5,63 ko)
| 1 | package JamaPlus; | 
|---|---|
| 2 |  | 
| 3 |    /** Cholesky Decomposition.
 | 
| 4 |    <P>
 | 
| 5 |    For a symmetric, positive definite matrix A, the Cholesky decomposition
 | 
| 6 |    is an lower triangular matrix L so that A = L*L'.
 | 
| 7 |    <P>
 | 
| 8 |    If the matrix is not symmetric or positive definite, the constructor
 | 
| 9 |    returns a partial decomposition and sets an internal flag that may
 | 
| 10 |    be queried by the isSPD() method.
 | 
| 11 |    */
 | 
| 12 |  | 
| 13 | public class CholeskyDecomposition implements java.io.Serializable { | 
| 14 |  | 
| 15 | /* ------------------------
 | 
| 16 |    Class variables
 | 
| 17 |  * ------------------------ */
 | 
| 18 |  | 
| 19 |    /** Array for internal storage of decomposition.
 | 
| 20 |    @serial internal array storage.
 | 
| 21 |    */
 | 
| 22 | private double[][] L; | 
| 23 |  | 
| 24 |    /** Row and column dimension (square matrix).
 | 
| 25 |    @serial matrix dimension.
 | 
| 26 |    */
 | 
| 27 | private int n; | 
| 28 |  | 
| 29 |    /** Symmetric and positive definite flag.
 | 
| 30 |    @serial is symmetric and positive definite flag.
 | 
| 31 |    */
 | 
| 32 | private boolean isspd; | 
| 33 |  | 
| 34 | /* ------------------------
 | 
| 35 |    Constructor
 | 
| 36 |  * ------------------------ */
 | 
| 37 |  | 
| 38 |    /** Cholesky algorithm for symmetric and positive definite matrix.
 | 
| 39 |    @param  A   Square, symmetric matrix.
 | 
| 40 |    @return     Structure to access L and isspd flag.
 | 
| 41 |    */
 | 
| 42 |  | 
| 43 |    public CholeskyDecomposition (Matrix Arg) {
 | 
| 44 |  | 
| 45 |  | 
| 46 |      // Initialize.
 | 
| 47 | double[][] A = Arg.getArray(); | 
| 48 | n = Arg.getRowDimension(); | 
| 49 | L = new double[n][n]; | 
| 50 | isspd = (Arg.getColumnDimension() == n); | 
| 51 |       // Main loop.
 | 
| 52 | for (int j = 0; j < n; j++) { | 
| 53 | double[] Lrowj = L[j]; | 
| 54 | double d = 0.0; | 
| 55 | for (int k = 0; k < j; k++) { | 
| 56 | double[] Lrowk = L[k]; | 
| 57 | double s = 0.0; | 
| 58 | for (int i = 0; i < k; i++) { | 
| 59 | s += Lrowk[i]*Lrowj[i]; | 
| 60 | } | 
| 61 | Lrowj[k] = s = (A[j][k] - s)/L[k][k]; | 
| 62 | d = d + s*s; | 
| 63 | isspd = isspd & (A[k][j] == A[j][k]); | 
| 64 | } | 
| 65 | d = A[j][j] - d; | 
| 66 |          isspd = isspd & (d > 0.0);
 | 
| 67 | L[j][j] = Math.sqrt(Math.max(d,0.0)); | 
| 68 | for (int k = j+1; k < n; k++) { | 
| 69 |             L[j][k] = 0.0;
 | 
| 70 | } | 
| 71 | } | 
| 72 | } | 
| 73 |  | 
| 74 | /* ------------------------
 | 
| 75 |    Temporary, experimental code.
 | 
| 76 |  * ------------------------ *\
 | 
| 77 |  | 
| 78 |    \** Right Triangular Cholesky Decomposition.
 | 
| 79 |    <P>
 | 
| 80 |    For a symmetric, positive definite matrix A, the Right Cholesky
 | 
| 81 |    decomposition is an upper triangular matrix R so that A = R'*R.
 | 
| 82 |    This constructor computes R with the Fortran inspired column oriented
 | 
| 83 |    algorithm used in LINPACK and MATLAB.  In Java, we suspect a row oriented,
 | 
| 84 |    lower triangular decomposition is faster.  We have temporarily included
 | 
| 85 |    this constructor here until timing experiments confirm this suspicion.
 | 
| 86 |    *\
 | 
| 87 |  | 
| 88 |    \** Array for internal storage of right triangular decomposition. **\
 | 
| 89 |    private transient double[][] R;
 | 
| 90 |  | 
| 91 |    \** Cholesky algorithm for symmetric and positive definite matrix.
 | 
| 92 |    @param  A           Square, symmetric matrix.
 | 
| 93 |    @param  rightflag   Actual value ignored.
 | 
| 94 |    @return             Structure to access R and isspd flag.
 | 
| 95 |    *\
 | 
| 96 |  | 
| 97 |    public CholeskyDecomposition (Matrix Arg, int rightflag) {
 | 
| 98 |       // Initialize.
 | 
| 99 |       double[][] A = Arg.getArray();
 | 
| 100 |       n = Arg.getColumnDimension();
 | 
| 101 |       R = new double[n][n];
 | 
| 102 |       isspd = (Arg.getColumnDimension() == n);
 | 
| 103 |       // Main loop.
 | 
| 104 |       for (int j = 0; j < n; j++) {
 | 
| 105 |          double d = 0.0;
 | 
| 106 |          for (int k = 0; k < j; k++) {
 | 
| 107 |             double s = A[k][j];
 | 
| 108 |             for (int i = 0; i < k; i++) {
 | 
| 109 |                s = s - R[i][k]*R[i][j];
 | 
| 110 |             }
 | 
| 111 |             R[k][j] = s = s/R[k][k];
 | 
| 112 |             d = d + s*s;
 | 
| 113 |             isspd = isspd & (A[k][j] == A[j][k]); 
 | 
| 114 |          }
 | 
| 115 |          d = A[j][j] - d;
 | 
| 116 |          isspd = isspd & (d > 0.0);
 | 
| 117 |          R[j][j] = Math.sqrt(Math.max(d,0.0));
 | 
| 118 |          for (int k = j+1; k < n; k++) {
 | 
| 119 |             R[k][j] = 0.0;
 | 
| 120 |          }
 | 
| 121 |       }
 | 
| 122 |    }
 | 
| 123 |  | 
| 124 |    \** Return upper triangular factor.
 | 
| 125 |    @return     R
 | 
| 126 |    *\
 | 
| 127 |  | 
| 128 |    public Matrix getR () {
 | 
| 129 |       return new Matrix(R,n,n);
 | 
| 130 |    }
 | 
| 131 |  | 
| 132 | \* ------------------------
 | 
| 133 |    End of temporary code.
 | 
| 134 |  * ------------------------ */
 | 
| 135 |  | 
| 136 | /* ------------------------
 | 
| 137 |    Public Methods
 | 
| 138 |  * ------------------------ */
 | 
| 139 |  | 
| 140 |    /** Is the matrix symmetric and positive definite?
 | 
| 141 |    @return     true if A is symmetric and positive definite.
 | 
| 142 |    */
 | 
| 143 |  | 
| 144 | public boolean isSPD () { | 
| 145 |       return isspd;
 | 
| 146 | } | 
| 147 |  | 
| 148 |    /** Return triangular factor.
 | 
| 149 |    @return     L
 | 
| 150 |    */
 | 
| 151 |  | 
| 152 |    public Matrix getL () {
 | 
| 153 | return new Matrix(L,n,n); | 
| 154 | } | 
| 155 |  | 
| 156 |    /** Solve A*X = B
 | 
| 157 |    @param  B   A Matrix with as many rows as A and any number of columns.
 | 
| 158 |    @return     X so that L*L'*X = B
 | 
| 159 |    @exception  IllegalArgumentException  Matrix row dimensions must agree.
 | 
| 160 |    @exception  RuntimeException  Matrix is not symmetric positive definite.
 | 
| 161 |    */
 | 
| 162 |  | 
| 163 |    public Matrix solve (Matrix B) {
 | 
| 164 |       if (B.getRowDimension() != n) {
 | 
| 165 | throw new IllegalArgumentException("Matrix row dimensions must agree."); | 
| 166 | } | 
| 167 |       if (!isspd) {
 | 
| 168 | throw new RuntimeException("Matrix is not symmetric positive definite."); | 
| 169 | } | 
| 170 |  | 
| 171 |       // Copy right hand side.
 | 
| 172 | double[][] X = B.getArrayCopy(); | 
| 173 |       int nx = B.getColumnDimension();
 | 
| 174 |  | 
| 175 |               // Solve L*Y = B;
 | 
| 176 | for (int k = 0; k < n; k++) { | 
| 177 | for (int j = 0; j < nx; j++) { | 
| 178 | for (int i = 0; i < k ; i++) { | 
| 179 | X[k][j] -= X[i][j]*L[k][i]; | 
| 180 | } | 
| 181 | X[k][j] /= L[k][k]; | 
| 182 | } | 
| 183 | } | 
| 184 |  | 
| 185 |               // Solve L'*X = Y;
 | 
| 186 | for (int k = n-1; k >= 0; k--) { | 
| 187 | for (int j = 0; j < nx; j++) { | 
| 188 | for (int i = k+1; i < n ; i++) { | 
| 189 | X[k][j] -= X[i][j]*L[i][k]; | 
| 190 | } | 
| 191 | X[k][j] /= L[k][k]; | 
| 192 | } | 
| 193 | } | 
| 194 |  | 
| 195 |  | 
| 196 | return new Matrix(X,n,nx); | 
| 197 | } | 
| 198 | } | 
| 199 |  |