root/library/bdm/math/square_mat.h @ 706

Revision 700, 8.9 kB (checked in by smidl, 15 years ago)

Making tutorial/userguide example work again (changes of mpdf and bayes)

  • Property svn:eol-style set to native
Line 
1/*!
2 * \file
3 * \brief Matrices in decomposed forms (LDL', LU, UDU', etc).
4 * \author Vaclav Smidl.
5 *
6 * -----------------------------------
7 * BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8 *
9 * Using IT++ for numerical operations
10 * -----------------------------------
11 */
12
13#ifndef DC_H
14#define DC_H
15
16
17#include "../itpp_ext.h"
18#include "../bdmerror.h"
19
20namespace bdm
21{
22
23using namespace itpp;
24
25//! Auxiliary function dydr; dyadic reduction
26void dydr ( double * r, double *f, double *Dr, double *Df, double *R, int jl, int jh, double *kr, int m, int mx );
27
28//! Auxiliary function ltuinv; inversion of a triangular matrix;
29//TODO can be done via: dtrtri.f from lapack
30mat ltuinv ( const mat &L );
31
32/*! \brief Abstract class for representation of double symmetric matrices in square-root form.
33
34All operations defined on this class should be optimized for the chosen decomposition.
35*/
36class sqmat {
37public:
38        /*!
39         * Perfroms a rank-1 update by outer product of vectors: \f$V = V + w v v'\f$.
40         * @param  v Vector forming the outer product to be added
41         * @param  w weight of updating; can be negative
42
43         BLAS-2b operation.
44         */
45        virtual void opupdt ( const vec &v, double w ) { bdm_error("not implemented"); };
46
47        /*! \brief Conversion to full matrix.
48        */
49
50        virtual mat to_mat() const { bdm_error("not implemented"); return mat(0,0); }
51
52        /*! \brief Inplace symmetric multiplication by a SQUARE matrix \f$C\f$, i.e. \f$V = C*V*C'\f$
53        @param C multiplying matrix,
54        */
55        virtual void mult_sym ( const mat &C ) { bdm_error("not implemented"); };
56
57        /*! \brief Inplace symmetric multiplication by a SQUARE transpose of matrix \f$C\f$, i.e. \f$V = C'*V*C\f$
58        @param C multiplying matrix,
59        */
60        virtual void mult_sym_t ( const mat &C ) { bdm_error("not implemented"); }
61
62
63        /*!
64        \brief Logarithm of a determinant.
65
66        */
67        virtual double logdet() const { bdm_error("not implemented"); return 0;};
68
69        /*!
70        \brief Multiplies square root of \f$V\f$ by vector \f$x\f$.
71
72        Used e.g. in generating normal samples.
73        */
74        virtual vec sqrt_mult ( const vec &v )  const { bdm_error("not implemented"); return vec(0); };
75
76        /*!
77        \brief Evaluates quadratic form \f$x= v'*V*v\f$;
78
79        */
80        virtual double qform ( const vec &v ) const { bdm_error("not implemented"); return 0; };
81
82        /*!
83        \brief Evaluates quadratic form \f$x= v'*inv(V)*v\f$;
84
85        */
86        virtual double invqform ( const vec &v ) const { bdm_error("not implemented"); return 0; };
87
88//      //! easy version of the
89//      sqmat inv();
90
91        //! Clearing matrix so that it corresponds to zeros.
92        virtual void clear() { bdm_error("not implemented"); };
93
94        //! Reimplementing common functions of mat: cols().
95        int cols() const {
96                return dim;
97        };
98
99        //! Reimplementing common functions of mat: rows().
100        int rows() const {
101                return dim;
102        };
103
104        //! Destructor for future use;
105        virtual ~sqmat() {};
106        //! Default constructor
107        sqmat ( const int dim0 ) : dim ( dim0 ) {};
108        //! Default constructor
109        sqmat() : dim ( 0 ) {};
110protected:
111        //! dimension of the square matrix
112        int dim;
113};
114
115
116/*! \brief Fake sqmat. This class maps sqmat operations to operations on full matrix.
117
118This class can be used to compare performance of algorithms using decomposed matrices with perormance of the same algorithms using full matrices;
119*/
120class fsqmat: public sqmat {
121protected:
122        //! Full matrix on which the operations are performed
123        mat M;
124public:
125        void opupdt ( const vec &v, double w );
126        mat to_mat() const;
127        void mult_sym ( const mat &C );
128        void mult_sym_t ( const mat &C );
129        //! store result of \c mult_sym in external matrix \f$U\f$
130        void mult_sym ( const mat &C, fsqmat &U ) const;
131        //! store result of \c mult_sym_t in external matrix \f$U\f$
132        void mult_sym_t ( const mat &C, fsqmat &U ) const;
133        void clear();
134
135        //! Default initialization
136        fsqmat() {}; // mat will be initialized OK
137        //! Default initialization with proper size
138        fsqmat ( const int dim0 ); // mat will be initialized OK
139        //! Constructor
140        fsqmat ( const mat &M );
141
142        /*!
143          Some templates require this constructor to compile, but
144          it shouldn't actually be called.
145        */
146        fsqmat ( const fsqmat &M, const ivec &perm ) {
147                bdm_error ( "not implemented" );
148        }
149
150        //! Constructor
151        fsqmat ( const vec &d ) : sqmat ( d.length() ) {
152                M = diag ( d );
153        };
154
155        //! Destructor for future use;
156        virtual ~fsqmat() {};
157
158
159        /*! \brief Matrix inversion preserving the chosen form.
160
161        @param Inv a space where the inverse is stored.
162
163        */
164        void inv ( fsqmat &Inv ) const;
165
166        double logdet() const {
167                return log ( det ( M ) );
168        };
169        double qform ( const  vec &v ) const {
170                return ( v* ( M*v ) );
171        };
172        double invqform ( const  vec &v ) const {
173                return ( v* ( itpp::inv ( M ) *v ) );
174        };
175        vec sqrt_mult ( const vec &v ) const {
176                mat Ch = chol ( M );
177                return Ch*v;
178        };
179
180        //! Add another matrix in fsq form with weight w
181        void add ( const fsqmat &fsq2, double w = 1.0 ) {
182                M += fsq2.M;
183        };
184
185        //! Access functions
186        void setD ( const vec &nD ) {
187                M = diag ( nD );
188        }
189        //! Access functions
190        vec getD () {
191                return diag ( M );
192        }
193        //! Access functions
194        void setD ( const vec &nD, int i ) {
195                for ( int j = i; j < nD.length(); j++ ) {
196                        M ( j, j ) = nD ( j - i );    //Fixme can be more general
197                }
198        }
199
200
201        //! add another fsqmat matrix
202        fsqmat& operator += ( const fsqmat &A ) {
203                M += A.M;
204                return *this;
205        };
206        //! subtrack another fsqmat matrix
207        fsqmat& operator -= ( const fsqmat &A ) {
208                M -= A.M;
209                return *this;
210        };
211        //! multiply by a scalar
212        fsqmat& operator *= ( double x ) {
213                M *= x;
214                return *this;
215        };
216       
217        //! cast to normal mat
218        operator mat&() {return M;};
219       
220//              fsqmat& operator = ( const fsqmat &A) {M=A.M; return *this;};
221        //! print full matrix
222        friend std::ostream &operator<< ( std::ostream &os, const fsqmat &sq );
223        //!access function
224        mat & _M (  ) {return M;};
225
226};
227
228
229/*! \brief Matrix stored in LD form, (commonly known as UD)
230
231Matrix is decomposed as follows: \f[M = L'DL\f] where only \f$L\f$ and \f$D\f$ matrices are stored.
232All inplace operations modifies only these and the need to compose and decompose the matrix is avoided.
233*/
234class ldmat: public sqmat {
235public:
236        //! Construct by copy of L and D.
237        ldmat ( const mat &L, const vec &D );
238        //! Construct by decomposition of full matrix V.
239        ldmat ( const mat &V );
240        //! Construct by restructuring of V0 accordint to permutation vector perm.
241        ldmat ( const ldmat &V0, const ivec &perm ) : sqmat ( V0.rows() ) {
242                ldform ( V0.L.get_cols ( perm ), V0.D );
243        };
244        //! Construct diagonal matrix with diagonal D0
245        ldmat ( vec D0 );
246        //!Default constructor
247        ldmat ();
248        //! Default initialization with proper size
249        ldmat ( const int dim0 );
250
251        //! Destructor for future use;
252        virtual ~ldmat() {};
253
254        // Reimplementation of compulsory operatios
255
256        void opupdt ( const vec &v, double w );
257        mat to_mat() const;
258        void mult_sym ( const mat &C );
259        void mult_sym_t ( const mat &C );
260        //! Add another matrix in LD form with weight w
261        void add ( const ldmat &ld2, double w = 1.0 );
262        double logdet() const;
263        double qform ( const vec &v ) const;
264        double invqform ( const vec &v ) const;
265        void clear();
266        vec sqrt_mult ( const vec &v ) const;
267
268
269        /*! \brief Matrix inversion preserving the chosen form.
270        @param Inv a space where the inverse is stored.
271        */
272        void inv ( ldmat &Inv ) const;
273
274        /*! \brief Symmetric multiplication of \f$U\f$ by a general matrix \f$C\f$, result of which is stored in the current class.
275        @param C matrix to multiply with
276        @param U a space where the inverse is stored.
277        */
278        void mult_sym ( const mat &C, ldmat &U ) const;
279
280        /*! \brief Symmetric multiplication of \f$U\f$ by a transpose of a general matrix \f$C\f$, result of which is stored in the current class.
281        @param C matrix to multiply with
282        @param U a space where the inverse is stored.
283        */
284        void mult_sym_t ( const mat &C, ldmat &U ) const;
285
286
287        /*! \brief Transforms general \f$A'D0 A\f$ into pure \f$L'DL\f$
288
289        The new decomposition fullfills: \f$A'*diag(D)*A = self.L'*diag(self.D)*self.L\f$
290        @param A general matrix
291        @param D0 general vector
292        */
293        void ldform ( const mat &A, const vec &D0 );
294
295        //! Access functions
296        void setD ( const vec &nD ) {
297                D = nD;
298        }
299        //! Access functions
300        void setD ( const vec &nD, int i ) {
301                D.replace_mid ( i, nD );    //Fixme can be more general
302        }
303        //! Access functions
304        void setL ( const vec &nL ) {
305                L = nL;
306        }
307
308        //! Access functions
309        const vec& _D() const {
310                return D;
311        }
312        //! Access functions
313        const mat& _L() const {
314                return L;
315        }
316
317        //! add another ldmat matrix
318        ldmat& operator += ( const ldmat &ldA );
319        //! subtract another ldmat matrix
320        ldmat& operator -= ( const ldmat &ldA );
321        //! multiply by a scalar
322        ldmat& operator *= ( double x );
323
324        //! print both \c L and \c D
325        friend std::ostream &operator<< ( std::ostream &os, const ldmat &sq );
326
327protected:
328        //! Positive vector \f$D\f$
329        vec D;
330        //! Lower-triangular matrix \f$L\f$
331        mat L;
332
333};
334
335//////// Operations:
336//!mapping of add operation to operators
337inline ldmat& ldmat::operator += ( const ldmat & ldA )  {
338        this->add ( ldA );
339        return *this;
340}
341//!mapping of negative add operation to operators
342inline ldmat& ldmat::operator -= ( const ldmat & ldA )  {
343        this->add ( ldA, -1.0 );
344        return *this;
345}
346
347}
348
349#endif // DC_H
Note: See TracBrowser for help on using the browser.