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

Revision 384, 24.5 kB (checked in by mido, 15 years ago)

possibly broken?

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