root/bdm/stat/libBM.h @ 347

Revision 347, 23.9 kB (checked in by smidl, 15 years ago)

change in loggers! old experiments may stop working

  • 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
17#include "../itpp_ext.h"
18#include "../libconfig/libconfig.h++"
19#include <map>
20
21using namespace libconfig;
22
23using namespace itpp;
24using namespace std;
25
26namespace bdm {
27
28//! Root class of BDM objects
29
30class bdmroot {
31public:
32        //! make sure this is a virtual object
33        virtual ~bdmroot() 
34        {
35        }
36
37        //! This method returns a basic info about the current instance
38        virtual string ToString()
39        {
40                return "";
41        }
42
43        //! This method arrange instance properties according the data stored in the Setting structure
44        virtual void from_setting( const Setting &root )
45        {
46        }
47
48        //! This method save all the instance properties into the Setting structure
49        virtual void to_setting( Setting &root ) 
50        {       
51        }
52};
53
54typedef std::map<string, int> RVmap;
55extern ivec RV_SIZES;
56extern Array<string> RV_NAMES;
57
58//! Structure of RV (used internally), i.e. expanded RVs
59class str {
60public:
61        //! vector id ids (non-unique!)
62        ivec ids;
63        //! vector of times
64        ivec times;
65        //!Default constructor
66        str ( ivec ids0, ivec times0 ) :ids ( ids0 ),times ( times0 ) {
67                it_assert_debug ( times0.length() ==ids0.length(),"Incompatible input" );
68        };
69};
70
71/*!
72* \brief Class representing variables, most often random variables
73
74The purpose of this class is to decribe a vector of data. Such description is used for connecting various vectors between each other, see class datalink.
75
76The class is implemented using global variables to assure uniqueness of description:
77
78 In is a vector
79\dot
80digraph datalink {
81rankdir=LR;
82subgraph cluster0 {
83node [shape=record];
84label = "RV_MAP \n std::map<string,int>";
85map [label="{{\"a\"| \"b\" | \"c\"} | {<3> 3 |<1> 1|<2> 2}}"];
86color = "white"
87}
88subgraph cluster1{
89node [shape=record];
90label = "RV_NAMES";
91names [label="{<1> \"b\" | <2> \"c\" | <3>\"a\" }"];
92color = "white"
93}
94subgraph cluster2{
95node [shape=record];
96label = "RV_SIZES";
97labelloc = b;
98sizes [label="{<1>1 |<2> 4 |<3> 1}"];
99color = "white"
100}
101map:1 -> names:1;
102map:1 -> sizes:1;
103map:3 -> names:3;
104map:3 -> sizes:3;
105}
106\enddot
107*/
108
109class RV :public bdmroot {
110protected:
111        //! size of the data vector
112        int dsize;
113        //! number of individual rvs
114        int len;
115        //! Vector of unique IDs
116        ivec ids;
117        //! Vector of shifts from current time
118        ivec times;
119
120private:
121        //! auxiliary function used in constructor
122        void init ( Array<std::string> in_names, ivec in_sizes, ivec in_times );
123        int init ( const  string &name, int size );
124public:
125        //! \name Constructors
126        //!@{
127
128        //! Full constructor
129        RV ( Array<std::string> in_names, ivec in_sizes, ivec in_times ) {init ( in_names,in_sizes,in_times );};
130        //! Constructor with times=0
131        RV ( Array<std::string> in_names, ivec in_sizes ) {init ( in_names,in_sizes,zeros_i ( in_names.length() ) );};
132        //! Constructor with sizes=1, times=0
133        RV ( Array<std::string> in_names ) {init ( in_names,ones_i ( in_names.length() ),zeros_i ( in_names.length() ) );}
134        //! Constructor of empty RV
135        RV () :dsize ( 0 ),len ( 0 ),ids ( 0 ),times ( 0 ) {};
136        //! Constructor of a single RV with given id
137        RV ( string name, int sz, int tm=0 );
138        //!@}
139
140        //! \name Access functions
141        //!@{
142
143        //! Printing output e.g. for debugging.
144        friend std::ostream &operator<< ( std::ostream &os, const RV &rv );
145        int _dsize() const {return dsize;} ;
146        //! Recount size of the corresponding data vector
147        int countsize() const;
148        ivec cumsizes() const;
149        int length() const {return len;} ;
150        int id ( int at ) const{return ids ( at );};
151        int size ( int at ) const {return RV_SIZES ( ids ( at ) );};
152        int time ( int at ) const{return times ( at );};
153        std::string name ( int at ) const {return RV_NAMES ( ids ( at ) );};
154        void set_time ( int at, int time0 ) {times ( at ) =time0;};
155        //!@}
156
157        //TODO why not inline and later??
158
159        //! \name Algebra on Random Variables
160        //!@{
161
162        //! Find indices of self in another rv, \return ivec of the same size as self.
163        ivec findself ( const RV &rv2 ) const;
164        //! Compare if \c rv2 is identical to this \c RV
165        bool equal ( const RV &rv2 ) const;
166        //! Add (concat) another variable to the current one, \return true if all rv2 were added, false if rv2 is in conflict
167        bool add ( const RV &rv2 );
168        //! Subtract  another variable from the current one
169        RV subt ( const RV &rv2 ) const;
170        //! Select only variables at indeces ind
171        RV subselect ( const ivec &ind ) const;
172        //! Select only variables at indeces ind
173        RV operator() ( const ivec &ind ) const {return subselect ( ind );};
174        //! Select from data vector starting at di1 to di2
175        RV operator() ( int di1, int di2 ) const {
176                ivec sz=cumsizes();
177                int i1=0;
178                while ( sz ( i1 ) <di1 ) i1++;
179                int i2=i1;
180                while ( sz ( i2 ) <di2 ) i2++;
181                return subselect ( linspace ( i1,i2 ) );
182        };
183        //! Shift \c time shifted by delta.
184        void t ( int delta );
185        //!@}
186
187        //!\name Relation to vectors
188        //!@{
189
190        //! generate \c str from rv, by expanding sizes
191        str tostr() const;
192        //! when this rv is a part of bigger rv, this function returns indeces of self in the data vector of the bigger crv.
193        //! Then, data can be copied via: data_of_this = cdata(ind);
194        ivec dataind ( const RV &crv ) const;
195        //! generate mutual indeces when copying data betwenn self and crv.
196        //! Data are copied via: data_of_this(selfi) = data_of_rv2(rv2i)
197        void dataind ( const RV &rv2, ivec &selfi, ivec &rv2i ) const;
198        //! Minimum time-offset
199        int mint () const {return min ( times );};
200        //!@}
201
202};
203
204
205//! Concat two random variables
206RV concat ( const RV &rv1, const RV &rv2 );
207
208//!Default empty RV that can be used as default argument
209extern RV RV0;
210
211//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
212
213class fnc :public bdmroot {
214protected:
215        //! Length of the output vector
216        int dimy;
217public:
218        //!default constructor
219        fnc ( ) {};
220        //! function evaluates numerical value of \f$f(x)\f$ at \f$x=\f$ \c cond
221        virtual vec eval ( const vec &cond ) {
222                return vec ( 0 );
223        };
224
225        //! function substitutes given value into an appropriate position
226        virtual void condition ( const vec &val ) {};
227
228        //! access function
229        int dimension() const{return dimy;}
230};
231
232class mpdf;
233
234//! Probability density function with numerical statistics, e.g. posterior density.
235
236class epdf :public bdmroot {
237protected:
238        //! dimension of the random variable
239        int dim;
240        //! Description of the random variable
241        RV rv;
242
243public:
244        /*! \name Constructors
245         Construction of each epdf should support two types of constructors:
246        \li empty constructor,
247        \li copy constructor,
248
249        The following constructors should be supported for convenience:
250        \li constructor followed by calling \c set_parameters()
251        \li constructor accepting random variables calling \c set_rv()
252
253         All internal data structures are constructed as empty. Their values (including sizes) will be set by method \c set_parameters(). This way references can be initialized in constructors.
254        @{*/
255        epdf() :dim ( 0 ),rv ( ) {};
256        epdf ( const epdf &e ) :dim ( e.dim ),rv ( e.rv ) {};
257        epdf ( const RV &rv0 ) {set_rv ( rv0 );};
258        void set_parameters ( int dim0 ) {dim=dim0;}
259        //!@}
260
261        //! \name Matematical Operations
262        //!@{
263
264        //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
265        virtual vec sample () const {it_error ( "not implemneted" );return vec ( 0 );};
266        //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
267        virtual mat sample_m ( int N ) const;
268        //! Compute log-probability of argument \c val
269        virtual double evallog ( const vec &val ) const {it_error ( "not implemneted" );return 0.0;};
270        //! Compute log-probability of multiple values argument \c val
271        virtual vec evallog_m ( const mat &Val ) const {
272                vec x ( Val.cols() );
273                for ( int i=0;i<Val.cols();i++ ) {x ( i ) =evallog ( Val.get_col ( i ) ) ;}
274                return x;
275        }
276        //! Return conditional density on the given RV, the remaining rvs will be in conditioning
277        virtual mpdf* condition ( const RV &rv ) const  {it_warning ( "Not implemented" ); return NULL;}
278        //! Return marginal density on the given RV, the remainig rvs are intergrated out
279        virtual epdf* marginal ( const RV &rv ) const {it_warning ( "Not implemented" ); return NULL;}
280        //! return expected value
281        virtual vec mean() const {it_error ( "not implemneted" );return vec ( 0 );};
282        //! return expected variance (not covariance!)
283        virtual vec variance() const {it_error ( "not implemneted" );return vec ( 0 );};
284        //! Lower and upper bounds of \c percentage % quantile, returns mean-2*sigma as default
285        virtual void qbounds ( vec &lb, vec &ub, double percentage=0.95 ) const {
286                vec mea=mean(); vec std=sqrt ( variance() );
287                lb = mea-2*std; ub=mea+2*std;
288        };
289        //!@}
290
291        //! \name Connection to other classes
292        //! Description of the random quantity via attribute \c rv is optional.
293        //! For operations such as sampling \c rv does not need to be set. However, for \c marginalization
294        //! and \c conditioning \c rv has to be set. NB:
295        //! @{
296
297        //!Name its rv
298        void set_rv ( const RV &rv0 ) {rv = rv0; }//it_assert_debug(isnamed(),""); };
299        //! True if rv is assigned
300        bool isnamed() const {bool b= ( dim==rv._dsize() );return b;}
301        //! Return name (fails when isnamed is false)
302        const RV& _rv() const {it_assert_debug ( isnamed(),"" ); return rv;}
303        //!@}
304
305        //! \name Access to attributes
306        //! @{
307
308        //! Size of the random variable
309        int dimension() const {return dim;}
310        //!@}
311
312};
313
314
315//! Conditional probability density, e.g. modeling some dependencies.
316//TODO Samplecond can be generalized
317
318class mpdf : public bdmroot {
319protected:
320        //!dimension of the condition
321        int dimc;
322        //! random variable in condition
323        RV rvc;
324        //! pointer to internal epdf
325        epdf* ep;
326public:
327        //! \name Constructors
328        //! @{
329
330        mpdf ( ) :dimc ( 0 ),rvc ( ) {};
331        //! copy constructor does not set pointer \c ep - has to be done in offsprings!
332        mpdf ( const mpdf &m ) :dimc ( m.dimc ),rvc ( m.rvc ) {};
333        //!@}
334
335        //! \name Matematical operations
336        //!@{
337
338        //! 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
339        virtual vec samplecond ( const vec &cond ) {
340                this->condition ( cond );
341                vec temp= ep->sample();
342                return temp;
343        };
344        //! 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
345        virtual mat samplecond_m ( const vec &cond, int N ) {
346                this->condition ( cond );
347                mat temp ( ep->dimension(),N ); vec smp ( ep->dimension() );
348                for ( int i=0;i<N;i++ ) {smp=ep->sample() ;temp.set_col ( i, smp );}
349                return temp;
350        };
351        //! Update \c ep so that it represents this mpdf conditioned on \c rvc = cond
352        virtual void condition ( const vec &cond ) {it_error ( "Not implemented" );};
353
354        //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
355        virtual double evallogcond ( const vec &dt, const vec &cond ) {
356                double tmp; this->condition ( cond );tmp = ep->evallog ( dt );          it_assert_debug ( std::isfinite ( tmp ),"Infinite value" ); return tmp;
357        };
358
359        //! Matrix version of evallogcond
360        virtual vec evallogcond_m ( const mat &Dt, const vec &cond ) {this->condition ( cond );return ep->evallog_m ( Dt );};
361
362        //! \name Access to attributes
363        //! @{
364
365        RV _rv() {return ep->_rv();}
366        RV _rvc() {it_assert_debug ( isnamed(),"" ); return rvc;}
367        int dimension() {return ep->dimension();}
368        int dimensionc() {return dimc;}
369        epdf& _epdf() {return *ep;}
370        epdf* _e() {return ep;}
371        //!@}
372
373        //! \name Connection to other objects
374        //!@{
375        void set_rvc ( const RV &rvc0 ) {rvc=rvc0;}
376        void set_rv ( const RV &rv0 ) {ep->set_rv ( rv0 );}
377        bool isnamed() {return ( ep->isnamed() ) && ( dimc==rvc._dsize() );}
378        //!@}
379};
380
381/*! \brief DataLink is a connection between two data vectors Up and Down
382
383Up can be longer than Down. Down must be fully present in Up (TODO optional)
384See chart:
385\dot
386digraph datalink {
387        node [shape=record];
388        subgraph cluster0 {
389                label = "Up";
390        up [label="<1>|<2>|<3>|<4>|<5>"];
391                color = "white"
392}
393        subgraph cluster1{
394                label = "Down";
395                labelloc = b;
396        down [label="<1>|<2>|<3>"];
397                color = "white"
398}
399    up:1 -> down:1;
400    up:3 -> down:2;
401    up:5 -> down:3;
402}
403\enddot
404
405*/
406class datalink {
407protected:
408        //! Remember how long val should be
409        int downsize;
410        //! Remember how long val of "Up" should be
411        int upsize;
412        //! val-to-val link, indeces of the upper val
413        ivec v2v_up;
414public:
415        //! Constructor
416        datalink () {};
417        datalink ( const RV &rv, const RV &rv_up ) {set_connection ( rv,rv_up );};
418        //! set connection, rv must be fully present in rv_up
419        void set_connection ( const RV &rv, const RV &rv_up ) {
420                downsize = rv._dsize();
421                upsize = rv_up._dsize();
422                v2v_up= ( rv.dataind ( rv_up ) );
423
424                it_assert_debug ( v2v_up.length() ==downsize,"rv is not fully in rv_up" );
425        }
426        //! set connection using indeces
427        void set_connection ( int ds, int us, const ivec &upind ) {
428                downsize = ds;
429                upsize = us;
430                v2v_up= upind;
431
432                it_assert_debug ( v2v_up.length() ==downsize,"rv is not fully in rv_up" );
433        }
434        //! Get val for myself from val of "Up"
435        vec pushdown ( const vec &val_up ) {
436                it_assert_debug ( upsize==val_up.length(),"Wrong val_up" );
437                return get_vec ( val_up,v2v_up );
438        }
439        //! Fill val of "Up" by my pieces
440        void pushup ( vec &val_up, const vec &val ) {
441                it_assert_debug ( downsize==val.length(),"Wrong val" );
442                it_assert_debug ( upsize==val_up.length(),"Wrong val_up" );
443                set_subvector ( val_up, v2v_up, val );
444        }
445};
446
447//! data link between
448class datalink_m2e: public datalink {
449protected:
450        //! Remember how long cond should be
451        int condsize;
452        //!upper_val-to-local_cond link, indeces of the upper val
453        ivec v2c_up;
454        //!upper_val-to-local_cond link, ideces of the local cond
455        ivec v2c_lo;
456
457public:
458        datalink_m2e() {};
459        //! Constructor
460        void set_connection ( const RV &rv,  const RV &rvc, const RV &rv_up ) {
461                datalink::set_connection ( rv,rv_up );
462                condsize=  rvc._dsize();
463                //establish v2c connection
464                rvc.dataind ( rv_up, v2c_lo, v2c_up );
465        }
466        //!Construct condition
467        vec get_cond ( const vec &val_up ) {
468                vec tmp ( condsize );
469                set_subvector ( tmp,v2c_lo,val_up ( v2c_up ) );
470                return tmp;
471        }
472        void pushup_cond ( vec &val_up, const vec &val, const vec &cond ) {
473                it_assert_debug ( downsize==val.length(),"Wrong val" );
474                it_assert_debug ( upsize==val_up.length(),"Wrong val_up" );
475                set_subvector ( val_up, v2v_up, val );
476                set_subvector ( val_up, v2c_up, cond );
477        }
478};
479//!DataLink is a connection between mpdf and its superordinate (Up)
480//! This class links
481class datalink_m2m: public datalink_m2e {
482protected:
483        //!cond-to-cond link, indeces of the upper cond
484        ivec c2c_up;
485        //!cond-to-cond link, indeces of the local cond
486        ivec c2c_lo;
487public:
488        //! Constructor
489        datalink_m2m() {};
490        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
491                datalink_m2e::set_connection ( rv, rvc, rv_up );
492                //establish c2c connection
493                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
494                it_assert_debug ( c2c_lo.length() +v2c_lo.length() ==condsize, "cond is not fully given" );
495        }
496        //! Get cond for myself from val and cond of "Up"
497        vec get_cond ( const vec &val_up, const vec &cond_up ) {
498                vec tmp ( condsize );
499                set_subvector ( tmp,v2c_lo,val_up ( v2c_up ) );
500                set_subvector ( tmp,c2c_lo,cond_up ( c2c_up ) );
501                return tmp;
502        }
503        //! Fill
504
505};
506
507/*!
508@brief Class for storing results (and semi-results) of an experiment
509
510This class abstracts logging of results from implementation. This class replaces direct logging of results (e.g. to files or to global variables) by calling methods of a logger. Specializations of this abstract class for specific storage method are designed.
511 */
512class logger : public bdmroot {
513protected:
514        //! RVs of all logged variables.
515        Array<RV> entries;
516        //! Names of logged quantities, e.g. names of algorithm variants
517        Array<string> names;
518public:
519        //!Default constructor
520        logger ( ) : entries ( 0 ),names ( 0 ) {}
521
522        //! returns an identifier which will be later needed for calling the \c logit() function
523        //! For empty RV it returns -1, this entry will be ignored by \c logit().
524        virtual int add ( const RV &rv, string prefix="" ) {
525                int id;
526                if ( rv._dsize() >0 ) {
527                        id=entries.length();
528                        names=concat ( names, prefix); // diff
529                        entries.set_length ( id+1,true );
530                        entries ( id ) = rv;
531                }
532                else { id =-1;}
533                return id; // identifier of the last entry
534        }
535
536        //! log this vector
537        virtual void logit ( int id, const vec &v ) =0;
538        //! log this double
539        virtual void logit ( int id, const double &d ) =0;
540
541        //! Shifts storage position for another time step.
542        virtual void step() =0;
543
544        //! Finalize storing information
545        virtual void finalize() {};
546
547        //! Initialize the storage
548        virtual void init() {};
549
550};
551
552/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
553
554*/
555class mepdf : public mpdf {
556public:
557        //!Default constructor
558        mepdf ( epdf* em ) :mpdf ( ) {ep= em ;};
559        mepdf (const epdf* em ) :mpdf ( ) {ep=const_cast<epdf*>( em );};
560        void condition ( const vec &cond ) {}
561};
562
563//!\brief Abstract composition of pdfs, will be used for specific classes
564//!this abstract class is common to epdf and mpdf
565class compositepdf {
566protected:
567        //!Number of mpdfs in the composite
568        int n;
569        //! Elements of composition
570        Array<mpdf*> mpdfs;
571public:
572        compositepdf ( Array<mpdf*> A0 ) : n ( A0.length() ), mpdfs ( A0 ) {};
573        //! find common rv, flag \param checkoverlap modifies whether overlaps are acceptable
574        RV getrv ( bool checkoverlap=false );
575        //! common rvc of all mpdfs is written to rvc
576        void setrvc ( const RV &rv, RV &rvc );
577};
578
579/*! \brief Abstract class for discrete-time sources of data.
580
581The 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.
582Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
583
584*/
585
586class DS : public bdmroot {
587protected:
588        int dtsize;
589        int utsize;
590        //!Description of data returned by \c getdata().
591        RV Drv;
592        //!Description of data witten by by \c write().
593        RV Urv; //
594        //! Remember its own index in Logger L
595        int L_dt, L_ut;
596public:
597        //! default constructors
598        DS() :Drv ( ),Urv ( ) {};
599        //! Returns full vector of observed data=[output, input]
600        virtual void getdata ( vec &dt ) {it_error ( "abstract class" );};
601        //! Returns data records at indeces.
602        virtual void getdata ( vec &dt, const ivec &indeces ) {it_error ( "abstract class" );};
603        //! Accepts action variable and schedule it for application.
604        virtual void write ( vec &ut ) {it_error ( "abstract class" );};
605        //! Accepts action variables at specific indeces
606        virtual void write ( vec &ut, const ivec &indeces ) {it_error ( "abstract class" );};
607
608        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
609        virtual void step() =0;
610
611        //! Register DS for logging into logger L
612        virtual void log_add ( logger &L ) {
613                it_assert_debug ( dtsize==Drv._dsize(),"" );
614                it_assert_debug ( utsize==Urv._dsize(),"" );
615
616                L_dt=L.add ( Drv,"" );
617                L_ut=L.add ( Urv,"" );
618        }
619        //! Register DS for logging into logger L
620        virtual void logit ( logger &L ) {
621                vec tmp ( Drv._dsize() +Urv._dsize() );
622                getdata ( tmp );
623                // d is first in getdata
624                L.logit ( L_dt,tmp.left ( Drv._dsize() ) );
625                // u follows after d in getdata
626                L.logit ( L_ut,tmp.mid ( Drv._dsize(), Urv._dsize() ) );
627        }
628        //!access function
629        virtual RV _drv() const {return concat ( Drv,Urv );}
630        //!access function
631        const RV& _urv() const {return Urv;}
632        //! set random rvariables
633        virtual void set_drv (const  RV &drv, const RV &urv) { Drv=drv;Urv=urv;}
634};
635
636/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
637
638This object represents exact or approximate evaluation of the Bayes rule:
639\f[
640f(\theta_t | d_1,\ldots,d_t) = \frac{f(y_t|\theta_t,\cdot) f(\theta_t|d_1,\ldots,d_{t-1})}{f(y_t|d_1,\ldots,d_{t-1})}
641\f]
642
643Access to the resulting posterior density is via function \c posterior().
644
645As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
646It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
647
648Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
649\f[
650f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
651\f]
652
653The value of \f$ c_t \f$ is set by function condition().
654
655*/
656
657class BM :public bdmroot {
658protected:
659        //! Random variable of the data (optional)
660        RV drv;
661        //!Logarithm of marginalized data likelihood.
662        double ll;
663        //!  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.
664        bool evalll;
665public:
666        //! \name Constructors
667        //! @{
668
669        BM () :ll ( 0 ),evalll ( true ), LIDs ( 4 ), LFlags(4) {
670                LIDs=-1;/*empty IDs*/ LFlags=0; LFlags(0)=1;/*log only mean*/};
671        BM ( const BM &B ) :  drv ( B.drv ), ll ( B.ll ), evalll ( B.evalll ) {}
672        //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
673        //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
674        virtual BM* _copy_ () const {return NULL;};
675        //!@}
676
677        //! \name Mathematical operations
678        //!@{
679
680        /*! \brief Incremental Bayes rule
681        @param dt vector of input data
682        */
683        virtual void bayes ( const vec &dt ) = 0;
684        //! Batch Bayes rule (columns of Dt are observations)
685        virtual void bayesB ( const mat &Dt );
686        //! Evaluates predictive log-likelihood of the given data record
687        //! I.e. marginal likelihood of the data with the posterior integrated out.
688        virtual double logpred ( const vec &dt ) const{it_error ( "Not implemented" );return 0.0;}
689        //! Matrix version of logpred
690        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;}
691
692        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
693        virtual epdf* epredictor ( ) const {it_error ( "Not implemented" );return NULL;};
694        //!Constructs a conditional density 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t})
695        virtual mpdf* predictor ( ) const {it_error ( "Not implemented" );return NULL;};
696        //!@}
697
698        //! \name Extension to conditional BM
699        //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
700        //! Alternatively, it can be used for automated connection to DS when the condition is observed
701        //!@{
702
703        //! Name of extension variable
704        RV rvc;
705        //! access function
706        const RV& _rvc() const {return rvc;}
707
708        //! Substitute \c val for \c rvc.
709        virtual void condition ( const vec &val ) {it_error ( "Not implemented!" );};
710
711        //!@}
712
713
714        //! \name Access to attributes
715        //!@{
716
717        const RV& _drv() const {return drv;}
718        void set_drv ( const RV &rv ) {drv=rv;}
719        void set_rv ( const RV &rv ) {const_cast<epdf&> ( posterior() ).set_rv ( rv );}
720        double _ll() const {return ll;}
721        void set_evalll ( bool evl0 ) {evalll=evl0;}
722        virtual const epdf& posterior() const =0;
723        virtual const epdf* _e() const =0;
724        //!@}
725
726        //! \name Logging of results
727        //!@{
728
729        //! Set boolean options from a string recognized are: "logbounds,logll"
730        virtual void set_options ( const string &opt ) {
731                LFlags(0)=1;
732                if ( opt.find ( "logbounds" ) !=string::npos ) {LFlags(1)=1; LFlags(2)=1;}
733                if ( opt.find ( "logll" ) !=string::npos ) {LFlags(3)=1;}
734        }
735        //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
736        ivec LIDs;
737
738        //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
739        ivec LFlags;
740        //! Add all logged variables to a logger
741        virtual void log_add ( logger &L, const string &name="" ) {
742                // internal
743                RV r;
744                if ( posterior().isnamed() ) {r=posterior()._rv();}
745                else{r=RV ( "est", posterior().dimension() );};
746
747                // Add mean value
748                if (LFlags(0)) LIDs ( 0 ) =L.add ( r,name+"mean_" );
749                if (LFlags(1)) LIDs ( 1 ) =L.add ( r,name+"lb_" );
750                if (LFlags(2)) LIDs ( 2 ) =L.add ( r,name+"ub_" );
751                if (LFlags(3)) LIDs ( 3 ) =L.add ( RV("ll",1),name ); //TODO: "local" RV
752        }
753        virtual void logit ( logger &L ) {
754                L.logit ( LIDs ( 0 ), posterior().mean() );
755                if ( LFlags(1) || LFlags(2)) { //if one of them is off, its LID==-1 and will not be stored
756                        vec ub,lb;
757                        posterior().qbounds ( lb,ub );
758                        L.logit ( LIDs ( 1 ), lb ); 
759                        L.logit ( LIDs ( 2 ), ub );
760                }
761                if (LFlags(3)) L.logit ( LIDs ( 3 ), ll );
762        }
763        //!@}
764};
765
766
767}; //namespace
768#endif // BM_H
Note: See TracBrowser for help on using the browser.