Statistiques
| Révision :

root / tmp / org.txm.analec.rcp / src / JamaPlus / LUDecomposition.java @ 2019

Historique | Voir | Annoter | Télécharger (8,29 ko)

1 481 mdecorde
package JamaPlus;
2 481 mdecorde
3 481 mdecorde
   /** LU Decomposition.
4 481 mdecorde
   <P>
5 481 mdecorde
   For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
6 481 mdecorde
   unit lower triangular matrix L, an n-by-n upper triangular matrix U,
7 481 mdecorde
   and a permutation vector piv of length m so that A(piv,:) = L*U.
8 481 mdecorde
   If m < n, then L is m-by-m and U is m-by-n.
9 481 mdecorde
   <P>
10 481 mdecorde
   The LU decompostion with pivoting always exists, even if the matrix is
11 481 mdecorde
   singular, so the constructor will never fail.  The primary use of the
12 481 mdecorde
   LU decomposition is in the solution of square systems of simultaneous
13 481 mdecorde
   linear equations.  This will fail if isNonsingular() returns false.
14 481 mdecorde
   */
15 481 mdecorde
16 481 mdecorde
public class LUDecomposition implements java.io.Serializable {
17 481 mdecorde
18 481 mdecorde
/* ------------------------
19 481 mdecorde
   Class variables
20 481 mdecorde
 * ------------------------ */
21 481 mdecorde
22 481 mdecorde
   /** Array for internal storage of decomposition.
23 481 mdecorde
   @serial internal array storage.
24 481 mdecorde
   */
25 481 mdecorde
   private double[][] LU;
26 481 mdecorde
27 481 mdecorde
   /** Row and column dimensions, and pivot sign.
28 481 mdecorde
   @serial column dimension.
29 481 mdecorde
   @serial row dimension.
30 481 mdecorde
   @serial pivot sign.
31 481 mdecorde
   */
32 481 mdecorde
   private int m, n, pivsign;
33 481 mdecorde
34 481 mdecorde
   /** Internal storage of pivot vector.
35 481 mdecorde
   @serial pivot vector.
36 481 mdecorde
   */
37 481 mdecorde
   private int[] piv;
38 481 mdecorde
39 481 mdecorde
/* ------------------------
40 481 mdecorde
   Constructor
41 481 mdecorde
 * ------------------------ */
42 481 mdecorde
43 481 mdecorde
   /** LU Decomposition
44 481 mdecorde
   @param  A   Rectangular matrix
45 481 mdecorde
   @return     Structure to access L, U and piv.
46 481 mdecorde
   */
47 481 mdecorde
48 481 mdecorde
   public LUDecomposition (Matrix A) {
49 481 mdecorde
50 481 mdecorde
   // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
51 481 mdecorde
52 481 mdecorde
      LU = A.getArrayCopy();
53 481 mdecorde
      m = A.getRowDimension();
54 481 mdecorde
      n = A.getColumnDimension();
55 481 mdecorde
      piv = new int[m];
56 481 mdecorde
      for (int i = 0; i < m; i++) {
57 481 mdecorde
         piv[i] = i;
58 481 mdecorde
      }
59 481 mdecorde
      pivsign = 1;
60 481 mdecorde
      double[] LUrowi;
61 481 mdecorde
      double[] LUcolj = new double[m];
62 481 mdecorde
63 481 mdecorde
      // Outer loop.
64 481 mdecorde
65 481 mdecorde
      for (int j = 0; j < n; j++) {
66 481 mdecorde
67 481 mdecorde
         // Make a copy of the j-th column to localize references.
68 481 mdecorde
69 481 mdecorde
         for (int i = 0; i < m; i++) {
70 481 mdecorde
            LUcolj[i] = LU[i][j];
71 481 mdecorde
         }
72 481 mdecorde
73 481 mdecorde
         // Apply previous transformations.
74 481 mdecorde
75 481 mdecorde
         for (int i = 0; i < m; i++) {
76 481 mdecorde
            LUrowi = LU[i];
77 481 mdecorde
78 481 mdecorde
            // Most of the time is spent in the following dot product.
79 481 mdecorde
80 481 mdecorde
            int kmax = Math.min(i,j);
81 481 mdecorde
            double s = 0.0;
82 481 mdecorde
            for (int k = 0; k < kmax; k++) {
83 481 mdecorde
               s += LUrowi[k]*LUcolj[k];
84 481 mdecorde
            }
85 481 mdecorde
86 481 mdecorde
            LUrowi[j] = LUcolj[i] -= s;
87 481 mdecorde
         }
88 481 mdecorde
89 481 mdecorde
         // Find pivot and exchange if necessary.
90 481 mdecorde
91 481 mdecorde
         int p = j;
92 481 mdecorde
         for (int i = j+1; i < m; i++) {
93 481 mdecorde
            if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) {
94 481 mdecorde
               p = i;
95 481 mdecorde
            }
96 481 mdecorde
         }
97 481 mdecorde
         if (p != j) {
98 481 mdecorde
            for (int k = 0; k < n; k++) {
99 481 mdecorde
               double t = LU[p][k]; LU[p][k] = LU[j][k]; LU[j][k] = t;
100 481 mdecorde
            }
101 481 mdecorde
            int k = piv[p]; piv[p] = piv[j]; piv[j] = k;
102 481 mdecorde
            pivsign = -pivsign;
103 481 mdecorde
         }
104 481 mdecorde
105 481 mdecorde
         // Compute multipliers.
106 481 mdecorde
107 481 mdecorde
         if (j < m & LU[j][j] != 0.0) {
108 481 mdecorde
            for (int i = j+1; i < m; i++) {
109 481 mdecorde
               LU[i][j] /= LU[j][j];
110 481 mdecorde
            }
111 481 mdecorde
         }
112 481 mdecorde
      }
113 481 mdecorde
   }
