root/bdm/stat/libBM.h @ 257

Revision 257, 15.7 kB (checked in by smidl, 15 years ago)

All objects have a virtual predecessor. This allows type checking in UI, see

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