Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/pinv.cs @ 11194

Last change on this file since 11194 was 9102, checked in by gkronber, 12 years ago

#1967: ILNumerics source for experimentation

File size: 22.8 KB
Line 
1///
2///    This file is part of ILNumerics Community Edition.
3///
4///    ILNumerics Community Edition - high performance computing for applications.
5///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
6///
7///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
8///    it under the terms of the GNU General Public License version 3 as published by
9///    the Free Software Foundation.
10///
11///    ILNumerics Community Edition is distributed in the hope that it will be useful,
12///    but WITHOUT ANY WARRANTY; without even the implied warranty of
13///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14///    GNU General Public License for more details.
15///
16///    You should have received a copy of the GNU General Public License
17///    along with ILNumerics Community Edition. See the file License.txt in the root
18///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
19///
20///    In addition this software uses the following components and/or licenses:
21///
22///    =================================================================================
23///    The Open Toolkit Library License
24///   
25///    Copyright (c) 2006 - 2009 the Open Toolkit library.
26///   
27///    Permission is hereby granted, free of charge, to any person obtaining a copy
28///    of this software and associated documentation files (the "Software"), to deal
29///    in the Software without restriction, including without limitation the rights to
30///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
31///    the Software, and to permit persons to whom the Software is furnished to do
32///    so, subject to the following conditions:
33///
34///    The above copyright notice and this permission notice shall be included in all
35///    copies or substantial portions of the Software.
36///
37///    =================================================================================
38///   
39
40using System;
41using System.Collections.Generic;
42using System.Text;
43using ILNumerics.Storage;
44using ILNumerics.Misc;
45using ILNumerics.Exceptions;
46using ILNumerics;
47
48namespace ILNumerics  {
49
50    public partial class ILMath {
51
52
53
54
55        /// <summary>
56        /// Pseudo - inverse of input argument M
57        /// </summary>
58        /// <param name="M">Input matrix M</param>
59        /// <returns>Pseudo inverse of input matrix M</returns>
60        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
61        /// of input matrix M. The return value will be of the same size as
62        /// the transposed of M. it will satisfy the following conditions:
63        /// <list type="bullet">
64        /// <item>M * pinv(M) * M  = M </item>
65        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
66        /// <item>pinv(M) * M is hermitian</item>
67        /// <item>M * pinv(M) is hermitian</item>
68        /// </list>
69        /// pinv uses Lapack's function svd internally. Any singular values less than
70        /// the default tolerance will be set to zero. As tolerance the following equation is used: \\
71        /// tol = length(M) * norm(M) * Double.epsilon \\
72        /// with
73        /// <list type="bullet">
74        /// <item>length(M) - the longest dimension of M</item>
75        /// <item>norm(M) being the largest singular value of M, </item>
76        /// <item>Double.epsilon - the smallest number greater than zero</item>
77        /// </list>
78        /// You may use a overloaded function to define an alternative tolerance.
79        /// </remarks>
80        /// <seealso cref="ILNumerics.ILMath.pinv(ILInArray{double}, double)"/>
81        public static ILRetArray< double > pinv(ILInArray< double > M) {
82            return pinv(M, -1);
83        }
84        /// <summary>
85        /// Pseudo inverse of input matrix M
86        /// </summary>
87        /// <param name="M">Input matrix M</param>
88        /// <param name="tolerance">Tolerance, see remarks (default = -1; use default tolerance)</param>
89        /// <returns>Pseudo inverse of M</returns>
90        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
91        /// of input matrix M. The return value will be of the same size as
92        /// the transposed of M. it will satisfy the following conditions:
93        /// <list type="bullet">
94        /// <item>M * pinv(M) * M  = M </item>
95        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
96        /// <item>pinv(M) * M is hermitian</item>
97        /// <item>M * pinv(M) is hermitian</item>
98        /// </list>
99        /// pinv uses LAPACK's function svd internally. Any singular values less than
100        /// tolerance will be set to zero. If tolerance is less than zero, the following equation
101        /// is used as default: \\
102        /// tol = length(M) * norm(M) * Double.epsilon \\
103        /// with
104        /// <list type="bullet">
105        /// <item>length(M) - the longest dimension of M</item>
106        /// <item>norm(M) being the largest singular value of M, </item>
107        /// <item>Double.epsilon - the smallest constructable double precision number greater than zero</item>
108        /// </list>
109        /// </remarks>
110        public static ILRetArray< double > pinv(ILInArray< double > M,  double tolerance) {
111            using (ILScope.Enter(M)) {
112                // let svd check the dimensions!
113                //if (M.Dimensions.NumberOfDimensions > 2)
114                //   throw new ILDimensionMismatchException("pinv: ...");
115
116                // in order to use the cheap packed version of svd, the matrix must be m x n with m > n!
117                if (M.Size[0] < M.Size[1]) {
118                   
119                    return pinv(M.T, tolerance).T;
120                }
121                if (M.IsScalar)
122                    return  1.0 / M;
123
124                ILArray< double> U = empty< double>(ILSize.Empty00);
125                ILArray< double> V = empty< double>(ILSize.Empty00);
126                ILArray< double> S = svd(M, U, V, true, false);
127
128                int m = M.Size[0];
129                int n = M.Size[1];
130
131                ILArray< double> s;
132                switch (m) {
133                    case 0:
134                        s = zeros< double>(ILSize.Scalar1_1);
135                        break;
136                    case 1:
137                        s = S[0];
138                        break;
139                    default:
140                        s = diag< double>(S);
141                        break;
142                }
143                if (tolerance < 0) {
144                    tolerance = ( double)(M.Size.Longest * max(s).GetValue(0) *  MachineParameterDouble.eps);
145                }
146                // sum vector elements: s is dense vector returned from svd
147                int count = (int)sum(s > ( double)tolerance);
148
149                ILArray< double> Ret = empty< double>(ILSize.Empty00);
150                if (count == 0)
151                    S.a = zeros< double>(new ILSize(n, m));
152                else {
153                    ILArray< double> OneVec = array< double>( 1.0, count, 1);
154
155                    S.a = diag(divide(OneVec, s[r(0,count - 1)]));
156                   
157                    U.a = U[full,r(0,count-1)].T;
158                   
159                    Ret.a = multiply(multiply(V[full,r(0,count - 1)], S), U);
160                }
161                return Ret;
162            }
163        }
164
165#region HYCALPER AUTO GENERATED CODE
166
167
168
169        /// <summary>
170        /// Pseudo - inverse of input argument M
171        /// </summary>
172        /// <param name="M">Input matrix M</param>
173        /// <returns>Pseudo inverse of input matrix M</returns>
174        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
175        /// of input matrix M. The return value will be of the same size as
176        /// the transposed of M. it will satisfy the following conditions:
177        /// <list type="bullet">
178        /// <item>M * pinv(M) * M  = M </item>
179        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
180        /// <item>pinv(M) * M is hermitian</item>
181        /// <item>M * pinv(M) is hermitian</item>
182        /// </list>
183        /// pinv uses Lapack's function svd internally. Any singular values less than
184        /// the default tolerance will be set to zero. As tolerance the following equation is used: \\
185        /// tol = length(M) * norm(M) * Double.epsilon \\
186        /// with
187        /// <list type="bullet">
188        /// <item>length(M) - the longest dimension of M</item>
189        /// <item>norm(M) being the largest singular value of M, </item>
190        /// <item>Double.epsilon - the smallest number greater than zero</item>
191        /// </list>
192        /// You may use a overloaded function to define an alternative tolerance.
193        /// </remarks>
194        /// <seealso cref="ILNumerics.ILMath.pinv(ILInArray{double}, double)"/>
195        public static ILRetArray< float > pinv(ILInArray< float > M) {
196            return pinv(M, -1);
197        }
198        /// <summary>
199        /// Pseudo inverse of input matrix M
200        /// </summary>
201        /// <param name="M">Input matrix M</param>
202        /// <param name="tolerance">Tolerance, see remarks (default = -1; use default tolerance)</param>
203        /// <returns>Pseudo inverse of M</returns>
204        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
205        /// of input matrix M. The return value will be of the same size as
206        /// the transposed of M. it will satisfy the following conditions:
207        /// <list type="bullet">
208        /// <item>M * pinv(M) * M  = M </item>
209        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
210        /// <item>pinv(M) * M is hermitian</item>
211        /// <item>M * pinv(M) is hermitian</item>
212        /// </list>
213        /// pinv uses LAPACK's function svd internally. Any singular values less than
214        /// tolerance will be set to zero. If tolerance is less than zero, the following equation
215        /// is used as default: \\
216        /// tol = length(M) * norm(M) * Double.epsilon \\
217        /// with
218        /// <list type="bullet">
219        /// <item>length(M) - the longest dimension of M</item>
220        /// <item>norm(M) being the largest singular value of M, </item>
221        /// <item>Double.epsilon - the smallest constructable double precision number greater than zero</item>
222        /// </list>
223        /// </remarks>
224        public static ILRetArray< float > pinv(ILInArray< float > M,  float tolerance) {
225            using (ILScope.Enter(M)) {
226                // let svd check the dimensions!
227                //if (M.Dimensions.NumberOfDimensions > 2)
228                //   throw new ILDimensionMismatchException("pinv: ...");
229
230                // in order to use the cheap packed version of svd, the matrix must be m x n with m > n!
231                if (M.Size[0] < M.Size[1]) {
232                    return pinv(M.T, tolerance).T;
233                }
234                if (M.IsScalar)
235                    return  1 / M;
236
237                ILArray< float> U = empty< float>(ILSize.Empty00);
238                ILArray< float> V = empty< float>(ILSize.Empty00);
239                ILArray< float> S = svd(M, U, V, true, false);
240
241                int m = M.Size[0];
242                int n = M.Size[1];
243
244                ILArray< float> s;
245                switch (m) {
246                    case 0:
247                        s = zeros< float>(ILSize.Scalar1_1);
248                        break;
249                    case 1:
250                        s = S[0];
251                        break;
252                    default:
253                        s = diag< float>(S);
254                        break;
255                }
256                if (tolerance < 0) {
257                    tolerance = ( float)(M.Size.Longest * max(s).GetValue(0) *  ILMath.MachineParameterSingle.eps);
258                }
259                // sum vector elements: s is dense vector returned from svd
260                int count = (int)sum(s > ( float)tolerance);
261
262                ILArray< float> Ret = empty< float>(ILSize.Empty00);
263                if (count == 0)
264                    S.a = zeros< float>(new ILSize(n, m));
265                else {
266                    ILArray< float> OneVec = array< float>( 1.0f, count, 1);
267
268                    S.a = diag(divide(OneVec, s[r(0,count - 1)]));
269                    U = U[":;0:" + (count - 1)].T;
270                    Ret = multiply(multiply(V[":;0:" + (count - 1)], S), U);
271                }
272                return Ret;
273            }
274        }
275
276
277        /// <summary>
278        /// Pseudo - inverse of input argument M
279        /// </summary>
280        /// <param name="M">Input matrix M</param>
281        /// <returns>Pseudo inverse of input matrix M</returns>
282        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
283        /// of input matrix M. The return value will be of the same size as
284        /// the transposed of M. it will satisfy the following conditions:
285        /// <list type="bullet">
286        /// <item>M * pinv(M) * M  = M </item>
287        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
288        /// <item>pinv(M) * M is hermitian</item>
289        /// <item>M * pinv(M) is hermitian</item>
290        /// </list>
291        /// pinv uses Lapack's function svd internally. Any singular values less than
292        /// the default tolerance will be set to zero. As tolerance the following equation is used: \\
293        /// tol = length(M) * norm(M) * Double.epsilon \\
294        /// with
295        /// <list type="bullet">
296        /// <item>length(M) - the longest dimension of M</item>
297        /// <item>norm(M) being the largest singular value of M, </item>
298        /// <item>Double.epsilon - the smallest number greater than zero</item>
299        /// </list>
300        /// You may use a overloaded function to define an alternative tolerance.
301        /// </remarks>
302        /// <seealso cref="ILNumerics.ILMath.pinv(ILInArray{double}, double)"/>
303        public static ILRetArray< fcomplex > pinv(ILInArray< fcomplex > M) {
304            return pinv(M, -1);
305        }
306        /// <summary>
307        /// Pseudo inverse of input matrix M
308        /// </summary>
309        /// <param name="M">Input matrix M</param>
310        /// <param name="tolerance">Tolerance, see remarks (default = -1; use default tolerance)</param>
311        /// <returns>Pseudo inverse of M</returns>
312        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
313        /// of input matrix M. The return value will be of the same size as
314        /// the transposed of M. it will satisfy the following conditions:
315        /// <list type="bullet">
316        /// <item>M * pinv(M) * M  = M </item>
317        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
318        /// <item>pinv(M) * M is hermitian</item>
319        /// <item>M * pinv(M) is hermitian</item>
320        /// </list>
321        /// pinv uses LAPACK's function svd internally. Any singular values less than
322        /// tolerance will be set to zero. If tolerance is less than zero, the following equation
323        /// is used as default: \\
324        /// tol = length(M) * norm(M) * Double.epsilon \\
325        /// with
326        /// <list type="bullet">
327        /// <item>length(M) - the longest dimension of M</item>
328        /// <item>norm(M) being the largest singular value of M, </item>
329        /// <item>Double.epsilon - the smallest constructable double precision number greater than zero</item>
330        /// </list>
331        /// </remarks>
332        public static ILRetArray< fcomplex > pinv(ILInArray< fcomplex > M,  fcomplex tolerance) {
333            using (ILScope.Enter(M)) {
334                // let svd check the dimensions!
335                //if (M.Dimensions.NumberOfDimensions > 2)
336                //   throw new ILDimensionMismatchException("pinv: ...");
337
338                // in order to use the cheap packed version of svd, the matrix must be m x n with m > n!
339                if (M.Size[0] < M.Size[1]) {
340                    return conj(pinv(conj(M.T), tolerance)).T;
341                }
342                if (M.IsScalar)
343                    return  new fcomplex(1f,0f) / M;
344
345                ILArray< fcomplex> U = empty< fcomplex>(ILSize.Empty00);
346                ILArray< fcomplex> V = empty< fcomplex>(ILSize.Empty00);
347                ILArray< float> S = svd(M, U, V, true, false);
348
349                int m = M.Size[0];
350                int n = M.Size[1];
351
352                ILArray< float> s;
353                switch (m) {
354                    case 0:
355                        s = zeros< float>(ILSize.Scalar1_1);
356                        break;
357                    case 1:
358                        s = S[0];
359                        break;
360                    default:
361                        s = diag< float>(S);
362                        break;
363                }
364                if (tolerance < 0) {
365                    tolerance = ( fcomplex)(M.Size.Longest * max(s).GetValue(0) *  ILMath.MachineParameterSingle.eps);
366                }
367                // sum vector elements: s is dense vector returned from svd
368                int count = (int)sum(s > ( float)tolerance);
369
370                ILArray< fcomplex> Ret = empty< fcomplex>(ILSize.Empty00);
371                if (count == 0)
372                    S.a = zeros< float>(new ILSize(n, m));
373                else {
374                    ILArray< float> OneVec = array< float>( 1.0f, count, 1);
375
376                    S.a = diag(divide(OneVec, s[r(0,count - 1)]));
377                    U = conj(U[":;0:" + (count - 1)].T);
378                    Ret = multiply(multiply(V[":;0:" + (count - 1)], real2fcomplex(S)), U);
379                }
380                return Ret;
381            }
382        }
383
384
385        /// <summary>
386        /// Pseudo - inverse of input argument M
387        /// </summary>
388        /// <param name="M">Input matrix M</param>
389        /// <returns>Pseudo inverse of input matrix M</returns>
390        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
391        /// of input matrix M. The return value will be of the same size as
392        /// the transposed of M. it will satisfy the following conditions:
393        /// <list type="bullet">
394        /// <item>M * pinv(M) * M  = M </item>
395        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
396        /// <item>pinv(M) * M is hermitian</item>
397        /// <item>M * pinv(M) is hermitian</item>
398        /// </list>
399        /// pinv uses Lapack's function svd internally. Any singular values less than
400        /// the default tolerance will be set to zero. As tolerance the following equation is used: \\
401        /// tol = length(M) * norm(M) * Double.epsilon \\
402        /// with
403        /// <list type="bullet">
404        /// <item>length(M) - the longest dimension of M</item>
405        /// <item>norm(M) being the largest singular value of M, </item>
406        /// <item>Double.epsilon - the smallest number greater than zero</item>
407        /// </list>
408        /// You may use a overloaded function to define an alternative tolerance.
409        /// </remarks>
410        /// <seealso cref="ILNumerics.ILMath.pinv(ILInArray{double}, double)"/>
411        public static ILRetArray< complex > pinv(ILInArray< complex > M) {
412            return pinv(M, -1);
413        }
414        /// <summary>
415        /// Pseudo inverse of input matrix M
416        /// </summary>
417        /// <param name="M">Input matrix M</param>
418        /// <param name="tolerance">Tolerance, see remarks (default = -1; use default tolerance)</param>
419        /// <returns>Pseudo inverse of M</returns>
420        /// <remarks>The function returns the pseudo inverse (Moore-Penrose pseudoinverse)
421        /// of input matrix M. The return value will be of the same size as
422        /// the transposed of M. it will satisfy the following conditions:
423        /// <list type="bullet">
424        /// <item>M * pinv(M) * M  = M </item>
425        /// <item>pinv(M) * M * pinv(M) = pinv(M)</item>
426        /// <item>pinv(M) * M is hermitian</item>
427        /// <item>M * pinv(M) is hermitian</item>
428        /// </list>
429        /// pinv uses LAPACK's function svd internally. Any singular values less than
430        /// tolerance will be set to zero. If tolerance is less than zero, the following equation
431        /// is used as default: \\
432        /// tol = length(M) * norm(M) * Double.epsilon \\
433        /// with
434        /// <list type="bullet">
435        /// <item>length(M) - the longest dimension of M</item>
436        /// <item>norm(M) being the largest singular value of M, </item>
437        /// <item>Double.epsilon - the smallest constructable double precision number greater than zero</item>
438        /// </list>
439        /// </remarks>
440        public static ILRetArray< complex > pinv(ILInArray< complex > M,  complex tolerance) {
441            using (ILScope.Enter(M)) {
442                // let svd check the dimensions!
443                //if (M.Dimensions.NumberOfDimensions > 2)
444                //   throw new ILDimensionMismatchException("pinv: ...");
445
446                // in order to use the cheap packed version of svd, the matrix must be m x n with m > n!
447                if (M.Size[0] < M.Size[1]) {
448                    return conj(pinv(conj(M.T), tolerance)).T;
449                }
450                if (M.IsScalar)
451                    return  new complex(1,0) / M;
452
453                ILArray< complex> U = empty< complex>(ILSize.Empty00);
454                ILArray< complex> V = empty< complex>(ILSize.Empty00);
455                ILArray< double> S = svd(M, U, V, true, false);
456
457                int m = M.Size[0];
458                int n = M.Size[1];
459
460                ILArray< double> s;
461                switch (m) {
462                    case 0:
463                        s = zeros< double>(ILSize.Scalar1_1);
464                        break;
465                    case 1:
466                        s = S[0];
467                        break;
468                    default:
469                        s = diag< double>(S);
470                        break;
471                }
472                if (tolerance < 0) {
473                    tolerance = ( complex)(M.Size.Longest * max(s).GetValue(0) *  ILMath.MachineParameterDouble.eps);
474                }
475                // sum vector elements: s is dense vector returned from svd
476                int count = (int)sum(s > ( double)tolerance);
477
478                ILArray< complex> Ret = empty< complex>(ILSize.Empty00);
479                if (count == 0)
480                    S.a = zeros< double>(new ILSize(n, m));
481                else {
482                    ILArray< double> OneVec = array< double>( 1.0, count, 1);
483
484                    S.a = diag(divide(OneVec, s[r(0,count - 1)]));
485                    U = conj(U[":;0:" + (count - 1)].T);
486                    Ret = multiply(multiply(V[":;0:" + (count - 1)], real2complex(S)), U);
487                }
488                return Ret;
489            }
490        }
491
492#endregion HYCALPER AUTO GENERATED CODE
493   }
494}
Note: See TracBrowser for help on using the repository browser.