Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3.2/sources/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/2.3.0/ALGLIB-2.3.0/spdgevd.cs @ 13783

Last change on this file since 13783 was 2806, checked in by gkronber, 15 years ago

Added plugin for new version of ALGLIB. #875 (Update ALGLIB sources)

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