root/bdm/stat/libBM.h @ 256

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

uibuilder works (again)

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