Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/ALGLIB/spdinverse.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: 15.6 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 spdinverse
32    {
33        /*************************************************************************
34        Inversion of a symmetric positive definite matrix which is given
35        by Cholesky decomposition.
36
37        Input parameters:
38            A       -   Cholesky decomposition of the matrix to be inverted:
39                        A=U’*U or A = L*L'.
40                        Output of  CholeskyDecomposition subroutine.
41                        Array with elements [0..N-1, 0..N-1].
42            N       -   size of matrix A.
43            IsUpper –   storage format.
44                        If IsUpper = True, then matrix A is given as A = U'*U
45                        (matrix contains upper triangle).
46                        Similarly, if IsUpper = False, then A = L*L'.
47
48        Output parameters:
49            A       -   upper or lower triangle of symmetric matrix A^-1, depending
50                        on the value of IsUpper.
51
52        Result:
53            True, if the inversion succeeded.
54            False, if matrix A contains zero elements on its main diagonal.
55            Matrix A could not be inverted.
56
57        The algorithm is the modification of DPOTRI and DLAUU2 subroutines from
58        LAPACK library.
59        *************************************************************************/
60        public static bool spdmatrixcholeskyinverse(ref double[,] a,
61            int n,
62            bool isupper)
63        {
64            bool result = new bool();
65            int i = 0;
66            int j = 0;
67            int k = 0;
68            double v = 0;
69            double ajj = 0;
70            double aii = 0;
71            double[] t = new double[0];
72            double[,] a1 = new double[0,0];
73            int i_ = 0;
74
75            result = true;
76           
77            //
78            // Test the input parameters.
79            //
80            t = new double[n-1+1];
81            if( isupper )
82            {
83               
84                //
85                // Compute inverse of upper triangular matrix.
86                //
87                for(j=0; j<=n-1; j++)
88                {
89                    if( (double)(a[j,j])==(double)(0) )
90                    {
91                        result = false;
92                        return result;
93                    }
94                    a[j,j] = 1/a[j,j];
95                    ajj = -a[j,j];
96                   
97                    //
98                    // Compute elements 1:j-1 of j-th column.
99                    //
100                    for(i_=0; i_<=j-1;i_++)
101                    {
102                        t[i_] = a[i_,j];
103                    }
104                    for(i=0; i<=j-1; i++)
105                    {
106                        v = 0.0;
107                        for(i_=i; i_<=j-1;i_++)
108                        {
109                            v += a[i,i_]*t[i_];
110                        }
111                        a[i,j] = v;
112                    }
113                    for(i_=0; i_<=j-1;i_++)
114                    {
115                        a[i_,j] = ajj*a[i_,j];
116                    }
117                }
118               
119                //
120                // InvA = InvU * InvU'
121                //
122                for(i=0; i<=n-1; i++)
123                {
124                    aii = a[i,i];
125                    if( i<n-1 )
126                    {
127                        v = 0.0;
128                        for(i_=i; i_<=n-1;i_++)
129                        {
130                            v += a[i,i_]*a[i,i_];
131                        }
132                        a[i,i] = v;
133                        for(k=0; k<=i-1; k++)
134                        {
135                            v = 0.0;
136                            for(i_=i+1; i_<=n-1;i_++)
137                            {
138                                v += a[k,i_]*a[i,i_];
139                            }
140                            a[k,i] = a[k,i]*aii+v;
141                        }
142                    }
143                    else
144                    {
145                        for(i_=0; i_<=i;i_++)
146                        {
147                            a[i_,i] = aii*a[i_,i];
148                        }
149                    }
150                }
151            }
152            else
153            {
154               
155                //
156                // Compute inverse of lower triangular matrix.
157                //
158                for(j=n-1; j>=0; j--)
159                {
160                    if( (double)(a[j,j])==(double)(0) )
161                    {
162                        result = false;
163                        return result;
164                    }
165                    a[j,j] = 1/a[j,j];
166                    ajj = -a[j,j];
167                    if( j<n-1 )
168                    {
169                       
170                        //
171                        // Compute elements j+1:n of j-th column.
172                        //
173                        for(i_=j+1; i_<=n-1;i_++)
174                        {
175                            t[i_] = a[i_,j];
176                        }
177                        for(i=j+1+1; i<=n; i++)
178                        {
179                            v = 0.0;
180                            for(i_=j+1; i_<=i-1;i_++)
181                            {
182                                v += a[i-1,i_]*t[i_];
183                            }
184                            a[i-1,j] = v;
185                        }
186                        for(i_=j+1; i_<=n-1;i_++)
187                        {
188                            a[i_,j] = ajj*a[i_,j];
189                        }
190                    }
191                }
192               
193                //
194                // InvA = InvL' * InvL
195                //
196                for(i=0; i<=n-1; i++)
197                {
198                    aii = a[i,i];
199                    if( i<n-1 )
200                    {
201                        v = 0.0;
202                        for(i_=i; i_<=n-1;i_++)
203                        {
204                            v += a[i_,i]*a[i_,i];
205                        }
206                        a[i,i] = v;
207                        for(k=0; k<=i-1; k++)
208                        {
209                            v = 0.0;
210                            for(i_=i+1; i_<=n-1;i_++)
211                            {
212                                v += a[i_,k]*a[i_,i];
213                            }
214                            a[i,k] = aii*a[i,k]+v;
215                        }
216                    }
217                    else
218                    {
219                        for(i_=0; i_<=i;i_++)
220                        {
221                            a[i,i_] = aii*a[i,i_];
222                        }
223                    }
224                }
225            }
226            return result;
227        }
228
229
230        /*************************************************************************
231        Inversion of a symmetric positive definite matrix.
232
233        Given an upper or lower triangle of a symmetric positive definite matrix,
234        the algorithm generates matrix A^-1 and saves the upper or lower triangle
235        depending on the input.
236
237        Input parameters:
238            A       -   matrix to be inverted (upper or lower triangle).
239                        Array with elements [0..N-1,0..N-1].
240            N       -   size of matrix A.
241            IsUpper -   storage format.
242                        If IsUpper = True, then the upper triangle of matrix A is
243                        given, otherwise the lower triangle is given.
244
245        Output parameters:
246            A       -   inverse of matrix A.
247                        Array with elements [0..N-1,0..N-1].
248                        If IsUpper = True, then the upper triangle of matrix A^-1
249                        is used, and the elements below the main diagonal are not
250                        used nor changed. The same applies if IsUpper = False.
251
252        Result:
253            True, if the matrix is positive definite.
254            False, if the matrix is not positive definite (and it could not be
255            inverted by this algorithm).
256        *************************************************************************/
257        public static bool spdmatrixinverse(ref double[,] a,
258            int n,
259            bool isupper)
260        {
261            bool result = new bool();
262
263            result = false;
264            if( cholesky.spdmatrixcholesky(ref a, n, isupper) )
265            {
266                if( spdmatrixcholeskyinverse(ref a, n, isupper) )
267                {
268                    result = true;
269                }
270            }
271            return result;
272        }
273
274
275        public static bool inversecholesky(ref double[,] a,
276            int n,
277            bool isupper)
278        {
279            bool result = new bool();
280            int i = 0;
281            int j = 0;
282            int k = 0;
283            int nmj = 0;
284            int jm1 = 0;
285            int jp1 = 0;
286            int ip1 = 0;
287            double v = 0;
288            double ajj = 0;
289            double aii = 0;
290            double[] t = new double[0];
291            double[] d = new double[0];
292            int i_ = 0;
293
294            result = true;
295           
296            //
297            // Test the input parameters.
298            //
299            t = new double[n+1];
300            d = new double[n+1];
301            if( isupper )
302            {
303               
304                //
305                // Compute inverse of upper triangular matrix.
306                //
307                for(j=1; j<=n; j++)
308                {
309                    if( (double)(a[j,j])==(double)(0) )
310                    {
311                        result = false;
312                        return result;
313                    }
314                    jm1 = j-1;
315                    a[j,j] = 1/a[j,j];
316                    ajj = -a[j,j];
317                   
318                    //
319                    // Compute elements 1:j-1 of j-th column.
320                    //
321                    for(i_=1; i_<=jm1;i_++)
322                    {
323                        t[i_] = a[i_,j];
324                    }
325                    for(i=1; i<=j-1; i++)
326                    {
327                        v = 0.0;
328                        for(i_=i; i_<=jm1;i_++)
329                        {
330                            v += a[i,i_]*a[i_,j];
331                        }
332                        a[i,j] = v;
333                    }
334                    for(i_=1; i_<=jm1;i_++)
335                    {
336                        a[i_,j] = ajj*a[i_,j];
337                    }
338                }
339               
340                //
341                // InvA = InvU * InvU'
342                //
343                for(i=1; i<=n; i++)
344                {
345                    aii = a[i,i];
346                    if( i<n )
347                    {
348                        v = 0.0;
349                        for(i_=i; i_<=n;i_++)
350                        {
351                            v += a[i,i_]*a[i,i_];
352                        }
353                        a[i,i] = v;
354                        ip1 = i+1;
355                        for(k=1; k<=i-1; k++)
356                        {
357                            v = 0.0;
358                            for(i_=ip1; i_<=n;i_++)
359                            {
360                                v += a[k,i_]*a[i,i_];
361                            }
362                            a[k,i] = a[k,i]*aii+v;
363                        }
364                    }
365                    else
366                    {
367                        for(i_=1; i_<=i;i_++)
368                        {
369                            a[i_,i] = aii*a[i_,i];
370                        }
371                    }
372                }
373            }
374            else
375            {
376               
377                //
378                // Compute inverse of lower triangular matrix.
379                //
380                for(j=n; j>=1; j--)
381                {
382                    if( (double)(a[j,j])==(double)(0) )
383                    {
384                        result = false;
385                        return result;
386                    }
387                    a[j,j] = 1/a[j,j];
388                    ajj = -a[j,j];
389                    if( j<n )
390                    {
391                       
392                        //
393                        // Compute elements j+1:n of j-th column.
394                        //
395                        nmj = n-j;
396                        jp1 = j+1;
397                        for(i_=jp1; i_<=n;i_++)
398                        {
399                            t[i_] = a[i_,j];
400                        }
401                        for(i=j+1; i<=n; i++)
402                        {
403                            v = 0.0;
404                            for(i_=jp1; i_<=i;i_++)
405                            {
406                                v += a[i,i_]*t[i_];
407                            }
408                            a[i,j] = v;
409                        }
410                        for(i_=jp1; i_<=n;i_++)
411                        {
412                            a[i_,j] = ajj*a[i_,j];
413                        }
414                    }
415                }
416               
417                //
418                // InvA = InvL' * InvL
419                //
420                for(i=1; i<=n; i++)
421                {
422                    aii = a[i,i];
423                    if( i<n )
424                    {
425                        v = 0.0;
426                        for(i_=i; i_<=n;i_++)
427                        {
428                            v += a[i_,i]*a[i_,i];
429                        }
430                        a[i,i] = v;
431                        ip1 = i+1;
432                        for(k=1; k<=i-1; k++)
433                        {
434                            v = 0.0;
435                            for(i_=ip1; i_<=n;i_++)
436                            {
437                                v += a[i_,k]*a[i_,i];
438                            }
439                            a[i,k] = aii*a[i,k]+v;
440                        }
441                    }
442                    else
443                    {
444                        for(i_=1; i_<=i;i_++)
445                        {
446                            a[i,i_] = aii*a[i,i_];
447                        }
448                    }
449                }
450            }
451            return result;
452        }
453
454
455        public static bool inversesymmetricpositivedefinite(ref double[,] a,
456            int n,
457            bool isupper)
458        {
459            bool result = new bool();
460
461            result = false;
462            if( cholesky.choleskydecomposition(ref a, n, isupper) )
463            {
464                if( inversecholesky(ref a, n, isupper) )
465                {
466                    result = true;
467                }
468            }
469            return result;
470        }
471    }
472}
Note: See TracBrowser for help on using the repository browser.