Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.ALGLIB/2.3.0/ALGLIB-2.3.0/spdinverse.cs @ 2806

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

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

File size: 9.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( trfac.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}
Note: See TracBrowser for help on using the repository browser.