Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.LinearRegression/3.2/alglib/lq.cs @ 2273

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

Added linear regression plugin. #697

File size: 12.9 KB
Line 
1/*************************************************************************
2Copyright (c) 2005-2007, Sergey Bochkanov (ALGLIB project).
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7
8- Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10
11- Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer listed
13  in this license in the documentation and/or other materials
14  provided with the distribution.
15
16- Neither the name of the copyright holders nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*************************************************************************/
32
33using System;
34
35class lq
36{
37    /*************************************************************************
38    LQ decomposition of a rectangular matrix of size MxN
39
40    Input parameters:
41        A   -   matrix A whose indexes range within [0..M-1, 0..N-1].
42        M   -   number of rows in matrix A.
43        N   -   number of columns in matrix A.
44
45    Output parameters:
46        A   -   matrices L and Q in compact form (see below)
47        Tau -   array of scalar factors which are used to form
48                matrix Q. Array whose index ranges within [0..Min(M,N)-1].
49
50    Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size
51    MxM, L - lower triangular (or lower trapezoid) matrix of size M x N.
52
53    The elements of matrix L are located on and below  the  main  diagonal  of
54    matrix A. The elements which are located in Tau array and above  the  main
55    diagonal of matrix A are used to form matrix Q as follows:
56
57    Matrix Q is represented as a product of elementary reflections
58
59    Q = H(k-1)*H(k-2)*...*H(1)*H(0),
60
61    where k = min(m,n), and each H(i) is of the form
62
63    H(i) = 1 - tau * v * (v^T)
64
65    where tau is a scalar stored in Tau[I]; v - real vector, so that v(0:i-1)=0,
66    v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1).
67
68      -- ALGLIB --
69         Copyright 2005-2007 by Bochkanov Sergey
70    *************************************************************************/
71    public static void rmatrixlq(ref double[,] a,
72        int m,
73        int n,
74        ref double[] tau)
75    {
76        double[] work = new double[0];
77        double[] t = new double[0];
78        int i = 0;
79        int k = 0;
80        int minmn = 0;
81        int maxmn = 0;
82        double tmp = 0;
83        int i_ = 0;
84        int i1_ = 0;
85
86        minmn = Math.Min(m, n);
87        maxmn = Math.Max(m, n);
88        work = new double[m+1];
89        t = new double[n+1];
90        tau = new double[minmn-1+1];
91        k = Math.Min(m, n);
92        for(i=0; i<=k-1; i++)
93        {
94           
95            //
96            // Generate elementary reflector H(i) to annihilate A(i,i+1:n-1)
97            //
98            i1_ = (i) - (1);
99            for(i_=1; i_<=n-i;i_++)
100            {
101                t[i_] = a[i,i_+i1_];
102            }
103            reflections.generatereflection(ref t, n-i, ref tmp);
104            tau[i] = tmp;
105            i1_ = (1) - (i);
106            for(i_=i; i_<=n-1;i_++)
107            {
108                a[i,i_] = t[i_+i1_];
109            }
110            t[1] = 1;
111            if( i<n )
112            {
113               
114                //
115                // Apply H(i) to A(i+1:m,i:n) from the right
116                //
117                reflections.applyreflectionfromtheright(ref a, tau[i], ref t, i+1, m-1, i, n-1, ref work);
118            }
119        }
120    }
121
122
123    /*************************************************************************
124    Partial unpacking of matrix Q from the LQ decomposition of a matrix A
125
126    Input parameters:
127        A       -   matrices L and Q in compact form.
128                    Output of RMatrixLQ subroutine.
129        M       -   number of rows in given matrix A. M>=0.
130        N       -   number of columns in given matrix A. N>=0.
131        Tau     -   scalar factors which are used to form Q.
132                    Output of the RMatrixLQ subroutine.
133        QRows   -   required number of rows in matrix Q. N>=QRows>=0.
134
135    Output parameters:
136        Q       -   first QRows rows of matrix Q. Array whose indexes range
137                    within [0..QRows-1, 0..N-1]. If QRows=0, the array remains
138                    unchanged.
139
140      -- ALGLIB --
141         Copyright 2005 by Bochkanov Sergey
142    *************************************************************************/
143    public static void rmatrixlqunpackq(ref double[,] a,
144        int m,
145        int n,
146        ref double[] tau,
147        int qrows,
148        ref double[,] q)
149    {
150        int i = 0;
151        int j = 0;
152        int k = 0;
153        int minmn = 0;
154        double[] v = new double[0];
155        double[] work = new double[0];
156        int i_ = 0;
157        int i1_ = 0;
158
159        System.Diagnostics.Debug.Assert(qrows<=n, "RMatrixLQUnpackQ: QRows>N!");
160        if( m<=0 | n<=0 | qrows<=0 )
161        {
162            return;
163        }
164       
165        //
166        // init
167        //
168        minmn = Math.Min(m, n);
169        k = Math.Min(minmn, qrows);
170        q = new double[qrows-1+1, n-1+1];
171        v = new double[n+1];
172        work = new double[qrows+1];
173        for(i=0; i<=qrows-1; i++)
174        {
175            for(j=0; j<=n-1; j++)
176            {
177                if( i==j )
178                {
179                    q[i,j] = 1;
180                }
181                else
182                {
183                    q[i,j] = 0;
184                }
185            }
186        }
187       
188        //
189        // unpack Q
190        //
191        for(i=k-1; i>=0; i--)
192        {
193           
194            //
195            // Apply H(i)
196            //
197            i1_ = (i) - (1);
198            for(i_=1; i_<=n-i;i_++)
199            {
200                v[i_] = a[i,i_+i1_];
201            }
202            v[1] = 1;
203            reflections.applyreflectionfromtheright(ref q, tau[i], ref v, 0, qrows-1, i, n-1, ref work);
204        }
205    }
206
207
208    /*************************************************************************
209    Unpacking of matrix L from the LQ decomposition of a matrix A
210
211    Input parameters:
212        A       -   matrices Q and L in compact form.
213                    Output of RMatrixLQ subroutine.
214        M       -   number of rows in given matrix A. M>=0.
215        N       -   number of columns in given matrix A. N>=0.
216
217    Output parameters:
218        L       -   matrix L, array[0..M-1, 0..N-1].
219
220      -- ALGLIB --
221         Copyright 2005 by Bochkanov Sergey
222    *************************************************************************/
223    public static void rmatrixlqunpackl(ref double[,] a,
224        int m,
225        int n,
226        ref double[,] l)
227    {
228        int i = 0;
229        int k = 0;
230        int i_ = 0;
231
232        if( m<=0 | n<=0 )
233        {
234            return;
235        }
236        l = new double[m-1+1, n-1+1];
237        for(i=0; i<=n-1; i++)
238        {
239            l[0,i] = 0;
240        }
241        for(i=1; i<=m-1; i++)
242        {
243            for(i_=0; i_<=n-1;i_++)
244            {
245                l[i,i_] = l[0,i_];
246            }
247        }
248        for(i=0; i<=m-1; i++)
249        {
250            k = Math.Min(i, n-1);
251            for(i_=0; i_<=k;i_++)
252            {
253                l[i,i_] = a[i,i_];
254            }
255        }
256    }
257
258
259    /*************************************************************************
260    Obsolete 1-based subroutine
261    See RMatrixLQ for 0-based replacement.
262    *************************************************************************/
263    public static void lqdecomposition(ref double[,] a,
264        int m,
265        int n,
266        ref double[] tau)
267    {
268        double[] work = new double[0];
269        double[] t = new double[0];
270        int i = 0;
271        int k = 0;
272        int nmip1 = 0;
273        int minmn = 0;
274        int maxmn = 0;
275        double tmp = 0;
276        int i_ = 0;
277        int i1_ = 0;
278
279        minmn = Math.Min(m, n);
280        maxmn = Math.Max(m, n);
281        work = new double[m+1];
282        t = new double[n+1];
283        tau = new double[minmn+1];
284       
285        //
286        // Test the input arguments
287        //
288        k = Math.Min(m, n);
289        for(i=1; i<=k; i++)
290        {
291           
292            //
293            // Generate elementary reflector H(i) to annihilate A(i,i+1:n)
294            //
295            nmip1 = n-i+1;
296            i1_ = (i) - (1);
297            for(i_=1; i_<=nmip1;i_++)
298            {
299                t[i_] = a[i,i_+i1_];
300            }
301            reflections.generatereflection(ref t, nmip1, ref tmp);
302            tau[i] = tmp;
303            i1_ = (1) - (i);
304            for(i_=i; i_<=n;i_++)
305            {
306                a[i,i_] = t[i_+i1_];
307            }
308            t[1] = 1;
309            if( i<n )
310            {
311               
312                //
313                // Apply H(i) to A(i+1:m,i:n) from the right
314                //
315                reflections.applyreflectionfromtheright(ref a, tau[i], ref t, i+1, m, i, n, ref work);
316            }
317        }
318    }
319
320
321    /*************************************************************************
322    Obsolete 1-based subroutine
323    See RMatrixLQUnpackQ for 0-based replacement.
324    *************************************************************************/
325    public static void unpackqfromlq(ref double[,] a,
326        int m,
327        int n,
328        ref double[] tau,
329        int qrows,
330        ref double[,] q)
331    {
332        int i = 0;
333        int j = 0;
334        int k = 0;
335        int minmn = 0;
336        double[] v = new double[0];
337        double[] work = new double[0];
338        int vm = 0;
339        int i_ = 0;
340        int i1_ = 0;
341
342        System.Diagnostics.Debug.Assert(qrows<=n, "UnpackQFromLQ: QRows>N!");
343        if( m==0 | n==0 | qrows==0 )
344        {
345            return;
346        }
347       
348        //
349        // init
350        //
351        minmn = Math.Min(m, n);
352        k = Math.Min(minmn, qrows);
353        q = new double[qrows+1, n+1];
354        v = new double[n+1];
355        work = new double[qrows+1];
356        for(i=1; i<=qrows; i++)
357        {
358            for(j=1; j<=n; j++)
359            {
360                if( i==j )
361                {
362                    q[i,j] = 1;
363                }
364                else
365                {
366                    q[i,j] = 0;
367                }
368            }
369        }
370       
371        //
372        // unpack Q
373        //
374        for(i=k; i>=1; i--)
375        {
376           
377            //
378            // Apply H(i)
379            //
380            vm = n-i+1;
381            i1_ = (i) - (1);
382            for(i_=1; i_<=vm;i_++)
383            {
384                v[i_] = a[i,i_+i1_];
385            }
386            v[1] = 1;
387            reflections.applyreflectionfromtheright(ref q, tau[i], ref v, 1, qrows, i, n, ref work);
388        }
389    }
390
391
392    /*************************************************************************
393    Obsolete 1-based subroutine
394    *************************************************************************/
395    public static void lqdecompositionunpacked(double[,] a,
396        int m,
397        int n,
398        ref double[,] l,
399        ref double[,] q)
400    {
401        int i = 0;
402        int j = 0;
403        double[] tau = new double[0];
404
405        a = (double[,])a.Clone();
406
407        if( n<=0 )
408        {
409            return;
410        }
411        q = new double[n+1, n+1];
412        l = new double[m+1, n+1];
413       
414        //
415        // LQDecomposition
416        //
417        lqdecomposition(ref a, m, n, ref tau);
418       
419        //
420        // L
421        //
422        for(i=1; i<=m; i++)
423        {
424            for(j=1; j<=n; j++)
425            {
426                if( j>i )
427                {
428                    l[i,j] = 0;
429                }
430                else
431                {
432                    l[i,j] = a[i,j];
433                }
434            }
435        }
436       
437        //
438        // Q
439        //
440        unpackqfromlq(ref a, m, n, ref tau, n, ref q);
441    }
442}
Note: See TracBrowser for help on using the repository browser.