114 481 mdecorde
115 481 mdecorde
/* ------------------------
116 481 mdecorde
   Temporary, experimental code.
117 481 mdecorde
   ------------------------ *\
118 481 mdecorde

119 481 mdecorde
   \** LU Decomposition, computed by Gaussian elimination.
120 481 mdecorde
   <P>
121 481 mdecorde
   This constructor computes L and U with the "daxpy"-based elimination
122 481 mdecorde
   algorithm used in LINPACK and MATLAB.  In Java, we suspect the dot-product,
123 481 mdecorde
   Crout algorithm will be faster.  We have temporarily included this
124 481 mdecorde
   constructor until timing experiments confirm this suspicion.
125 481 mdecorde
   <P>
126 481 mdecorde
   @param  A             Rectangular matrix
127 481 mdecorde
   @param  linpackflag   Use Gaussian elimination.  Actual value ignored.
128 481 mdecorde
   @return               Structure to access L, U and piv.
129 481 mdecorde
   *\
130 481 mdecorde

131 481 mdecorde
   public LUDecomposition (Matrix A, int linpackflag) {
132 481 mdecorde
      // Initialize.
133 481 mdecorde
      LU = A.getArrayCopy();
134 481 mdecorde
      m = A.getRowDimension();
135 481 mdecorde
      n = A.getColumnDimension();
136 481 mdecorde
      piv = new int[m];
137 481 mdecorde
      for (int i = 0; i < m; i++) {
138 481 mdecorde
         piv[i] = i;
139 481 mdecorde
      }
140 481 mdecorde
      pivsign = 1;
141 481 mdecorde
      // Main loop.
142 481 mdecorde
      for (int k = 0; k < n; k++) {
143 481 mdecorde
         // Find pivot.
144 481 mdecorde
         int p = k;
145 481 mdecorde
         for (int i = k+1; i < m; i++) {
146 481 mdecorde
            if (Math.abs(LU[i][k]) > Math.abs(LU[p][k])) {
147 481 mdecorde
               p = i;
148 481 mdecorde
            }
149 481 mdecorde
         }
150 481 mdecorde
         // Exchange if necessary.
151 481 mdecorde
         if (p != k) {
152 481 mdecorde
            for (int j = 0; j < n; j++) {
153 481 mdecorde
               double t = LU[p][j]; LU[p][j] = LU[k][j]; LU[k][j] = t;
154 481 mdecorde
            }
155 481 mdecorde
            int t = piv[p]; piv[p] = piv[k]; piv[k] = t;
156 481 mdecorde
            pivsign = -pivsign;
157 481 mdecorde
         }
158 481 mdecorde
         // Compute multipliers and eliminate k-th column.
159 481 mdecorde
         if (LU[k][k] != 0.0) {
160 481 mdecorde
            for (int i = k+1; i < m; i++) {
161 481 mdecorde
               LU[i][k] /= LU[k][k];
162 481 mdecorde
               for (int j = k+1; j < n; j++) {
163 481 mdecorde
                  LU[i][j] -= LU[i][k]*LU[k][j];
164 481 mdecorde
               }
165 481 mdecorde
            }
166 481 mdecorde
         }
167 481 mdecorde
      }
168 481 mdecorde
   }
169 481 mdecorde

170 481 mdecorde
\* ------------------------
171 481 mdecorde
   End of temporary code.
172 481 mdecorde
 * ------------------------ */
