Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/ALGLIB/spdrcond.cs @ 2636

Last change on this file since 2636 was 2563, checked in by gkronber, 15 years ago

Updated ALGLIB to latest version. #751 (Plugin for for data-modeling with ANN (integrated into CEDMA))

File size: 13.9 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 spdrcond
32    {
33        /*************************************************************************
34        Condition number estimate of a symmetric positive definite matrix.
35
36        The algorithm calculates a lower bound of the condition number. In this case,
37        the algorithm does not return a lower bound of the condition number, but an
38        inverse number (to avoid an overflow in case of a singular matrix).
39
40        It should be noted that 1-norm and inf-norm of 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 positive definite matrix which is given by its
46                        upper or lower triangle depending on the value of
47                        IsUpper. 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)), if matrix A is positive definite,
53           -1, if matrix A is not positive definite, and its condition number
54            could not be found by this algorithm.
55        *************************************************************************/
56        public static double spdmatrixrcond(ref double[,] a,
57            int n,
58            bool isupper)
59        {
60            double result = 0;
61            double[,] a1 = new double[0,0];
62            int i = 0;
63            int j = 0;
64            int im = 0;
65            int jm = 0;
66            double v = 0;
67            double nrm = 0;
68            int[] pivots = new int[0];
69
70            a1 = new double[n+1, n+1];
71            for(i=1; i<=n; i++)
72            {
73                if( isupper )
74                {
75                    for(j=i; j<=n; j++)
76                    {
77                        a1[i,j] = a[i-1,j-1];
78                    }
79                }
80                else
81                {
82                    for(j=1; j<=i; j++)
83                    {
84                        a1[i,j] = a[i-1,j-1];
85                    }
86                }
87            }
88            nrm = 0;
89            for(j=1; j<=n; j++)
90            {
91                v = 0;
92                for(i=1; i<=n; i++)
93                {
94                    im = i;
95                    jm = j;
96                    if( isupper & j<i )
97                    {
98                        im = j;
99                        jm = i;
100                    }
101                    if( !isupper & j>i )
102                    {
103                        im = j;
104                        jm = i;
105                    }
106                    v = v+Math.Abs(a1[im,jm]);
107                }
108                nrm = Math.Max(nrm, v);
109            }
110            if( cholesky.choleskydecomposition(ref a1, n, isupper) )
111            {
112                internalcholeskyrcond(ref a1, n, isupper, true, nrm, ref v);
113                result = v;
114            }
115            else
116            {
117                result = -1;
118            }
119            return result;
120        }
121
122
123        /*************************************************************************
124        Condition number estimate of a symmetric positive definite matrix given by
125        Cholesky decomposition.
126
127        The algorithm calculates a lower bound of the condition number. In this
128        case, the algorithm does not return a lower bound of the condition number,
129        but an inverse number (to avoid an overflow in case of a singular matrix).
130
131        It should be noted that 1-norm and inf-norm condition numbers of symmetric
132        matrices are equal, so the algorithm doesn't take into account the
133        differences between these types of norms.
134
135        Input parameters:
136            CD  - Cholesky decomposition of matrix A,
137                  output of SMatrixCholesky subroutine.
138            N   - size of matrix A.
139
140        Result: 1/LowerBound(cond(A))
141        *************************************************************************/
142        public static double spdmatrixcholeskyrcond(ref double[,] a,
143            int n,
144            bool isupper)
145        {
146            double result = 0;
147            double[,] a1 = new double[0,0];
148            int i = 0;
149            int j = 0;
150            double v = 0;
151
152            a1 = new double[n+1, n+1];
153            for(i=1; i<=n; i++)
154            {
155                if( isupper )
156                {
157                    for(j=i; j<=n; j++)
158                    {
159                        a1[i,j] = a[i-1,j-1];
160                    }
161                }
162                else
163                {
164                    for(j=1; j<=i; j++)
165                    {
166                        a1[i,j] = a[i-1,j-1];
167                    }
168                }
169            }
170            internalcholeskyrcond(ref a1, n, isupper, false, 0, ref v);
171            result = v;
172            return result;
173        }
174
175
176        public static double rcondspd(double[,] a,
177            int n,
178            bool isupper)
179        {
180            double result = 0;
181            int i = 0;
182            int j = 0;
183            int im = 0;
184            int jm = 0;
185            double v = 0;
186            double nrm = 0;
187            int[] pivots = new int[0];
188
189            a = (double[,])a.Clone();
190
191            nrm = 0;
192            for(j=1; j<=n; j++)
193            {
194                v = 0;
195                for(i=1; i<=n; i++)
196                {
197                    im = i;
198                    jm = j;
199                    if( isupper & j<i )
200                    {
201                        im = j;
202                        jm = i;
203                    }
204                    if( !isupper & j>i )
205                    {
206                        im = j;
207                        jm = i;
208                    }
209                    v = v+Math.Abs(a[im,jm]);
210                }
211                nrm = Math.Max(nrm, v);
212            }
213            if( cholesky.choleskydecomposition(ref a, n, isupper) )
214            {
215                internalcholeskyrcond(ref a, n, isupper, true, nrm, ref v);
216                result = v;
217            }
218            else
219            {
220                result = -1;
221            }
222            return result;
223        }
224
225
226        public static double rcondcholesky(ref double[,] cd,
227            int n,
228            bool isupper)
229        {
230            double result = 0;
231            double v = 0;
232
233            internalcholeskyrcond(ref cd, n, isupper, false, 0, ref v);
234            result = v;
235            return result;
236        }
237
238
239        public static void internalcholeskyrcond(ref double[,] chfrm,
240            int n,
241            bool isupper,
242            bool isnormprovided,
243            double anorm,
244            ref double rcond)
245        {
246            bool normin = new bool();
247            int i = 0;
248            int ix = 0;
249            int kase = 0;
250            double ainvnm = 0;
251            double scl = 0;
252            double scalel = 0;
253            double scaleu = 0;
254            double smlnum = 0;
255            double[] work0 = new double[0];
256            double[] work1 = new double[0];
257            double[] work2 = new double[0];
258            int[] iwork = new int[0];
259            double v = 0;
260            int i_ = 0;
261
262            System.Diagnostics.Debug.Assert(n>=0);
263           
264            //
265            // Estimate the norm of A.
266            //
267            if( !isnormprovided )
268            {
269                kase = 0;
270                anorm = 0;
271                while( true )
272                {
273                    estnorm.iterativeestimate1norm(n, ref work1, ref work0, ref iwork, ref anorm, ref kase);
274                    if( kase==0 )
275                    {
276                        break;
277                    }
278                    if( isupper )
279                    {
280                       
281                        //
282                        // Multiply by U
283                        //
284                        for(i=1; i<=n; i++)
285                        {
286                            v = 0.0;
287                            for(i_=i; i_<=n;i_++)
288                            {
289                                v += chfrm[i,i_]*work0[i_];
290                            }
291                            work0[i] = v;
292                        }
293                       
294                        //
295                        // Multiply by U'
296                        //
297                        for(i=n; i>=1; i--)
298                        {
299                            v = 0.0;
300                            for(i_=1; i_<=i;i_++)
301                            {
302                                v += chfrm[i_,i]*work0[i_];
303                            }
304                            work0[i] = v;
305                        }
306                    }
307                    else
308                    {
309                       
310                        //
311                        // Multiply by L'
312                        //
313                        for(i=1; i<=n; i++)
314                        {
315                            v = 0.0;
316                            for(i_=i; i_<=n;i_++)
317                            {
318                                v += chfrm[i_,i]*work0[i_];
319                            }
320                            work0[i] = v;
321                        }
322                       
323                        //
324                        // Multiply by L
325                        //
326                        for(i=n; i>=1; i--)
327                        {
328                            v = 0.0;
329                            for(i_=1; i_<=i;i_++)
330                            {
331                                v += chfrm[i,i_]*work0[i_];
332                            }
333                            work0[i] = v;
334                        }
335                    }
336                }
337            }
338           
339            //
340            // Quick return if possible
341            //
342            rcond = 0;
343            if( n==0 )
344            {
345                rcond = 1;
346                return;
347            }
348            if( (double)(anorm)==(double)(0) )
349            {
350                return;
351            }
352            smlnum = AP.Math.MinRealNumber;
353           
354            //
355            // Estimate the 1-norm of inv(A).
356            //
357            kase = 0;
358            normin = false;
359            while( true )
360            {
361                estnorm.iterativeestimate1norm(n, ref work1, ref work0, ref iwork, ref ainvnm, ref kase);
362                if( kase==0 )
363                {
364                    break;
365                }
366                if( isupper )
367                {
368                   
369                    //
370                    // Multiply by inv(U').
371                    //
372                    trlinsolve.safesolvetriangular(ref chfrm, n, ref work0, ref scalel, isupper, true, false, normin, ref work2);
373                    normin = true;
374                   
375                    //
376                    // Multiply by inv(U).
377                    //
378                    trlinsolve.safesolvetriangular(ref chfrm, n, ref work0, ref scaleu, isupper, false, false, normin, ref work2);
379                }
380                else
381                {
382                   
383                    //
384                    // Multiply by inv(L).
385                    //
386                    trlinsolve.safesolvetriangular(ref chfrm, n, ref work0, ref scalel, isupper, false, false, normin, ref work2);
387                    normin = true;
388                   
389                    //
390                    // Multiply by inv(L').
391                    //
392                    trlinsolve.safesolvetriangular(ref chfrm, n, ref work0, ref scaleu, isupper, true, false, normin, ref work2);
393                }
394               
395                //
396                // Multiply by 1/SCALE if doing so will not cause overflow.
397                //
398                scl = scalel*scaleu;
399                if( (double)(scl)!=(double)(1) )
400                {
401                    ix = 1;
402                    for(i=2; i<=n; i++)
403                    {
404                        if( (double)(Math.Abs(work0[i]))>(double)(Math.Abs(work0[ix])) )
405                        {
406                            ix = i;
407                        }
408                    }
409                    if( (double)(scl)<(double)(Math.Abs(work0[ix])*smlnum) | (double)(scl)==(double)(0) )
410                    {
411                        return;
412                    }
413                    for(i=1; i<=n; i++)
414                    {
415                        work0[i] = work0[i]/scl;
416                    }
417                }
418            }
419           
420            //
421            // Compute the estimate of the reciprocal condition number.
422            //
423            if( (double)(ainvnm)!=(double)(0) )
424            {
425                v = 1/ainvnm;
426                rcond = v/anorm;
427            }
428        }
429    }
430}
Note: See TracBrowser for help on using the repository browser.