root/bdm/stat/libBM.h @ 229

Revision 229, 15.4 kB (checked in by smidl, 15 years ago)

epdf has a new function: variance()

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Bayesian Models (bm) that use Bayes rule to learn from observations
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/*!
14\defgroup core Core BDM classes
15@{
16*/
17#ifndef BM_H
18#define BM_H
19
20#include <itpp/itbase.h>
21#include "../itpp_ext.h"
22//#include <std>
23
24using namespace itpp;
25
26//! Structure of RV (used internally), i.e. expanded RVs
27class str {
28public:
29        //! vector id ids (non-unique!)
30        ivec ids;
31        //! vector of times
32        ivec times;
33        //!Default constructor
34        str ( ivec ids0, ivec times0 ) :ids ( ids0 ),times ( times0 ) {
35                it_assert_debug ( times0.length() ==ids0.length(),"Incompatible input" );
36        };
37};
38
39/*!
40* \brief Class representing variables, most often random variables
41
42* More?...
43*/
44
45class RV {
46protected:
47        //! size = sum of sizes
48        int tsize;
49        //! len = number of individual rvs
50        int len;
51        //! Vector of unique IDs
52        ivec ids;
53        //! Vector of sizes
54        ivec sizes;
55        //! Vector of shifts from current time
56        ivec times;
57        //! Array of names
58        Array<std::string> names;
59
60private:
61        //! auxiliary function used in constructor
62        void init ( ivec in_ids, Array<std::string> in_names, ivec in_sizes, ivec in_times );
63public:
64        //! Full constructor
65        RV ( Array<std::string> in_names, ivec in_sizes, ivec in_times );
66        //! Constructor with times=0
67        RV ( Array<std::string> in_names, ivec in_sizes );
68        //! Constructor with sizes=1, times=0
69        RV ( Array<std::string> in_names );
70        //! Constructor of empty RV
71        RV ();
72
73        //! Printing output e.g. for debugging.
74        friend std::ostream &operator<< ( std::ostream &os, const RV &rv );
75
76        //! Return number of scalars in the RV.
77        int count() const {return tsize;} ;
78        //! Return length (number of entries) of the RV.
79        int length() const {return len;} ;
80
81        //TODO why not inline and later??
82
83        //! Find indexes of self in another rv, \return ivec of the same size as self.
84        ivec findself ( const RV &rv2 ) const;
85        //! Compare if \c rv2 is identical to this \c RV
86        bool equal ( const RV &rv2 ) const;
87        //! Add (concat) another variable to the current one, \return true if all rv2 were added, false if rv2 is in conflict
88        bool add ( const RV &rv2 );
89        //! Subtract  another variable from the current one
90        RV subt ( const RV &rv2 ) const;
91        //! Select only variables at indeces ind
92        RV subselect ( const ivec &ind ) const;
93        //! Select only variables at indeces ind
94        RV operator() ( const ivec &ind ) const;
95        //! Shift \c time shifted by delta.
96        void t ( int delta );
97        //! generate \c str from rv, by expanding sizes
98        str tostr() const;
99        //! when this rv is a part of bigger rv, this function returns indeces of self in the data vector of the bigger crv.
100        //! Then, data can be copied via: data_of_this = cdata(ind);
101        ivec dataind ( const RV &crv ) const;
102        //! generate mutual indeces when copying data betwenn self and crv.
103        //! Data are copied via: data_of_this(selfi) = data_of_rv2(rv2i)
104        void dataind ( const RV &rv2, ivec &selfi, ivec &rv2i ) const;
105
106        //!access function
107        Array<std::string>& _names() {return names;};
108
109        //!access function
110        int id ( int at ) {return ids ( at );};
111        //!access function
112        int size ( int at ) {return sizes ( at );};
113        //!access function
114        int time ( int at ) {return times ( at );};
115        //!access function
116        std::string name ( int at ) {return names ( at );};
117
118        //!access function
119        void set_id ( int at, int id0 ) {ids ( at ) =id0;};
120        //!access function
121        void set_size ( int at, int size0 ) {sizes ( at ) =size0; tsize=sum ( sizes );};
122        //!access function
123        void set_time ( int at, int time0 ) {times ( at ) =time0;};
124
125        //!Assign unused ids to this rv
126        void newids();
127};
128
129//! Concat two random variables
130RV concat ( const RV &rv1, const RV &rv2 );
131
132//!Default empty RV that can be used as default argument
133extern RV RV0;
134
135//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
136
137class fnc {
138protected:
139        //! Length of the output vector
140        int dimy;
141public:
142        //!default constructor
143        fnc ( int dy ) :dimy ( dy ) {};
144        //! function evaluates numerical value of \f$f(x)\f$ at \f$x=\f$ \c cond
145        virtual vec eval ( const vec &cond ) {
146                return vec ( 0 );
147        };
148       
149        //! function substitutes given value into an appropriate position
150        virtual void condition(const vec &val){};
151
152        //! access function
153        int _dimy() const{return dimy;}
154
155        //! Destructor for future use;
156        virtual ~fnc() {};
157};
158
159class mpdf;
160
161//! Probability density function with numerical statistics, e.g. posterior density.
162
163class epdf {
164protected:
165        //! Identified of the random variable
166        RV rv;
167public:
168        //!default constructor
169        epdf() :rv ( ) {};
170
171        //!default constructor
172        epdf ( const RV &rv0 ) :rv ( rv0 ) {};
173
174//      //! Returns the required moment of the epdf
175//      virtual vec moment ( const int order = 1 );
176
177        //! Returns a sample, \f$x\f$ from density \f$epdf(rv)\f$
178        virtual vec sample () const =0;
179        //! Returns N samples from density \f$epdf(rv)\f$
180        virtual mat sample_m ( int N ) const;
181       
182        //! Compute log-probability of argument \c val
183        virtual double evallog ( const vec &val ) const =0;
184
185        //! Compute log-probability of multiple values argument \c val
186        virtual vec evallog_m ( const mat &Val ) const {
187                vec x ( Val.cols() );
188                for ( int i=0;i<Val.cols();i++ ) {x ( i ) =evallog ( Val.get_col ( i ) ) ;}
189                return x;
190        }
191        //! Return conditional density on the given RV, the remaining rvs will be in conditioning
192        virtual mpdf* condition ( const RV &rv ) const  {it_warning ( "Not implemented" ); return NULL;}
193        //! Return marginal density on the given RV, the remainig rvs are intergrated out
194        virtual epdf* marginal ( const RV &rv ) const {it_warning ( "Not implemented" ); return NULL;}
195
196        //! return expected value
197        virtual vec mean() const =0;
198
199        //! return expected variance (not covariance!)
200        virtual vec variance() const = 0;
201       
202        //! Destructor for future use;
203        virtual ~epdf() {};
204        //! access function, possibly dangerous!
205        const RV& _rv() const {return rv;}
206        //! modifier function - useful when copying epdfs
207        void _renewrv ( const RV &in_rv ) {rv=in_rv;}
208        //!
209};
210
211
212//! Conditional probability density, e.g. modeling some dependencies.
213//TODO Samplecond can be generalized
214
215class mpdf {
216protected:
217        //! modeled random variable
218        RV rv;
219        //! random variable in condition
220        RV rvc;
221        //! pointer to internal epdf
222        epdf* ep;
223public:
224
225        //! Returns a sample from the density conditioned on \c cond, \f$x \sim epdf(rv|cond)\f$. \param cond is numeric value of \c rv \param ll is a return value of log-likelihood of the sample.
226        virtual vec samplecond ( const vec &cond, double &ll ) {
227                this->condition ( cond );
228                vec temp= ep->sample();
229                ll=ep->evallog ( temp );return temp;
230        };
231        //! Returns \param N samples from the density conditioned on \c cond, \f$x \sim epdf(rv|cond)\f$. \param cond is numeric value of \c rv \param ll is a return value of log-likelihood of the sample.
232        virtual mat samplecond_m ( const vec &cond, vec &ll, int N ) {
233                this->condition ( cond );
234                mat temp ( rv.count(),N ); vec smp ( rv.count() );
235                for ( int i=0;i<N;i++ ) {smp=ep->sample() ;temp.set_col ( i, smp );ll ( i ) =ep->evallog ( smp );}
236                return temp;
237        };
238        //! Update \c ep so that it represents this mpdf conditioned on \c rvc = cond
239        virtual void condition ( const vec &cond ) {it_error ( "Not implemented" );};
240
241        //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
242        virtual double evallogcond ( const vec &dt, const vec &cond ) {double tmp; this->condition ( cond );tmp = ep->evallog ( dt );           it_assert_debug(std::isfinite(tmp),"Infinite value"); return tmp;
243        };
244
245        //! Matrix version of evallogcond
246        virtual vec evallogcond_m ( const mat &Dt, const vec &cond ) {this->condition ( cond );return ep->evallog_m ( Dt );};
247
248        //! Destructor for future use;
249        virtual ~mpdf() {};
250
251        //! Default constructor
252        mpdf ( const RV &rv0, const RV &rvc0 ) :rv ( rv0 ),rvc ( rvc0 ) {};
253        //! access function
254        RV _rvc() const {return rvc;}
255        //! access function
256        RV _rv() const {return rv;}
257        //!access function
258        epdf& _epdf() {return *ep;}
259        //!access function
260        epdf* _e() {return ep;}
261};
262
263//!DataLink is a connection between an epdf and its superordinate epdf (Up)
264//! It is assumed that my val is fully present in "Up"
265class datalink_e2e {
266protected:
267        //! Remember how long val should be
268        int valsize;
269        //! Remember how long val of "Up" should be
270        int valupsize;
271        //! val-to-val link, indeces of the upper val
272        ivec v2v_up;
273public:
274        //! Constructor
275        datalink_e2e ( const RV &rv, const RV &rv_up ) :
276                        valsize ( rv.count() ), valupsize ( rv_up.count() ), v2v_up ( rv.dataind ( rv_up ) )  {
277                it_assert_debug ( v2v_up.length() ==valsize,"rv is not fully in rv_up" );
278        }
279        //! Get val for myself from val of "Up"
280        vec get_val ( const vec &val_up ) {it_assert_debug ( valupsize==val_up.length(),"Wrong val_up" ); return get_vec ( val_up,v2v_up );}
281        //! Fill val of "Up" by my pieces
282        void fill_val ( vec &val_up, const vec &val ) {
283                it_assert_debug ( valsize==val.length(),"Wrong val" );
284                it_assert_debug ( valupsize==val_up.length(),"Wrong val_up" );
285                set_subvector ( val_up, v2v_up, val );
286        }
287};
288
289//! data link between
290class datalink_m2e: public datalink_e2e {
291protected:
292        //! Remember how long cond should be
293        int condsize;
294        //!upper_val-to-local_cond link, indeces of the upper val
295        ivec v2c_up;
296        //!upper_val-to-local_cond link, ideces of the local cond
297        ivec v2c_lo;
298
299public:
300        //! Constructor
301        datalink_m2e ( const RV &rv,  const RV &rvc, const RV &rv_up ) :
302                        datalink_e2e ( rv,rv_up ), condsize ( rvc.count() ) {
303                //establish v2c connection
304                rvc.dataind ( rv_up, v2c_lo, v2c_up );
305        }
306        //!Construct condition
307        vec get_cond ( const vec &val_up ) {
308                vec tmp ( condsize );
309                set_subvector ( tmp,v2c_lo,val_up ( v2c_up ) );
310                return tmp;
311        }
312        void fill_val_cond ( vec &val_up, const vec &val, const vec &cond ) {
313                it_assert_debug ( valsize==val.length(),"Wrong val" );
314                it_assert_debug ( valupsize==val_up.length(),"Wrong val_up" );
315                set_subvector ( val_up, v2v_up, val );
316                set_subvector ( val_up, v2c_up, cond );
317        }
318};
319//!DataLink is a connection between mpdf and its superordinate (Up)
320//! This class links
321class datalink_m2m: public datalink_m2e {
322protected:
323        //!cond-to-cond link, indeces of the upper cond
324        ivec c2c_up;
325        //!cond-to-cond link, indeces of the local cond
326        ivec c2c_lo;
327public:
328        //! Constructor
329        datalink_m2m ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) :
330                        datalink_m2e ( rv, rvc, rv_up) {
331                //establish c2c connection
332                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
333                it_assert_debug(c2c_lo.length()+v2c_lo.length()==condsize, "cond is not fully given");
334        }
335        //! Get cond for myself from val and cond of "Up"
336        vec get_cond ( const vec &val_up, const vec &cond_up ) {
337                vec tmp ( condsize );
338                set_subvector ( tmp,v2c_lo,val_up ( v2c_up ) );
339                set_subvector ( tmp,c2c_lo,cond_up ( c2c_up ) );
340                return tmp;
341        }
342        //! Fill
343
344};
345
346/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
347
348*/
349class mepdf : public mpdf {
350public:
351        //!Default constructor
352        mepdf (const epdf* em ) :mpdf ( em->_rv(),RV() ) {ep=const_cast<epdf*>(em);};
353        void condition ( const vec &cond ) {}
354};
355
356//!\brief Abstract composition of pdfs, a base for specific classes
357//!this abstract class is common to epdf and mpdf
358class compositepdf {
359protected:
360        //!Number of mpdfs in the composite
361        int n;
362        //! Elements of composition
363        Array<mpdf*> mpdfs;
364public:
365        compositepdf ( Array<mpdf*> A0 ) : n ( A0.length() ), mpdfs ( A0 ) {};
366        //! find common rv, flag \param checkoverlap modifies whether overlaps are acceptable
367        RV getrv ( bool checkoverlap=false );
368        //! common rvc of all mpdfs is written to rvc
369        void setrvc ( const RV &rv, RV &rvc );
370};
371
372/*! \brief Abstract class for discrete-time sources of data.
373
374The class abstracts operations of: (i) data aquisition, (ii) data-preprocessing, (iii) scaling of data, and (iv) data resampling from the task of estimation and control.
375Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
376
377*/
378
379class DS {
380protected:
381        //!Observed variables, returned by \c getdata().
382        RV Drv;
383        //!Action variables, accepted by \c write().
384        RV Urv; //
385public:
386        //! Returns full vector of observed data
387        void getdata ( vec &dt );
388        //! Returns data records at indeces.
389        void getdata ( vec &dt, ivec &indeces );
390        //! Accepts action variable and schedule it for application.
391        void write ( vec &ut );
392        //! Accepts action variables at specific indeces
393        void write ( vec &ut, ivec &indeces );
394        /*! \brief Method that assigns random variables to the datasource.
395        Typically, the datasource will be constructed without knowledge of random variables. This method will associate existing variables with RVs.
396
397        (Inherited from m3k, may be deprecated soon).
398        */
399        void linkrvs ( RV &drv, RV &urv );
400
401        //! Moves from \f$t\f$ to \f$t+1\f$, i.e. perfroms the actions and reads response of the system.
402        void step();
403
404};
405
406/*! \brief Bayesian Model of the world, i.e. all uncertainty is modeled by probabilities.
407
408*/
409
410class BM {
411protected:
412        //!Random variable of the posterior
413        RV rv;
414        //!Logarithm of marginalized data likelihood.
415        double ll;
416        //!  If true, the filter will compute likelihood of the data record and store it in \c ll . Set to false if you want to save computational time.
417        bool evalll;
418public:
419
420        //!Default constructor
421        BM ( const RV &rv0, double ll0=0,bool evalll0=true ) :rv ( rv0 ), ll ( ll0 ),evalll ( evalll0 ) {//Fixme: test rv
422        };
423        //!Copy constructor
424        BM ( const BM &B ) : rv ( B.rv ), ll ( B.ll ), evalll ( B.evalll ) {}
425
426        /*! \brief Incremental Bayes rule
427        @param dt vector of input data
428        */
429        virtual void bayes ( const vec &dt ) = 0;
430        //! Batch Bayes rule (columns of Dt are observations)
431        virtual void bayesB ( const mat &Dt );
432        //! Returns a reference to the epdf representing posterior density on parameters.
433        virtual const epdf& _epdf() const =0;
434
435        //! Returns a pointer to the epdf representing posterior density on parameters. Use with care!
436        virtual const epdf* _e() const =0;
437
438        //! Evaluates predictive log-likelihood of the given data record
439        //! I.e. marginal likelihood of the data with the posterior integrated out.
440        virtual double logpred ( const vec &dt ) const{it_error ( "Not implemented" );return 0.0;}
441        //! Matrix version of logpred
442        vec logpred_m ( const mat &dt ) const{vec tmp ( dt.cols() );for ( int i=0;i<dt.cols();i++ ) {tmp ( i ) =logpred ( dt.get_col ( i ) );}return tmp;}
443
444        //!Constructs a predictive density (marginal density on data)
445        virtual epdf* predictor ( const RV &rv ) const {it_error ( "Not implemented" );return NULL;};
446
447        //! Destructor for future use;
448        virtual ~BM() {};
449        //!access function
450        const RV& _rv() const {return rv;}
451        //!access function
452        double _ll() const {return ll;}
453        //!access function
454        void set_evalll ( bool evl0 ) {evalll=evl0;}
455
456        //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
457        //! Prototype: BM* _copy_(){BM Tmp*=new Tmp(this*);  return Tmp; }
458        virtual BM* _copy_ ( bool changerv=false ) {it_error ( "function _copy_ not implemented for this BM" ); return NULL;};
459};
460
461/*!
462\brief Conditional Bayesian Filter
463
464Evaluates conditional filtering density \f$f(rv|rvc,data)\f$ for a given \c rvc which is specified in each step by calling function \c condition.
465
466This is an interface class used to assure that certain BM has operation \c condition .
467
468*/
469
470class BMcond {
471protected:
472        //! Identificator of the conditioning variable
473        RV rvc;
474public:
475        //! Substitute \c val for \c rvc.
476        virtual void condition ( const vec &val ) =0;
477        //! Default constructor
478        BMcond ( RV &rv0 ) :rvc ( rv0 ) {};
479        //! Destructor for future use
480        virtual ~BMcond() {};
481        //! access function
482        const RV& _rvc() const {return rvc;}
483};
484
485/*! @} */
486#endif // BM_H
Note: See TracBrowser for help on using the browser.