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

Revision 461, 25.5 kB (checked in by vbarta, 15 years ago)

mpdf (& its dependencies) reformat: now using shared_ptr, moved virtual method bodies to .cpp

  • 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 "../shared_ptr.h"
21#include "user_info.h"
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
353private:
354  //! pointer to internal epdf
355  shared_ptr<epdf> shep;
356
357public:
358  //! \name Constructors
359  //! @{
360
361    mpdf():dimc(0), rvc() { }
362
363    mpdf(const mpdf &m):dimc(m.dimc), rvc(m.rvc), shep(m.shep) { }
364    //!@}
365
366    //! \name Matematical operations
367    //!@{
368
369    //! 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
370    virtual vec samplecond(const vec &cond);
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
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
381    //! Matrix version of evallogcond
382    virtual vec evallogcond_m(const mat &Dt, const vec &cond);
383
384    //! Array<vec> version of evallogcond
385    virtual vec evallogcond_m(const Array<vec> &Dt, const vec &cond);
386
387    //! \name Access to attributes
388    //! @{
389
390    RV _rv() { return shep->_rv(); }
391    RV _rvc() { it_assert_debug(isnamed(), ""); return rvc; }
392    int dimension() { return shep->dimension(); }
393    int dimensionc() { return dimc; }
394
395    epdf *e() { return shep.get(); }
396
397    void set_ep(shared_ptr<epdf> ep) { shep = ep; }
398
399    //! Load from structure with elements:
400    //!  \code
401    //! { rv = {class="RV", names=(...),}; // RV describing meaning of random variable
402    //!   rvc= {class="RV", names=(...),}; // RV describing meaning of random variable in condition
403    //!   // elements of offsprings
404    //! }
405    //! \endcode
406    //!@}
407    void from_setting(const Setting &set);
408    //!@}
409
410    //! \name Connection to other objects
411    //!@{
412    void set_rvc(const RV &rvc0) { rvc = rvc0; }
413    void set_rv(const RV &rv0) { shep->set_rv(rv0); }
414    bool isnamed() { return (shep->isnamed()) && (dimc == rvc._dsize()); }
415    //!@}
416};
417
418/*! \brief DataLink is a connection between two data vectors Up and Down
419
420Up can be longer than Down. Down must be fully present in Up (TODO optional)
421See chart:
422\dot
423digraph datalink {
424  node [shape=record];
425  subgraph cluster0 {
426    label = "Up";
427      up [label="<1>|<2>|<3>|<4>|<5>"];
428    color = "white"
429}
430  subgraph cluster1{
431    label = "Down";
432    labelloc = b;
433      down [label="<1>|<2>|<3>"];
434    color = "white"
435}
436    up:1 -> down:1;
437    up:3 -> down:2;
438    up:5 -> down:3;
439}
440\enddot
441
442*/
443class datalink
444{
445protected:
446  //! Remember how long val should be
447  int downsize;
448
449  //! Remember how long val of "Up" should be
450  int upsize;
451
452  //! val-to-val link, indices of the upper val
453  ivec v2v_up;
454
455public:
456  //! Constructor
457  datalink():downsize(0), upsize(0) { }
458  datalink(const RV &rv, const RV &rv_up) { set_connection(rv, rv_up); }
459
460  //! set connection, rv must be fully present in rv_up
461  void set_connection(const RV &rv, const RV &rv_up) {
462    downsize = rv._dsize();
463    upsize = rv_up._dsize();
464    v2v_up = rv.dataind(rv_up);
465
466    it_assert_debug(v2v_up.length() == downsize, "rv is not fully in rv_up");
467  }
468
469  //! set connection using indices
470  void set_connection(int ds, int us, const ivec &upind) {
471    downsize = ds;
472    upsize = us;
473    v2v_up = upind;
474
475    it_assert_debug(v2v_up.length() == downsize, "rv is not fully in rv_up");
476  }
477
478  //! Get val for myself from val of "Up"
479  vec pushdown(const vec &val_up) {
480    it_assert_debug(upsize == val_up.length(), "Wrong val_up");
481    return get_vec(val_up, v2v_up);
482  }
483
484  //! Fill val of "Up" by my pieces
485  void pushup(vec &val_up, const vec &val) {
486    it_assert_debug(downsize == val.length(), "Wrong val");
487    it_assert_debug(upsize == val_up.length(), "Wrong val_up");
488    set_subvector(val_up, v2v_up, val);
489  }
490};
491
492//! Data link with a condition.
493class datalink_m2e: public datalink
494{
495protected:
496  //! Remember how long cond should be
497  int condsize;
498
499  //!upper_val-to-local_cond link, indices of the upper val
500  ivec v2c_up;
501
502  //!upper_val-to-local_cond link, indices of the local cond
503  ivec v2c_lo;
504
505public:
506  //! Constructor
507  datalink_m2e():condsize(0) { }
508
509  void set_connection(const RV &rv, const RV &rvc, const RV &rv_up) {
510    datalink::set_connection(rv, rv_up);
511    condsize = rvc._dsize();
512    //establish v2c connection
513    rvc.dataind(rv_up, v2c_lo, v2c_up);
514  }
515
516  //!Construct condition
517  vec get_cond(const vec &val_up) {
518    vec tmp(condsize);
519    set_subvector(tmp, v2c_lo, val_up(v2c_up));
520    return tmp;
521  }
522
523  void pushup_cond(vec &val_up, const vec &val, const vec &cond) {
524    it_assert_debug(downsize == val.length(), "Wrong val");
525    it_assert_debug(upsize == val_up.length(), "Wrong val_up");
526    set_subvector(val_up, v2v_up, val);
527    set_subvector(val_up, v2c_up, cond);
528  }
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, indices of the upper cond
537  ivec c2c_up;
538  //!cond-to-cond link, indices of the local cond
539  ivec c2c_lo;
540
541public:
542  //! Constructor
543  datalink_m2m() {};
544  void set_connection(const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up) {
545    datalink_m2e::set_connection(rv, rvc, rv_up);
546    //establish c2c connection
547    rvc.dataind(rvc_up, c2c_lo, c2c_up);
548    it_assert_debug(c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given");
549  }
550
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 {
612public:
613        //!Default constructor
614        mepdf() { }
615
616        mepdf(shared_ptr<epdf> em) :mpdf ( ) { set_ep(em); dimc=0; }
617
618        void condition ( const vec &cond ) {}
619
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                set_ep(e);
630        }
631};
632UIREGISTER(mepdf);
633
634//!\brief Chain rule of pdfs - abstract part common for mprod and merger.
635//!this abstract class is common to epdf and mpdf
636//!\todo Think of better design - global functions rv=get_rv(Array<mpdf*> mpdfs); ??
637class compositepdf {
638protected:
639  //! Elements of composition
640  Array<mpdf*> mpdfs;
641  bool owning_mpdfs;
642public:
643        compositepdf():mpdfs(0){};
644        compositepdf(Array<mpdf*> A0, bool own=false){set_elements(A0,own);};
645        void set_elements(Array<mpdf*> A0, bool own=false) {mpdfs=A0;owning_mpdfs=own;};
646  //! find common rv, flag \param checkoverlap modifies whether overlaps are acceptable
647  RV getrv(bool checkoverlap = false);
648  //! common rvc of all mpdfs is written to rvc
649  void setrvc(const RV &rv, RV &rvc);
650  ~compositepdf(){if (owning_mpdfs) for(int i=0;i<mpdfs.length();i++){delete mpdfs(i);}};
651};
652
653/*! \brief Abstract class for discrete-time sources of data.
654
655The class abstracts operations of: (i) data aquisition, (ii) data-preprocessing, (iii) scaling of data, and (iv) data resampling from the task of estimation and control.
656Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
657
658*/
659
660class DS : public root
661{
662protected:
663  int dtsize;
664  int utsize;
665  //!Description of data returned by \c getdata().
666  RV Drv;
667  //!Description of data witten by by \c write().
668  RV Urv; //
669  //! Remember its own index in Logger L
670  int L_dt, L_ut;
671public:
672  //! default constructors
673  DS() : Drv(), Urv() {};
674  //! Returns full vector of observed data=[output, input]
675  virtual void getdata(vec &dt) {it_error("abstract class");};
676  //! Returns data records at indeces.
677  virtual void getdata(vec &dt, const ivec &indeces) {it_error("abstract class");};
678  //! Accepts action variable and schedule it for application.
679  virtual void write(vec &ut) {it_error("abstract class");};
680  //! Accepts action variables at specific indeces
681  virtual void write(vec &ut, const ivec &indeces) {it_error("abstract class");};
682
683  //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
684  virtual void step() = 0;
685
686  //! Register DS for logging into logger L
687  virtual void log_add(logger &L) {
688    it_assert_debug(dtsize == Drv._dsize(), "");
689    it_assert_debug(utsize == Urv._dsize(), "");
690
691    L_dt = L.add(Drv, "");
692    L_ut = L.add(Urv, "");
693  }
694  //! Register DS for logging into logger L
695  virtual void logit(logger &L) {
696    vec tmp(Drv._dsize() + Urv._dsize());
697    getdata(tmp);
698    // d is first in getdata
699    L.logit(L_dt, tmp.left(Drv._dsize()));
700    // u follows after d in getdata
701    L.logit(L_ut, tmp.mid(Drv._dsize(), Urv._dsize()));
702  }
703  //!access function
704  virtual RV _drv() const {return concat(Drv, Urv);}
705  //!access function
706  const RV& _urv() const {return Urv;}
707  //! set random rvariables
708  virtual void set_drv(const  RV &drv, const RV &urv) { Drv = drv; Urv = urv;}
709};
710
711/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
712
713This object represents exact or approximate evaluation of the Bayes rule:
714\f[
715f(\theta_t | d_1,\ldots,d_t) = \frac{f(y_t|\theta_t,\cdot) f(\theta_t|d_1,\ldots,d_{t-1})}{f(y_t|d_1,\ldots,d_{t-1})}
716\f]
717
718Access to the resulting posterior density is via function \c posterior().
719
720As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
721It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
722
723Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
724\f[
725f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
726\f]
727
728The value of \f$ c_t \f$ is set by function condition().
729
730*/
731
732class BM : public root
733{
734protected:
735  //! Random variable of the data (optional)
736  RV drv;
737  //!Logarithm of marginalized data likelihood.
738  double ll;
739  //!  If true, the filter will compute likelihood of the data record and store it in \c ll . Set to false if you want to save computational time.
740  bool evalll;
741public:
742  //! \name Constructors
743  //! @{
744
745  BM() : ll(0), evalll(true), LIDs(4), LFlags(4) {
746    LIDs = -1;/*empty IDs*/
747    LFlags = 0;
748    LFlags(0) = 1;/*log only mean*/
749  };
750  BM(const BM &B) :  drv(B.drv), ll(B.ll), evalll(B.evalll) {}
751  //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
752  //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
753  virtual BM* _copy_() const {return NULL;};
754  //!@}
755
756  //! \name Mathematical operations
757  //!@{
758
759  /*! \brief Incremental Bayes rule
760  @param dt vector of input data
761  */
762  virtual void bayes(const vec &dt) = 0;
763  //! Batch Bayes rule (columns of Dt are observations)
764  virtual void bayesB(const mat &Dt);
765  //! Evaluates predictive log-likelihood of the given data record
766  //! I.e. marginal likelihood of the data with the posterior integrated out.
767  virtual double logpred(const vec &dt) const {it_error("Not implemented"); return 0.0;}
768  //! Matrix version of logpred
769  vec logpred_m(const mat &dt) const {vec tmp(dt.cols()); for (int i = 0; i < dt.cols(); i++) {tmp(i) = logpred(dt.get_col(i));} return tmp;}
770
771  //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
772  virtual epdf* epredictor() const {it_error("Not implemented"); return NULL;};
773  //!Constructs a conditional density 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t})
774  virtual mpdf* predictor() const {it_error("Not implemented"); return NULL;};
775  //!@}
776
777  //! \name Extension to conditional BM
778  //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
779  //! Alternatively, it can be used for automated connection to DS when the condition is observed
780  //!@{
781
782  //! Name of extension variable
783  RV rvc;
784  //! access function
785  const RV& _rvc() const {return rvc;}
786
787  //! Substitute \c val for \c rvc.
788  virtual void condition(const vec &val) {it_error("Not implemented!");};
789
790  //!@}
791
792
793  //! \name Access to attributes
794  //!@{
795
796  const RV& _drv() const {return drv;}
797  void set_drv(const RV &rv) {drv = rv;}
798  void set_rv(const RV &rv) {const_cast<epdf&>(posterior()).set_rv(rv);}
799  double _ll() const {return ll;}
800  void set_evalll(bool evl0) {evalll = evl0;}
801  virtual const epdf& posterior() const = 0;
802  virtual const epdf* _e() const = 0;
803  //!@}
804
805  //! \name Logging of results
806  //!@{
807
808  //! Set boolean options from a string, recognized are: "logbounds,logll"
809  virtual void set_options(const string &opt) {
810    LFlags(0) = 1;
811    if (opt.find("logbounds") != string::npos) {LFlags(1) = 1; LFlags(2) = 1;}
812    if (opt.find("logll") != string::npos) {LFlags(3) = 1;}
813  }
814  //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
815  ivec LIDs;
816
817  //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
818  ivec LFlags;
819  //! Add all logged variables to a logger
820  virtual void log_add(logger &L, const string &name = "") {
821    // internal
822    RV r;
823    if (posterior().isnamed()) {r = posterior()._rv();}
824    else {r = RV("est", posterior().dimension());};
825
826    // Add mean value
827    if (LFlags(0)) LIDs(0) = L.add(r, name + "mean_");
828    if (LFlags(1)) LIDs(1) = L.add(r, name + "lb_");
829    if (LFlags(2)) LIDs(2) = L.add(r, name + "ub_");
830    if (LFlags(3)) LIDs(3) = L.add(RV("ll", 1), name);    //TODO: "local" RV
831  }
832  virtual void logit(logger &L) {
833    L.logit(LIDs(0), posterior().mean());
834    if (LFlags(1) || LFlags(2)) {  //if one of them is off, its LID==-1 and will not be stored
835      vec ub, lb;
836      posterior().qbounds(lb, ub);
837      L.logit(LIDs(1), lb);
838      L.logit(LIDs(2), ub);
839    }
840    if (LFlags(3)) L.logit(LIDs(3), ll);
841  }
842  //!@}
843};
844
845
846}; //namespace
847#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.