root / tmp / org.txm.analec.rcp / src / JamaPlus / QRDecomposition.java @ 2164
Historique | Voir | Annoter | Télécharger (5,92 ko)
1 |
package JamaPlus; |
---|---|
2 |
import JamaPlus.util.*; |
3 |
|
4 |
/** QR Decomposition.
|
5 |
<P>
|
6 |
For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
|
7 |
orthogonal matrix Q and an n-by-n upper triangular matrix R so that
|
8 |
A = Q*R.
|
9 |
<P>
|
10 |
The QR decompostion always exists, even if the matrix does not have
|
11 |
full rank, so the constructor will never fail. The primary use of the
|
12 |
QR decomposition is in the least squares solution of nonsquare systems
|
13 |
of simultaneous linear equations. This will fail if isFullRank()
|
14 |
returns false.
|
15 |
*/
|
16 |
|
17 |
public class QRDecomposition implements java.io.Serializable { |
18 |
|
19 |
/* ------------------------
|
20 |
Class variables
|
21 |
* ------------------------ */
|
22 |
|
23 |
/** Array for internal storage of decomposition.
|
24 |
@serial internal array storage.
|
25 |
*/
|
26 |
private double[][] QR; |
27 |
|
28 |
/** Row and column dimensions.
|
29 |
@serial column dimension.
|
30 |
@serial row dimension.
|
31 |
*/
|
32 |
private int m, n; |
33 |
|
34 |
/** Array for internal storage of diagonal of R.
|
35 |
@serial diagonal of R.
|
36 |
*/
|
37 |
private double[] Rdiag; |
38 |
|
39 |
/* ------------------------
|
40 |
Constructor
|
41 |
* ------------------------ */
|
42 |
|
43 |
/** QR Decomposition, computed by Householder reflections.
|
44 |
@param A Rectangular matrix
|
45 |
@return Structure to access R and the Householder vectors and compute Q.
|
46 |
*/
|
47 |
|
48 |
public QRDecomposition (Matrix A) {
|
49 |
// Initialize.
|
50 |
QR = A.getArrayCopy(); |
51 |
m = A.getRowDimension(); |
52 |
n = A.getColumnDimension(); |
53 |
Rdiag = new double[n]; |
54 |
|
55 |
// Main loop.
|
56 |
for (int k = 0; k < n; k++) { |
57 |
// Compute 2-norm of k-th column without under/overflow.
|
58 |
double nrm = 0; |
59 |
for (int i = k; i < m; i++) { |
60 |
nrm = Math.hypot(nrm,QR[i][k]);
|
61 |
} |
62 |
|
63 |
if (nrm != 0.0) { |
64 |
// Form k-th Householder vector.
|
65 |
if (QR[k][k] < 0) { |
66 |
nrm = -nrm; |
67 |
} |
68 |
for (int i = k; i < m; i++) { |
69 |
QR[i][k] /= nrm; |
70 |
} |
71 |
QR[k][k] += 1.0;
|
72 |
|
73 |
// Apply transformation to remaining columns.
|
74 |
for (int j = k+1; j < n; j++) { |
75 |
double s = 0.0; |
76 |
for (int i = k; i < m; i++) { |
77 |
s += QR[i][k]*QR[i][j]; |
78 |
} |
79 |
s = -s/QR[k][k]; |
80 |
for (int i = k; i < m; i++) { |
81 |
QR[i][j] += s*QR[i][k]; |
82 |
} |
83 |
} |
84 |
} |
85 |
Rdiag[k] = -nrm; |
86 |
} |
87 |
} |
88 |
|
89 |
/* ------------------------
|
90 |
Public Methods
|
91 |
* ------------------------ */
|
92 |
|
93 |
/** Is the matrix full rank?
|
94 |
@return true if R, and hence A, has full rank.
|
95 |
*/
|
96 |
|
97 |
public boolean isFullRank () { |
98 |
for (int j = 0; j < n; j++) { |
99 |
if (Rdiag[j] == 0) |
100 |
return false; |
101 |
} |
102 |
return true; |
103 |
} |
104 |
|
105 |
/** Return the Householder vectors
|
106 |
@return Lower trapezoidal matrix whose columns define the reflections
|
107 |
*/
|
108 |
|
109 |
public Matrix getH () {
|
110 |
Matrix X = new Matrix(m,n);
|
111 |
double[][] H = X.getArray(); |
112 |
for (int i = 0; i < m; i++) { |
113 |
for (int j = 0; j < n; j++) { |
114 |
if (i >= j) {
|
115 |
H[i][j] = QR[i][j]; |
116 |
} else {
|
117 |
H[i][j] = 0.0;
|
118 |
} |
119 |
} |
120 |
} |
121 |
return X;
|
122 |
} |
123 |
|
124 |
/** Return the upper triangular factor
|
125 |
@return R
|
126 |
*/
|
127 |
|
128 |
public Matrix getR () {
|
129 |
Matrix X = new Matrix(n,n);
|
130 |
double[][] R = X.getArray(); |
131 |
for (int i = 0; i < n; i++) { |
132 |
for (int j = 0; j < n; j++) { |
133 |
if (i < j) {
|
134 |
R[i][j] = QR[i][j]; |
135 |
} else if (i == j) { |
136 |
R[i][j] = Rdiag[i]; |
137 |
} else {
|
138 |
R[i][j] = 0.0;
|
139 |
} |
140 |
} |
141 |
} |
142 |
return X;
|
143 |
} |
144 |
|
145 |
/** Generate and return the (economy-sized) orthogonal factor
|
146 |
@return Q
|
147 |
*/
|
148 |
|
149 |
public Matrix getQ () {
|
150 |
Matrix X = new Matrix(m,n);
|
151 |
double[][] Q = X.getArray(); |
152 |
for (int k = n-1; k >= 0; k--) { |
153 |
for (int i = 0; i < m; i++) { |
154 |
Q[i][k] = 0.0;
|
155 |
} |
156 |
Q[k][k] = 1.0;
|
157 |
for (int j = k; j < n; j++) { |
158 |
if (QR[k][k] != 0) { |
159 |
double s = 0.0; |
160 |
for (int i = k; i < m; i++) { |
161 |
s += QR[i][k]*Q[i][j]; |
162 |
} |
163 |
s = -s/QR[k][k]; |
164 |
for (int i = k; i < m; i++) { |
165 |
Q[i][j] += s*QR[i][k]; |
166 |
} |
167 |
} |
168 |
} |
169 |
} |
170 |
return X;
|
171 |
} |
172 |
|
173 |
/** Least squares solution of A*X = B
|
174 |
@param B A Matrix with as many rows as A and any number of columns.
|
175 |
@return X that minimizes the two norm of Q*R*X-B.
|
176 |
@exception IllegalArgumentException Matrix row dimensions must agree.
|
177 |
@exception RuntimeException Matrix is rank deficient.
|
178 |
*/
|
179 |
|
180 |
public Matrix solve (Matrix B) {
|
181 |
if (B.getRowDimension() != m) {
|
182 |
throw new IllegalArgumentException("Matrix row dimensions must agree."); |
183 |
} |
184 |
if (!this.isFullRank()) { |
185 |
throw new RuntimeException("Matrix is rank deficient."); |
186 |
} |
187 |
|
188 |
// Copy right hand side
|
189 |
int nx = B.getColumnDimension();
|
190 |
double[][] X = B.getArrayCopy(); |
191 |
|
192 |
// Compute Y = transpose(Q)*B
|
193 |
for (int k = 0; k < n; k++) { |
194 |
for (int j = 0; j < nx; j++) { |
195 |
double s = 0.0; |
196 |
for (int i = k; i < m; i++) { |
197 |
s += QR[i][k]*X[i][j]; |
198 |
} |
199 |
s = -s/QR[k][k]; |
200 |
for (int i = k; i < m; i++) { |
201 |
X[i][j] += s*QR[i][k]; |
202 |
} |
203 |
} |
204 |
} |
205 |
// Solve R*X = Y;
|
206 |
for (int k = n-1; k >= 0; k--) { |
207 |
for (int j = 0; j < nx; j++) { |
208 |
X[k][j] /= Rdiag[k]; |
209 |
} |
210 |
for (int i = 0; i < k; i++) { |
211 |
for (int j = 0; j < nx; j++) { |
212 |
X[i][j] -= X[k][j]*QR[i][k]; |
213 |
} |
214 |
} |
215 |
} |
216 |
return (new Matrix(X,n,nx).getMatrix(0,n-1,0,nx-1)); |
217 |
} |
218 |
} |