root/bdm/stat/libBM.h @ 214

Revision 214, 15.2 kB (checked in by smidl, 15 years ago)

debug asserts for infinite likelihoods

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