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

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

merging works for merger_mx

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