Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/2.5.0/ALGLIB-2.5.0/spdgevd.cs @ 4068

Last change on this file since 4068 was 4068, checked in by swagner, 14 years ago

Sorted usings and removed unused usings in entire solution (#1094)

File size: 15.5 KB
Line 
1/*************************************************************************
2Copyright (c) 2005-2007, Sergey Bochkanov (ALGLIB project).
3
4>>> SOURCE LICENSE >>>
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation (www.fsf.org); either version 2 of the
8License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15A copy of the GNU General Public License is available at
16http://www.fsf.org/licensing/licenses
17
18>>> END OF LICENSE >>>
19*************************************************************************/
20
21
22namespace alglib {
23  public class spdgevd {
24    /*************************************************************************
25    Algorithm for solving the following generalized symmetric positive-definite
26    eigenproblem:
27        A*x = lambda*B*x (1) or
28        A*B*x = lambda*x (2) or
29        B*A*x = lambda*x (3).
30    where A is a symmetric matrix, B - symmetric positive-definite matrix.
31    The problem is solved by reducing it to an ordinary  symmetric  eigenvalue
32    problem.
33
34    Input parameters:
35        A           -   symmetric matrix which is given by its upper or lower
36                        triangular part.
37                        Array whose indexes range within [0..N-1, 0..N-1].
38        N           -   size of matrices A and B.
39        IsUpperA    -   storage format of matrix A.
40        B           -   symmetric positive-definite matrix which is given by
41                        its upper or lower triangular part.
42                        Array whose indexes range within [0..N-1, 0..N-1].
43        IsUpperB    -   storage format of matrix B.
44        ZNeeded     -   if ZNeeded is equal to:
45                         * 0, the eigenvectors are not returned;
46                         * 1, the eigenvectors are returned.
47        ProblemType -   if ProblemType is equal to:
48                         * 1, the following problem is solved: A*x = lambda*B*x;
49                         * 2, the following problem is solved: A*B*x = lambda*x;
50                         * 3, the following problem is solved: B*A*x = lambda*x.
51
52    Output parameters:
53        D           -   eigenvalues in ascending order.
54                        Array whose index ranges within [0..N-1].
55        Z           -   if ZNeeded is equal to:
56                         * 0, Z hasn’t changed;
57                         * 1, Z contains eigenvectors.
58                        Array whose indexes range within [0..N-1, 0..N-1].
59                        The eigenvectors are stored in matrix columns. It should
60                        be noted that the eigenvectors in such problems do not
61                        form an orthogonal system.
62
63    Result:
64        True, if the problem was solved successfully.
65        False, if the error occurred during the Cholesky decomposition of matrix
66        B (the matrix isn’t positive-definite) or during the work of the iterative
67        algorithm for solving the symmetric eigenproblem.
68
69    See also the GeneralizedSymmetricDefiniteEVDReduce subroutine.
70
71      -- ALGLIB --
72         Copyright 1.28.2006 by Bochkanov Sergey
73    *************************************************************************/
74    public static bool smatrixgevd(double[,] a,
75        int n,
76        bool isuppera,
77        ref double[,] b,
78        bool isupperb,
79        int zneeded,
80        int problemtype,
81        ref double[] d,
82        ref double[,] z) {
83      bool result = new bool();
84      double[,] r = new double[0, 0];
85      double[,] t = new double[0, 0];
86      bool isupperr = new bool();
87      int j1 = 0;
88      int j2 = 0;
89      int j1inc = 0;
90      int j2inc = 0;
91      int i = 0;
92      int j = 0;
93      double v = 0;
94      int i_ = 0;
95
96      a = (double[,])a.Clone();
97
98
99      //
100      // Reduce and solve
101      //
102      result = smatrixgevdreduce(ref a, n, isuppera, ref b, isupperb, problemtype, ref r, ref isupperr);
103      if (!result) {
104        return result;
105      }
106      result = evd.smatrixevd(a, n, zneeded, isuppera, ref d, ref t);
107      if (!result) {
108        return result;
109      }
110
111      //
112      // Transform eigenvectors if needed
113      //
114      if (zneeded != 0) {
115
116        //
117        // fill Z with zeros
118        //
119        z = new double[n - 1 + 1, n - 1 + 1];
120        for (j = 0; j <= n - 1; j++) {
121          z[0, j] = 0.0;
122        }
123        for (i = 1; i <= n - 1; i++) {
124          for (i_ = 0; i_ <= n - 1; i_++) {
125            z[i, i_] = z[0, i_];
126          }
127        }
128
129        //
130        // Setup R properties
131        //
132        if (isupperr) {
133          j1 = 0;
134          j2 = n - 1;
135          j1inc = +1;
136          j2inc = 0;
137        } else {
138          j1 = 0;
139          j2 = 0;
140          j1inc = 0;
141          j2inc = +1;
142        }
143
144        //
145        // Calculate R*Z
146        //
147        for (i = 0; i <= n - 1; i++) {
148          for (j = j1; j <= j2; j++) {
149            v = r[i, j];
150            for (i_ = 0; i_ <= n - 1; i_++) {
151              z[i, i_] = z[i, i_] + v * t[j, i_];
152            }
153          }
154          j1 = j1 + j1inc;
155          j2 = j2 + j2inc;
156        }
157      }
158      return result;
159    }
160
161
162    /*************************************************************************
163    Algorithm for reduction of the following generalized symmetric positive-
164    definite eigenvalue problem:
165        A*x = lambda*B*x (1) or
166        A*B*x = lambda*x (2) or
167        B*A*x = lambda*x (3)
168    to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues of this and
169    the given problems are the same, and the eigenvectors of the given problem
170    could be obtained by multiplying the obtained eigenvectors by the
171    transformation matrix x = R*y).
172
173    Here A is a symmetric matrix, B - symmetric positive-definite matrix.
174
175    Input parameters:
176        A           -   symmetric matrix which is given by its upper or lower
177                        triangular part.
178                        Array whose indexes range within [0..N-1, 0..N-1].
179        N           -   size of matrices A and B.
180        IsUpperA    -   storage format of matrix A.
181        B           -   symmetric positive-definite matrix which is given by
182                        its upper or lower triangular part.
183                        Array whose indexes range within [0..N-1, 0..N-1].
184        IsUpperB    -   storage format of matrix B.
185        ProblemType -   if ProblemType is equal to:
186                         * 1, the following problem is solved: A*x = lambda*B*x;
187                         * 2, the following problem is solved: A*B*x = lambda*x;
188                         * 3, the following problem is solved: B*A*x = lambda*x.
189
190    Output parameters:
191        A           -   symmetric matrix which is given by its upper or lower
192                        triangle depending on IsUpperA. Contains matrix C.
193                        Array whose indexes range within [0..N-1, 0..N-1].
194        R           -   upper triangular or low triangular transformation matrix
195                        which is used to obtain the eigenvectors of a given problem
196                        as the product of eigenvectors of C (from the right) and
197                        matrix R (from the left). If the matrix is upper
198                        triangular, the elements below the main diagonal
199                        are equal to 0 (and vice versa). Thus, we can perform
200                        the multiplication without taking into account the
201                        internal structure (which is an easier though less
202                        effective way).
203                        Array whose indexes range within [0..N-1, 0..N-1].
204        IsUpperR    -   type of matrix R (upper or lower triangular).
205
206    Result:
207        True, if the problem was reduced successfully.
208        False, if the error occurred during the Cholesky decomposition of
209            matrix B (the matrix is not positive-definite).
210
211      -- ALGLIB --
212         Copyright 1.28.2006 by Bochkanov Sergey
213    *************************************************************************/
214    public static bool smatrixgevdreduce(ref double[,] a,
215        int n,
216        bool isuppera,
217        ref double[,] b,
218        bool isupperb,
219        int problemtype,
220        ref double[,] r,
221        ref bool isupperr) {
222      bool result = new bool();
223      double[,] t = new double[0, 0];
224      double[] w1 = new double[0];
225      double[] w2 = new double[0];
226      double[] w3 = new double[0];
227      int i = 0;
228      int j = 0;
229      double v = 0;
230      matinv.matinvreport rep = new matinv.matinvreport();
231      int info = 0;
232      int i_ = 0;
233      int i1_ = 0;
234
235      System.Diagnostics.Debug.Assert(n > 0, "SMatrixGEVDReduce: N<=0!");
236      System.Diagnostics.Debug.Assert(problemtype == 1 | problemtype == 2 | problemtype == 3, "SMatrixGEVDReduce: incorrect ProblemType!");
237      result = true;
238
239      //
240      // Problem 1:  A*x = lambda*B*x
241      //
242      // Reducing to:
243      //     C*y = lambda*y
244      //     C = L^(-1) * A * L^(-T)
245      //     x = L^(-T) * y
246      //
247      if (problemtype == 1) {
248
249        //
250        // Factorize B in T: B = LL'
251        //
252        t = new double[n - 1 + 1, n - 1 + 1];
253        if (isupperb) {
254          for (i = 0; i <= n - 1; i++) {
255            for (i_ = i; i_ <= n - 1; i_++) {
256              t[i_, i] = b[i, i_];
257            }
258          }
259        } else {
260          for (i = 0; i <= n - 1; i++) {
261            for (i_ = 0; i_ <= i; i_++) {
262              t[i, i_] = b[i, i_];
263            }
264          }
265        }
266        if (!trfac.spdmatrixcholesky(ref t, n, false)) {
267          result = false;
268          return result;
269        }
270
271        //
272        // Invert L in T
273        //
274        matinv.rmatrixtrinverse(ref t, n, false, false, ref info, ref rep);
275        if (info <= 0) {
276          result = false;
277          return result;
278        }
279
280        //
281        // Build L^(-1) * A * L^(-T) in R
282        //
283        w1 = new double[n + 1];
284        w2 = new double[n + 1];
285        r = new double[n - 1 + 1, n - 1 + 1];
286        for (j = 1; j <= n; j++) {
287
288          //
289          // Form w2 = A * l'(j) (here l'(j) is j-th column of L^(-T))
290          //
291          i1_ = (0) - (1);
292          for (i_ = 1; i_ <= j; i_++) {
293            w1[i_] = t[j - 1, i_ + i1_];
294          }
295          sblas.symmetricmatrixvectormultiply(ref a, isuppera, 0, j - 1, ref w1, 1.0, ref w2);
296          if (isuppera) {
297            blas.matrixvectormultiply(ref a, 0, j - 1, j, n - 1, true, ref w1, 1, j, 1.0, ref w2, j + 1, n, 0.0);
298          } else {
299            blas.matrixvectormultiply(ref a, j, n - 1, 0, j - 1, false, ref w1, 1, j, 1.0, ref w2, j + 1, n, 0.0);
300          }
301
302          //
303          // Form l(i)*w2 (here l(i) is i-th row of L^(-1))
304          //
305          for (i = 1; i <= n; i++) {
306            i1_ = (1) - (0);
307            v = 0.0;
308            for (i_ = 0; i_ <= i - 1; i_++) {
309              v += t[i - 1, i_] * w2[i_ + i1_];
310            }
311            r[i - 1, j - 1] = v;
312          }
313        }
314
315        //
316        // Copy R to A
317        //
318        for (i = 0; i <= n - 1; i++) {
319          for (i_ = 0; i_ <= n - 1; i_++) {
320            a[i, i_] = r[i, i_];
321          }
322        }
323
324        //
325        // Copy L^(-1) from T to R and transpose
326        //
327        isupperr = true;
328        for (i = 0; i <= n - 1; i++) {
329          for (j = 0; j <= i - 1; j++) {
330            r[i, j] = 0;
331          }
332        }
333        for (i = 0; i <= n - 1; i++) {
334          for (i_ = i; i_ <= n - 1; i_++) {
335            r[i, i_] = t[i_, i];
336          }
337        }
338        return result;
339      }
340
341      //
342      // Problem 2:  A*B*x = lambda*x
343      // or
344      // problem 3:  B*A*x = lambda*x
345      //
346      // Reducing to:
347      //     C*y = lambda*y
348      //     C = U * A * U'
349      //     B = U'* U
350      //
351      if (problemtype == 2 | problemtype == 3) {
352
353        //
354        // Factorize B in T: B = U'*U
355        //
356        t = new double[n - 1 + 1, n - 1 + 1];
357        if (isupperb) {
358          for (i = 0; i <= n - 1; i++) {
359            for (i_ = i; i_ <= n - 1; i_++) {
360              t[i, i_] = b[i, i_];
361            }
362          }
363        } else {
364          for (i = 0; i <= n - 1; i++) {
365            for (i_ = i; i_ <= n - 1; i_++) {
366              t[i, i_] = b[i_, i];
367            }
368          }
369        }
370        if (!trfac.spdmatrixcholesky(ref t, n, true)) {
371          result = false;
372          return result;
373        }
374
375        //
376        // Build U * A * U' in R
377        //
378        w1 = new double[n + 1];
379        w2 = new double[n + 1];
380        w3 = new double[n + 1];
381        r = new double[n - 1 + 1, n - 1 + 1];
382        for (j = 1; j <= n; j++) {
383
384          //
385          // Form w2 = A * u'(j) (here u'(j) is j-th column of U')
386          //
387          i1_ = (j - 1) - (1);
388          for (i_ = 1; i_ <= n - j + 1; i_++) {
389            w1[i_] = t[j - 1, i_ + i1_];
390          }
391          sblas.symmetricmatrixvectormultiply(ref a, isuppera, j - 1, n - 1, ref w1, 1.0, ref w3);
392          i1_ = (1) - (j);
393          for (i_ = j; i_ <= n; i_++) {
394            w2[i_] = w3[i_ + i1_];
395          }
396          i1_ = (j - 1) - (j);
397          for (i_ = j; i_ <= n; i_++) {
398            w1[i_] = t[j - 1, i_ + i1_];
399          }
400          if (isuppera) {
401            blas.matrixvectormultiply(ref a, 0, j - 2, j - 1, n - 1, false, ref w1, j, n, 1.0, ref w2, 1, j - 1, 0.0);
402          } else {
403            blas.matrixvectormultiply(ref a, j - 1, n - 1, 0, j - 2, true, ref w1, j, n, 1.0, ref w2, 1, j - 1, 0.0);
404          }
405
406          //
407          // Form u(i)*w2 (here u(i) is i-th row of U)
408          //
409          for (i = 1; i <= n; i++) {
410            i1_ = (i) - (i - 1);
411            v = 0.0;
412            for (i_ = i - 1; i_ <= n - 1; i_++) {
413              v += t[i - 1, i_] * w2[i_ + i1_];
414            }
415            r[i - 1, j - 1] = v;
416          }
417        }
418
419        //
420        // Copy R to A
421        //
422        for (i = 0; i <= n - 1; i++) {
423          for (i_ = 0; i_ <= n - 1; i_++) {
424            a[i, i_] = r[i, i_];
425          }
426        }
427        if (problemtype == 2) {
428
429          //
430          // Invert U in T
431          //
432          matinv.rmatrixtrinverse(ref t, n, true, false, ref info, ref rep);
433          if (info <= 0) {
434            result = false;
435            return result;
436          }
437
438          //
439          // Copy U^-1 from T to R
440          //
441          isupperr = true;
442          for (i = 0; i <= n - 1; i++) {
443            for (j = 0; j <= i - 1; j++) {
444              r[i, j] = 0;
445            }
446          }
447          for (i = 0; i <= n - 1; i++) {
448            for (i_ = i; i_ <= n - 1; i_++) {
449              r[i, i_] = t[i, i_];
450            }
451          }
452        } else {
453
454          //
455          // Copy U from T to R and transpose
456          //
457          isupperr = false;
458          for (i = 0; i <= n - 1; i++) {
459            for (j = i + 1; j <= n - 1; j++) {
460              r[i, j] = 0;
461            }
462          }
463          for (i = 0; i <= n - 1; i++) {
464            for (i_ = i; i_ <= n - 1; i_++) {
465              r[i_, i] = t[i, i_];
466            }
467          }
468        }
469      }
470      return result;
471    }
472  }
473}
Note: See TracBrowser for help on using the repository browser.