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

Revision 422, 26.1 kB (checked in by vbarta, 15 years ago)

RV partial cleanup: more arguments passed by reference, less inline functions, tests integrated into the testsuite

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