Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/2.3.0/ALGLIB-2.3.0/srcond.cs @ 3021

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

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

File size: 22.2 KB
Line 
1/*************************************************************************
2Copyright (c) 1992-2007 The University of Tennessee.  All rights reserved.
3
4Contributors:
5    * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
6      pseudocode.
7
8See subroutines comments for additional copyrights.
9
10>>> SOURCE LICENSE >>>
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation (www.fsf.org); either version 2 of the
14License, or (at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20
21A copy of the GNU General Public License is available at
22http://www.fsf.org/licensing/licenses
23
24>>> END OF LICENSE >>>
25*************************************************************************/
26
27using System;
28
29namespace alglib
30{
31    public class srcond
32    {
33        /*************************************************************************
34        Condition number estimate of a symmetric matrix
35
36        The algorithm calculates a lower bound of the condition number. In this
37        case, the algorithm does not return a lower bound of the condition number,
38        but an inverse number (to avoid an overflow in case of a singular matrix).
39
40        It should be noted that 1-norm and inf-norm condition numbers of symmetric
41        matrices are equal, so the algorithm doesn't take into account the
42        differences between these types of norms.
43
44        Input parameters:
45            A       -   symmetric definite matrix which is given by its upper or
46                        lower triangle depending on IsUpper.
47                        Array with elements [0..N-1, 0..N-1].
48            N       -   size of matrix A.
49            IsUpper -   storage format.
50
51        Result:
52            1/LowerBound(cond(A))
53        *************************************************************************/
54        public static double smatrixrcond(ref double[,] a,
55            int n,
56            bool isupper)
57        {
58            double result = 0;
59            int i = 0;
60            int j = 0;
61            double[,] a1 = new double[0,0];
62
63            a1 = new double[n+1, n+1];
64            for(i=1; i<=n; i++)
65            {
66                if( isupper )
67                {
68                    for(j=i; j<=n; j++)
69                    {
70                        a1[i,j] = a[i-1,j-1];
71                    }
72                }
73                else
74                {
75                    for(j=1; j<=i; j++)
76                    {
77                        a1[i,j] = a[i-1,j-1];
78                    }
79                }
80            }
81            result = rcondsymmetric(a1, n, isupper);
82            return result;
83        }
84
85
86        /*************************************************************************
87        Condition number estimate of a matrix given by LDLT-decomposition
88
89        The algorithm calculates a lower bound of the condition number. In this
90        case, the algorithm does not return a lower bound of the condition number,
91        but an inverse number (to avoid an overflow in case of a singular matrix).
92
93        It should be noted that 1-norm and inf-norm condition numbers of symmetric
94        matrices are equal, so the algorithm doesn't take into account the
95        differences between these types of norms.
96
97        Input parameters:
98            L       -   LDLT-decomposition of matrix A given by the upper or lower
99                        triangle depending on IsUpper.
100                        Output of SMatrixLDLT subroutine.
101            Pivots  -   table of permutations which were made during LDLT-decomposition,
102                        Output of SMatrixLDLT subroutine.
103            N       -   size of matrix A.
104            IsUpper -   storage format.
105
106        Result:
107            1/LowerBound(cond(A))
108        *************************************************************************/
109        public static double smatrixldltrcond(ref double[,] l,
110            ref int[] pivots,
111            int n,
112            bool isupper)
113        {
114            double result = 0;
115            int i = 0;
116            int j = 0;
117            double[,] l1 = new double[0,0];
118            int[] p1 = new int[0];
119
120            l1 = new double[n+1, n+1];
121            for(i=1; i<=n; i++)
122            {
123                if( isupper )
124                {
125                    for(j=i; j<=n; j++)
126                    {
127                        l1[i,j] = l[i-1,j-1];
128                    }
129                }
130                else
131                {
132                    for(j=1; j<=i; j++)
133                    {
134                        l1[i,j] = l[i-1,j-1];
135                    }
136                }
137            }
138            p1 = new int[n+1];
139            for(i=1; i<=n; i++)
140            {
141                if( pivots[i-1]>=0 )
142                {
143                    p1[i] = pivots[i-1]+1;
144                }
145                else
146                {
147                    p1[i] = -(pivots[i-1]+n+1);
148                }
149            }
150            result = rcondldlt(ref l1, ref p1, n, isupper);
151            return result;
152        }
153
154
155        public static double rcondsymmetric(double[,] a,
156            int n,
157            bool isupper)
158        {
159            double result = 0;
160            int i = 0;
161            int j = 0;
162            int im = 0;
163            int jm = 0;
164            double v = 0;
165            double nrm = 0;
166            int[] pivots = new int[0];
167
168            a = (double[,])a.Clone();
169
170            nrm = 0;
171            for(j=1; j<=n; j++)
172            {
173                v = 0;
174                for(i=1; i<=n; i++)
175                {
176                    im = i;
177                    jm = j;
178                    if( isupper & j<i )
179                    {
180                        im = j;
181                        jm = i;
182                    }
183                    if( !isupper & j>i )
184                    {
185                        im = j;
186                        jm = i;
187                    }
188                    v = v+Math.Abs(a[im,jm]);
189                }
190                nrm = Math.Max(nrm, v);
191            }
192            ldlt.ldltdecomposition(ref a, n, isupper, ref pivots);
193            internalldltrcond(ref a, ref pivots, n, isupper, true, nrm, ref v);
194            result = v;
195            return result;
196        }
197
198
199        public static double rcondldlt(ref double[,] l,
200            ref int[] pivots,
201            int n,
202            bool isupper)
203        {
204            double result = 0;
205            double v = 0;
206
207            internalldltrcond(ref l, ref pivots, n, isupper, false, 0, ref v);
208            result = v;
209            return result;
210        }
211
212
213        public static void internalldltrcond(ref double[,] l,
214            ref int[] pivots,
215            int n,
216            bool isupper,
217            bool isnormprovided,
218            double anorm,
219            ref double rcond)
220        {
221            int i = 0;
222            int kase = 0;
223            int k = 0;
224            int km1 = 0;
225            int km2 = 0;
226            int kp1 = 0;
227            int kp2 = 0;
228            double ainvnm = 0;
229            double[] work0 = new double[0];
230            double[] work1 = new double[0];
231            double[] work2 = new double[0];
232            int[] iwork = new int[0];
233            double v = 0;
234            int i_ = 0;
235
236            System.Diagnostics.Debug.Assert(n>=0);
237           
238            //
239            // Check that the diagonal matrix D is nonsingular.
240            //
241            rcond = 0;
242            if( isupper )
243            {
244                for(i=n; i>=1; i--)
245                {
246                    if( pivots[i]>0 & (double)(l[i,i])==(double)(0) )
247                    {
248                        return;
249                    }
250                }
251            }
252            else
253            {
254                for(i=1; i<=n; i++)
255                {
256                    if( pivots[i]>0 & (double)(l[i,i])==(double)(0) )
257                    {
258                        return;
259                    }
260                }
261            }
262           
263            //
264            // Estimate the norm of A.
265            //
266            if( !isnormprovided )
267            {
268                kase = 0;
269                anorm = 0;
270                while( true )
271                {
272                    estnorm.iterativeestimate1norm(n, ref work1, ref work0, ref iwork, ref anorm, ref kase);
273                    if( kase==0 )
274                    {
275                        break;
276                    }
277                    if( isupper )
278                    {
279                       
280                        //
281                        // Multiply by U'
282                        //
283                        k = n;
284                        while( k>=1 )
285                        {
286                            if( pivots[k]>0 )
287                            {
288                               
289                                //
290                                // P(k)
291                                //
292                                v = work0[k];
293                                work0[k] = work0[pivots[k]];
294                                work0[pivots[k]] = v;
295                               
296                                //
297                                // U(k)
298                                //
299                                km1 = k-1;
300                                v = 0.0;
301                                for(i_=1; i_<=km1;i_++)
302                                {
303                                    v += work0[i_]*l[i_,k];
304                                }
305                                work0[k] = work0[k]+v;
306                               
307                                //
308                                // Next k
309                                //
310                                k = k-1;
311                            }
312                            else
313                            {
314                               
315                                //
316                                // P(k)
317                                //
318                                v = work0[k-1];
319                                work0[k-1] = work0[-pivots[k-1]];
320                                work0[-pivots[k-1]] = v;
321                               
322                                //
323                                // U(k)
324                                //
325                                km1 = k-1;
326                                km2 = k-2;
327                                v = 0.0;
328                                for(i_=1; i_<=km2;i_++)
329                                {
330                                    v += work0[i_]*l[i_,km1];
331                                }
332                                work0[km1] = work0[km1]+v;
333                                v = 0.0;
334                                for(i_=1; i_<=km2;i_++)
335                                {
336                                    v += work0[i_]*l[i_,k];
337                                }
338                                work0[k] = work0[k]+v;
339                               
340                                //
341                                // Next k
342                                //
343                                k = k-2;
344                            }
345                        }
346                       
347                        //
348                        // Multiply by D
349                        //
350                        k = n;
351                        while( k>=1 )
352                        {
353                            if( pivots[k]>0 )
354                            {
355                                work0[k] = work0[k]*l[k,k];
356                                k = k-1;
357                            }
358                            else
359                            {
360                                v = work0[k-1];
361                                work0[k-1] = l[k-1,k-1]*work0[k-1]+l[k-1,k]*work0[k];
362                                work0[k] = l[k-1,k]*v+l[k,k]*work0[k];
363                                k = k-2;
364                            }
365                        }
366                       
367                        //
368                        // Multiply by U
369                        //
370                        k = 1;
371                        while( k<=n )
372                        {
373                            if( pivots[k]>0 )
374                            {
375                               
376                                //
377                                // U(k)
378                                //
379                                km1 = k-1;
380                                v = work0[k];
381                                for(i_=1; i_<=km1;i_++)
382                                {
383                                    work0[i_] = work0[i_] + v*l[i_,k];
384                                }
385                               
386                                //
387                                // P(k)
388                                //
389                                v = work0[k];
390                                work0[k] = work0[pivots[k]];
391                                work0[pivots[k]] = v;
392                               
393                                //
394                                // Next k
395                                //
396                                k = k+1;
397                            }
398                            else
399                            {
400                               
401                                //
402                                // U(k)
403                                //
404                                km1 = k-1;
405                                kp1 = k+1;
406                                v = work0[k];
407                                for(i_=1; i_<=km1;i_++)
408                                {
409                                    work0[i_] = work0[i_] + v*l[i_,k];
410                                }
411                                v = work0[kp1];
412                                for(i_=1; i_<=km1;i_++)
413                                {
414                                    work0[i_] = work0[i_] + v*l[i_,kp1];
415                                }
416                               
417                                //
418                                // P(k)
419                                //
420                                v = work0[k];
421                                work0[k] = work0[-pivots[k]];
422                                work0[-pivots[k]] = v;
423                               
424                                //
425                                // Next k
426                                //
427                                k = k+2;
428                            }
429                        }
430                    }
431                    else
432                    {
433                       
434                        //
435                        // Multiply by L'
436                        //
437                        k = 1;
438                        while( k<=n )
439                        {
440                            if( pivots[k]>0 )
441                            {
442                               
443                                //
444                                // P(k)
445                                //
446                                v = work0[k];
447                                work0[k] = work0[pivots[k]];
448                                work0[pivots[k]] = v;
449                               
450                                //
451                                // L(k)
452                                //
453                                kp1 = k+1;
454                                v = 0.0;
455                                for(i_=kp1; i_<=n;i_++)
456                                {
457                                    v += work0[i_]*l[i_,k];
458                                }
459                                work0[k] = work0[k]+v;
460                               
461                                //
462                                // Next k
463                                //
464                                k = k+1;
465                            }
466                            else
467                            {
468                               
469                                //
470                                // P(k)
471                                //
472                                v = work0[k+1];
473                                work0[k+1] = work0[-pivots[k+1]];
474                                work0[-pivots[k+1]] = v;
475                               
476                                //
477                                // L(k)
478                                //
479                                kp1 = k+1;
480                                kp2 = k+2;
481                                v = 0.0;
482                                for(i_=kp2; i_<=n;i_++)
483                                {
484                                    v += work0[i_]*l[i_,k];
485                                }
486                                work0[k] = work0[k]+v;
487                                v = 0.0;
488                                for(i_=kp2; i_<=n;i_++)
489                                {
490                                    v += work0[i_]*l[i_,kp1];
491                                }
492                                work0[kp1] = work0[kp1]+v;
493                               
494                                //
495                                // Next k
496                                //
497                                k = k+2;
498                            }
499                        }
500                       
501                        //
502                        // Multiply by D
503                        //
504                        k = n;
505                        while( k>=1 )
506                        {
507                            if( pivots[k]>0 )
508                            {
509                                work0[k] = work0[k]*l[k,k];
510                                k = k-1;
511                            }
512                            else
513                            {
514                                v = work0[k-1];
515                                work0[k-1] = l[k-1,k-1]*work0[k-1]+l[k,k-1]*work0[k];
516                                work0[k] = l[k,k-1]*v+l[k,k]*work0[k];
517                                k = k-2;
518                            }
519                        }
520                       
521                        //
522                        // Multiply by L
523                        //
524                        k = n;
525                        while( k>=1 )
526                        {
527                            if( pivots[k]>0 )
528                            {
529                               
530                                //
531                                // L(k)
532                                //
533                                kp1 = k+1;
534                                v = work0[k];
535                                for(i_=kp1; i_<=n;i_++)
536                                {
537                                    work0[i_] = work0[i_] + v*l[i_,k];
538                                }
539                               
540                                //
541                                // P(k)
542                                //
543                                v = work0[k];
544                                work0[k] = work0[pivots[k]];
545                                work0[pivots[k]] = v;
546                               
547                                //
548                                // Next k
549                                //
550                                k = k-1;
551                            }
552                            else
553                            {
554                               
555                                //
556                                // L(k)
557                                //
558                                kp1 = k+1;
559                                km1 = k-1;
560                                v = work0[k];
561                                for(i_=kp1; i_<=n;i_++)
562                                {
563                                    work0[i_] = work0[i_] + v*l[i_,k];
564                                }
565                                v = work0[km1];
566                                for(i_=kp1; i_<=n;i_++)
567                                {
568                                    work0[i_] = work0[i_] + v*l[i_,km1];
569                                }
570                               
571                                //
572                                // P(k)
573                                //
574                                v = work0[k];
575                                work0[k] = work0[-pivots[k]];
576                                work0[-pivots[k]] = v;
577                               
578                                //
579                                // Next k
580                                //
581                                k = k-2;
582                            }
583                        }
584                    }
585                }
586            }
587           
588            //
589            // Quick return if possible
590            //
591            rcond = 0;
592            if( n==0 )
593            {
594                rcond = 1;
595                return;
596            }
597            if( (double)(anorm)==(double)(0) )
598            {
599                return;
600            }
601           
602            //
603            // Estimate the 1-norm of inv(A).
604            //
605            kase = 0;
606            while( true )
607            {
608                estnorm.iterativeestimate1norm(n, ref work1, ref work0, ref iwork, ref ainvnm, ref kase);
609                if( kase==0 )
610                {
611                    break;
612                }
613                ssolve.solvesystemldlt(ref l, ref pivots, work0, n, isupper, ref work2);
614                for(i_=1; i_<=n;i_++)
615                {
616                    work0[i_] = work2[i_];
617                }
618            }
619           
620            //
621            // Compute the estimate of the reciprocal condition number.
622            //
623            if( (double)(ainvnm)!=(double)(0) )
624            {
625                v = 1/ainvnm;
626                rcond = v/anorm;
627            }
628        }
629    }
630}
Note: See TracBrowser for help on using the repository browser.