source: src/main/java/agents/Jama/QRDecomposition.java

Last change on this file was 1, checked in by Wouter Pasman, 6 years ago

Initial import : Genius 9.0.0

File size: 5.8 KB
Line 
1package agents.Jama;
2import agents.Jama.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
17public 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 Structure to access R and the Householder vectors and compute Q.
45 @param A Rectangular matrix
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 = Maths.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 private static final long serialVersionUID = 1;
219}
Note: See TracBrowser for help on using the repository browser.