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

Revision 436, 26.3 kB (checked in by vbarta, 15 years ago)

moved egiw_test to testsuite (partially converted to a configurable test); added public method clearing RVs

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