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