173 481 mdecorde
174 481 mdecorde
/* ------------------------
175 481 mdecorde
   Public Methods
176 481 mdecorde
 * ------------------------ */
177 481 mdecorde
178 481 mdecorde
   /** Is the matrix nonsingular?
179 481 mdecorde
   @return     true if U, and hence A, is nonsingular.
180 481 mdecorde
   */
181 481 mdecorde
182 481 mdecorde
   public boolean isNonsingular () {
183 481 mdecorde
      for (int j = 0; j < n; j++) {
184 481 mdecorde
         if (LU[j][j] == 0)
185 481 mdecorde
            return false;
186 481 mdecorde
      }
187 481 mdecorde
      return true;
188 481 mdecorde
   }
189 481 mdecorde
190 481 mdecorde
   /** Return lower triangular factor
191 481 mdecorde
   @return     L
192 481 mdecorde
   */
193 481 mdecorde
194 481 mdecorde
   public Matrix getL () {
195 481 mdecorde
      Matrix X = new Matrix(m,n);
196 481 mdecorde
      double[][] L = X.getArray();
197 481 mdecorde
      for (int i = 0; i < m; i++) {
198 481 mdecorde
         for (int j = 0; j < n; j++) {
199 481 mdecorde
            if (i > j) {
200 481 mdecorde
               L[i][j] = LU[i][j];
201 481 mdecorde
            } else if (i == j) {
202 481 mdecorde
               L[i][j] = 1.0;
203 481 mdecorde
            } else {
204 481 mdecorde
               L[i][j] = 0.0;
205 481 mdecorde
            }
206 481 mdecorde
         }
207 481 mdecorde
      }
208 481 mdecorde
      return X;
209 481 mdecorde
   }
210 481 mdecorde
211 481 mdecorde
   /** Return upper triangular factor
212 481 mdecorde
   @return     U
213 481 mdecorde
   */
214 481 mdecorde
215 481 mdecorde
   public Matrix getU () {
216 481 mdecorde
      Matrix X = new Matrix(n,n);
217 481 mdecorde
      double[][] U = X.getArray();
218 481 mdecorde
      for (int i = 0; i < n; i++) {
219 481 mdecorde
         for (int j = 0; j < n; j++) {
220 481 mdecorde
            if (i <= j) {
221 481 mdecorde
               U[i][j] = LU[i][j];
222 481 mdecorde
            } else {
223 481 mdecorde
               U[i][j] = 0.0;
224 481 mdecorde
            }
225 481 mdecorde
         }
226 481 mdecorde
      }
227 481 mdecorde
      return X;
228 481 mdecorde
   }
229 481 mdecorde
230 481 mdecorde
   /** Return pivot permutation vector
231 481 mdecorde
   @return     piv
232 481 mdecorde
   */
