Statistiques
| Révision :

root / tmp / org.txm.analec.rcp / src matt / JamaPlus / CholeskyDecomposition.java @ 3202

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
}