Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (5,92 ko)

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