233 481 mdecorde
234 481 mdecorde
   public int[] getPivot () {
235 481 mdecorde
      int[] p = new int[m];
236 481 mdecorde
      for (int i = 0; i < m; i++) {
237 481 mdecorde
         p[i] = piv[i];
238 481 mdecorde
      }
239 481 mdecorde
      return p;
240 481 mdecorde
   }
241 481 mdecorde
242 481 mdecorde
   /** Return pivot permutation vector as a one-dimensional double array
243 481 mdecorde
   @return     (double) piv
244 481 mdecorde
   */
245 481 mdecorde
246 481 mdecorde
   public double[] getDoublePivot () {
247 481 mdecorde
      double[] vals = new double[m];
248 481 mdecorde
      for (int i = 0; i < m; i++) {
249 481 mdecorde
         vals[i] = (double) piv[i];
250 481 mdecorde
      }
251 481 mdecorde
      return vals;
252 481 mdecorde
   }
253 481 mdecorde
254 481 mdecorde
   /** Determinant
255 481 mdecorde
   @return     det(A)
256 481 mdecorde
   @exception  IllegalArgumentException  Matrix must be square
257 481 mdecorde
   */
258 481 mdecorde
259 481 mdecorde
   public double det () {
260 481 mdecorde
      if (m != n) {
261 481 mdecorde
         throw new IllegalArgumentException("Matrix must be square.");
262 481 mdecorde
      }
263 481 mdecorde
      double d = (double) pivsign;
264 481 mdecorde
      for (int j = 0; j < n; j++) {
265 481 mdecorde
         d *= LU[j][j];
266 481 mdecorde
      }
267 481 mdecorde
      return d;
268 481 mdecorde
   }
269 481 mdecorde
270 481 mdecorde
   /** Solve A*X = B
271 481 mdecorde
   @param  B   A Matrix with as many rows as A and any number of columns.
272 481 mdecorde
   @return     X so that L*U*X = B(piv,:)
273 481 mdecorde
   @exception  IllegalArgumentException Matrix row dimensions must agree.
274 481 mdecorde
   @exception  RuntimeException  Matrix is singular.
275 481 mdecorde
   */
276 481 mdecorde
277 481 mdecorde
   public Matrix solve (Matrix B) {
278 481 mdecorde
      if (B.getRowDimension() != m) {
279 481 mdecorde
         throw new IllegalArgumentException("Matrix row dimensions must agree.");
280 481 mdecorde
      }
281 481 mdecorde
      if (!this.isNonsingular()) {
282 481 mdecorde
         throw new RuntimeException("Matrix is singular.");
283 481 mdecorde
      }
284 481 mdecorde
285 481 mdecorde
      // Copy right hand side with pivoting
286 481 mdecorde
      int nx = B.getColumnDimension();
287 481 mdecorde
      Matrix Xmat = B.getMatrix(piv,0,nx-1);
288 481 mdecorde
      double[][] X = Xmat.getArray();
289 481 mdecorde
290 481 mdecorde
      // Solve L*Y = B(piv,:)
291 481 mdecorde
      for (int k = 0; k < n; k++) {
292 481 mdecorde
         for (int i = k+1; i < n; i++) {
293 481 mdecorde
            for (int j = 0; j < nx; j++) {
294 481 mdecorde
               X[i][j] -= X[k][j]*LU[i][k];
295 481 mdecorde
            }
296 481 mdecorde
         }
297 481 mdecorde
      }
298 481 mdecorde
      // Solve U*X = Y;
299 481 mdecorde
      for (int k = n-1; k >= 0; k--) {
300 481 mdecorde
         for (int j = 0; j < nx; j++) {
301 481 mdecorde
            X[k][j] /= LU[k][k];
302 481 mdecorde
         }
303 481 mdecorde
         for (int i = 0; i < k; i++) {
304 481 mdecorde
            for (int j = 0; j < nx; j++) {
305 481 mdecorde
               X[i][j] -= X[k][j]*LU[i][k];
306 481 mdecorde
            }
307 481 mdecorde
         }
308 481 mdecorde
      }
309 481 mdecorde
      return Xmat;
310 481 mdecorde
   }
311 481 mdecorde
}