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

Revision 424, 26.2 kB (checked in by vbarta, 15 years ago)

moved datalink tests to testsuite, added default initialization to datalink classes

  • 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
464  //! Remember how long val of "Up" should be
465  int upsize;
466
467  //! val-to-val link, indices of the upper val
468  ivec v2v_up;
469
470public:
471  //! Constructor
472  datalink():downsize(0), upsize(0) { }
473  datalink(const RV &rv, const RV &rv_up) { set_connection(rv, rv_up); }
474
475  //! set connection, rv must be fully present in rv_up
476  void set_connection(const RV &rv, const RV &rv_up) {
477    downsize = rv._dsize();
478    upsize = rv_up._dsize();
479    v2v_up = rv.dataind(rv_up);
480
481    it_assert_debug(v2v_up.length() == downsize, "rv is not fully in rv_up");
482  }
483
484  //! set connection using indices
485  void set_connection(int ds, int us, const ivec &upind) {
486    downsize = ds;
487    upsize = us;
488    v2v_up = upind;
489
490    it_assert_debug(v2v_up.length() == downsize, "rv is not fully in rv_up");
491  }
492
493  //! Get val for myself from val of "Up"
494  vec pushdown(const vec &val_up) {
495    it_assert_debug(upsize == val_up.length(), "Wrong val_up");
496    return get_vec(val_up, v2v_up);
497  }
498
499  //! Fill val of "Up" by my pieces
500  void pushup(vec &val_up, const vec &val) {
501    it_assert_debug(downsize == val.length(), "Wrong val");
502    it_assert_debug(upsize == val_up.length(), "Wrong val_up");
503    set_subvector(val_up, v2v_up, val);
504  }
505};
506
507//! Data link with a condition.
508class datalink_m2e: public datalink
509{
510protected:
511  //! Remember how long cond should be
512  int condsize;
513
514  //!upper_val-to-local_cond link, indices of the upper val
515  ivec v2c_up;
516
517  //!upper_val-to-local_cond link, indices of the local cond
518  ivec v2c_lo;
519
520public:
521  //! Constructor
522  datalink_m2e():condsize(0) { }
523
524  void set_connection(const RV &rv, const RV &rvc, const RV &rv_up) {
525    datalink::set_connection(rv, rv_up);
526    condsize = rvc._dsize();
527    //establish v2c connection
528    rvc.dataind(rv_up, v2c_lo, v2c_up);
529  }
530
531  //!Construct condition
532  vec get_cond(const vec &val_up) {
533    vec tmp(condsize);
534    set_subvector(tmp, v2c_lo, val_up(v2c_up));
535    return tmp;
536  }
537
538  void pushup_cond(vec &val_up, const vec &val, const vec &cond) {
539    it_assert_debug(downsize == val.length(), "Wrong val");
540    it_assert_debug(upsize == val_up.length(), "Wrong val_up");
541    set_subvector(val_up, v2v_up, val);
542    set_subvector(val_up, v2c_up, cond);
543  }
544};
545
546//!DataLink is a connection between mpdf and its superordinate (Up)
547//! This class links
548class datalink_m2m: public datalink_m2e
549{
550protected:
551  //!cond-to-cond link, indices of the upper cond
552  ivec c2c_up;
553  //!cond-to-cond link, indices of the local cond
554  ivec c2c_lo;
555
556public:
557  //! Constructor
558  datalink_m2m() {};
559  void set_connection(const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up) {
560    datalink_m2e::set_connection(rv, rvc, rv_up);
561    //establish c2c connection
562    rvc.dataind(rvc_up, c2c_lo, c2c_up);
563    it_assert_debug(c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given");
564  }
565
566  //! Get cond for myself from val and cond of "Up"
567  vec get_cond(const vec &val_up, const vec &cond_up) {
568    vec tmp(condsize);
569    set_subvector(tmp, v2c_lo, val_up(v2c_up));
570    set_subvector(tmp, c2c_lo, cond_up(c2c_up));
571    return tmp;
572  }
573  //! Fill
574
575};
576
577/*!
578@brief Class for storing results (and semi-results) of an experiment
579
580This 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.
581 */
582class logger : public root
583{
584protected:
585  //! RVs of all logged variables.
586  Array<RV> entries;
587  //! Names of logged quantities, e.g. names of algorithm variants
588  Array<string> names;
589public:
590  //!Default constructor
591  logger() : entries(0), names(0) {}
592
593  //! returns an identifier which will be later needed for calling the \c logit() function
594  //! For empty RV it returns -1, this entry will be ignored by \c logit().
595  virtual int add(const RV &rv, string prefix = "") {
596    int id;
597    if (rv._dsize() > 0) {
598      id = entries.length();
599      names = concat(names, prefix); // diff
600      entries.set_length(id + 1, true);
601      entries(id) = rv;
602    }
603    else { id = -1;}
604    return id; // identifier of the last entry
605  }
606
607  //! log this vector
608  virtual void logit(int id, const vec &v) = 0;
609  //! log this double
610  virtual void logit(int id, const double &d) = 0;
611
612  //! Shifts storage position for another time step.
613  virtual void step() = 0;
614
615  //! Finalize storing information
616  virtual void finalize() {};
617
618  //! Initialize the storage
619  virtual void init() {};
620
621};
622
623/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
624
625*/
626class mepdf : public mpdf {
627        bool owning_ep; // flag trigers deleting ep by destructor
628public:
629        //!Default constructor
630        mepdf(){};
631        mepdf ( epdf* em, bool owning_ep0=false ) :mpdf ( ) {ep= em ;owning_ep=owning_ep0;dimc=0;};
632        mepdf (const epdf* em ) :mpdf ( ) {ep=const_cast<epdf*>( em );};
633        void condition ( const vec &cond ) {}
634        ~mepdf(){if (owning_ep) delete ep;}
635  //! Load from structure with elements:
636  //!  \code
637  //! { class = "mepdf",         
638  //!   epdfs = {class="epdfs",...}
639  //! }
640  //! \endcode
641  //!@}
642        void from_setting(const Setting &set){
643                epdf* e = UI::build<epdf>(set,"epdf");
644                ep=     e; 
645                owning_ep=true;
646        }
647};
648UIREGISTER(mepdf);
649
650//!\brief Chain rule of pdfs - abstract part common for mprod and merger.
651//!this abstract class is common to epdf and mpdf
652//!\todo Think of better design - global functions rv=get_rv(Array<mpdf*> mpdfs); ??
653class compositepdf {
654protected:
655  //! Elements of composition
656  Array<mpdf*> mpdfs;
657  bool owning_mpdfs;
658public:
659        compositepdf():mpdfs(0){};
660        compositepdf(Array<mpdf*> A0, bool own=false){set_elements(A0,own);};
661        void set_elements(Array<mpdf*> A0, bool own=false) {mpdfs=A0;owning_mpdfs=own;};
662  //! find common rv, flag \param checkoverlap modifies whether overlaps are acceptable
663  RV getrv(bool checkoverlap = false);
664  //! common rvc of all mpdfs is written to rvc
665  void setrvc(const RV &rv, RV &rvc);
666  ~compositepdf(){if (owning_mpdfs) for(int i=0;i<mpdfs.length();i++){delete mpdfs(i);}};
667};
668
669/*! \brief Abstract class for discrete-time sources of data.
670
671The 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.
672Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
673
674*/
675
676class DS : public root
677{
678protected:
679  int dtsize;
680  int utsize;
681  //!Description of data returned by \c getdata().
682  RV Drv;
683  //!Description of data witten by by \c write().
684  RV Urv; //
685  //! Remember its own index in Logger L
686  int L_dt, L_ut;
687public:
688  //! default constructors
689  DS() : Drv(), Urv() {};
690  //! Returns full vector of observed data=[output, input]
691  virtual void getdata(vec &dt) {it_error("abstract class");};
692  //! Returns data records at indeces.
693  virtual void getdata(vec &dt, const ivec &indeces) {it_error("abstract class");};
694  //! Accepts action variable and schedule it for application.
695  virtual void write(vec &ut) {it_error("abstract class");};
696  //! Accepts action variables at specific indeces
697  virtual void write(vec &ut, const ivec &indeces) {it_error("abstract class");};
698
699  //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
700  virtual void step() = 0;
701
702  //! Register DS for logging into logger L
703  virtual void log_add(logger &L) {
704    it_assert_debug(dtsize == Drv._dsize(), "");
705    it_assert_debug(utsize == Urv._dsize(), "");
706
707    L_dt = L.add(Drv, "");
708    L_ut = L.add(Urv, "");
709  }
710  //! Register DS for logging into logger L
711  virtual void logit(logger &L) {
712    vec tmp(Drv._dsize() + Urv._dsize());
713    getdata(tmp);
714    // d is first in getdata
715    L.logit(L_dt, tmp.left(Drv._dsize()));
716    // u follows after d in getdata
717    L.logit(L_ut, tmp.mid(Drv._dsize(), Urv._dsize()));
718  }
719  //!access function
720  virtual RV _drv() const {return concat(Drv, Urv);}
721  //!access function
722  const RV& _urv() const {return Urv;}
723  //! set random rvariables
724  virtual void set_drv(const  RV &drv, const RV &urv) { Drv = drv; Urv = urv;}
725};
726
727/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
728
729This object represents exact or approximate evaluation of the Bayes rule:
730\f[
731f(\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})}
732\f]
733
734Access to the resulting posterior density is via function \c posterior().
735
736As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
737It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
738
739Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
740\f[
741f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
742\f]
743
744The value of \f$ c_t \f$ is set by function condition().
745
746*/
747
748class BM : public root
749{
750protected:
751  //! Random variable of the data (optional)
752  RV drv;
753  //!Logarithm of marginalized data likelihood.
754  double ll;
755  //!  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.
756  bool evalll;
757public:
758  //! \name Constructors
759  //! @{
760
761  BM() : ll(0), evalll(true), LIDs(4), LFlags(4) {
762    LIDs = -1;/*empty IDs*/
763    LFlags = 0;
764    LFlags(0) = 1;/*log only mean*/
765  };
766  BM(const BM &B) :  drv(B.drv), ll(B.ll), evalll(B.evalll) {}
767  //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
768  //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
769  virtual BM* _copy_() const {return NULL;};
770  //!@}
771
772  //! \name Mathematical operations
773  //!@{
774
775  /*! \brief Incremental Bayes rule
776  @param dt vector of input data
777  */
778  virtual void bayes(const vec &dt) = 0;
779  //! Batch Bayes rule (columns of Dt are observations)
780  virtual void bayesB(const mat &Dt);
781  //! Evaluates predictive log-likelihood of the given data record
782  //! I.e. marginal likelihood of the data with the posterior integrated out.
783  virtual double logpred(const vec &dt) const {it_error("Not implemented"); return 0.0;}
784  //! Matrix version of logpred
785  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;}
786
787  //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
788  virtual epdf* epredictor() const {it_error("Not implemented"); return NULL;};
789  //!Constructs a conditional density 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t})
790  virtual mpdf* predictor() const {it_error("Not implemented"); return NULL;};
791  //!@}
792
793  //! \name Extension to conditional BM
794  //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
795  //! Alternatively, it can be used for automated connection to DS when the condition is observed
796  //!@{
797
798  //! Name of extension variable
799  RV rvc;
800  //! access function
801  const RV& _rvc() const {return rvc;}
802
803  //! Substitute \c val for \c rvc.
804  virtual void condition(const vec &val) {it_error("Not implemented!");};
805
806  //!@}
807
808
809  //! \name Access to attributes
810  //!@{
811
812  const RV& _drv() const {return drv;}
813  void set_drv(const RV &rv) {drv = rv;}
814  void set_rv(const RV &rv) {const_cast<epdf&>(posterior()).set_rv(rv);}
815  double _ll() const {return ll;}
816  void set_evalll(bool evl0) {evalll = evl0;}
817  virtual const epdf& posterior() const = 0;
818  virtual const epdf* _e() const = 0;
819  //!@}
820
821  //! \name Logging of results
822  //!@{
823
824  //! Set boolean options from a string, recognized are: "logbounds,logll"
825  virtual void set_options(const string &opt) {
826    LFlags(0) = 1;
827    if (opt.find("logbounds") != string::npos) {LFlags(1) = 1; LFlags(2) = 1;}
828    if (opt.find("logll") != string::npos) {LFlags(3) = 1;}
829  }
830  //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
831  ivec LIDs;
832
833  //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
834  ivec LFlags;
835  //! Add all logged variables to a logger
836  virtual void log_add(logger &L, const string &name = "") {
837    // internal
838    RV r;
839    if (posterior().isnamed()) {r = posterior()._rv();}
840    else {r = RV("est", posterior().dimension());};
841
842    // Add mean value
843    if (LFlags(0)) LIDs(0) = L.add(r, name + "mean_");
844    if (LFlags(1)) LIDs(1) = L.add(r, name + "lb_");
845    if (LFlags(2)) LIDs(2) = L.add(r, name + "ub_");
846    if (LFlags(3)) LIDs(3) = L.add(RV("ll", 1), name);    //TODO: "local" RV
847  }
848  virtual void logit(logger &L) {
849    L.logit(LIDs(0), posterior().mean());
850    if (LFlags(1) || LFlags(2)) {  //if one of them is off, its LID==-1 and will not be stored
851      vec ub, lb;
852      posterior().qbounds(lb, ub);
853      L.logit(LIDs(1), lb);
854      L.logit(LIDs(2), ub);
855    }
856    if (LFlags(3)) L.logit(LIDs(3), ll);
857  }
858  //!@}
859};
860
861
862}; //namespace
863#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.