root/library/bdm/base/bdmbase.h @ 412

Revision 412, 26.2 kB (checked in by smidl, 15 years ago)

arx example for estimator workig

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