Statistiques
| Révision :

root / tmp / org.txm.analec.rcp / src matt / JamaPlus / CholeskyDecomposition.java @ 1215

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