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

Revision 507, 27.3 kB (checked in by vbarta, 15 years ago)

removed class compositepdf; keeping mpdfs of mprod and merger_base in shared pointers

  • 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{
37        public:
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{
88        protected:
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
98        private:
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);
102        public:
103                //! \name Constructors
104                //!@{
105
106                //! Full constructor
107                RV (const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times) {
108                        init (in_names, in_sizes, in_times);
109                }
110
111                //! Constructor with times=0
112                RV (const Array<std::string> &in_names, const ivec &in_sizes) {
113                        init (in_names, in_sizes, zeros_i (in_names.length()));
114                }
115
116                //! Constructor with sizes=1, times=0
117                RV (const Array<std::string> &in_names) {
118                        init (in_names, ones_i (in_names.length()), zeros_i (in_names.length()));
119                }
120
121                //! Constructor of empty RV
122                RV() : dsize (0), len (0), ids (0), times (0) {}
123                //! Constructor of a single RV with given id
124                RV (string name, int sz, int tm = 0);
125                //!@}
126
127                //! \name Access functions
128                //!@{
129
130                //! State output, e.g. for debugging.
131                friend std::ostream &operator<< (std::ostream &os, const RV &rv);
132
133                int _dsize() const {
134                        return dsize;
135                }
136
137                //! Recount size of the corresponding data vector
138                int countsize() const;
139                ivec cumsizes() const;
140                int length() const {
141                        return len;
142                }
143                int id (int at) const {
144                        return ids (at);
145                }
146                int size (int at) const {
147                        return RV_SIZES (ids (at));
148                }
149                int time (int at) const {
150                        return times (at);
151                }
152                std::string name (int at) const {
153                        return RV_NAMES (ids (at));
154                }
155                void set_time (int at, int time0) {
156                        times (at) = time0;
157                }
158                //!@}
159
160                //TODO why not inline and later??
161
162                //! \name Algebra on Random Variables
163                //!@{
164
165                //! Find indices of self in another rv, \return ivec of the same size as self.
166                ivec findself (const RV &rv2) const;
167                //! Compare if \c rv2 is identical to this \c RV
168                bool equal (const RV &rv2) const;
169                //! Add (concat) another variable to the current one, \return true if all rv2 were added, false if rv2 is in conflict
170                bool add (const RV &rv2);
171                //! Subtract  another variable from the current one
172                RV subt (const RV &rv2) const;
173                //! Select only variables at indices ind
174                RV subselect (const ivec &ind) const;
175
176                //! Select only variables at indices ind
177                RV operator() (const ivec &ind) const {
178                        return subselect (ind);
179                }
180
181                //! Select from data vector starting at di1 to di2
182                RV operator() (int di1, int di2) const;
183
184                //! Shift \c time by delta.
185                void t (int delta);
186                //!@}
187
188                //!\name Relation to vectors
189                //!@{
190
191                //! generate \c str from rv, by expanding sizes TODO to_string..
192                str tostr() const;
193                //! when this rv is a part of bigger rv, this function returns indices of self in the data vector of the bigger crv.
194                //! Then, data can be copied via: data_of_this = cdata(ind);
195                ivec dataind (const RV &crv) const;
196                //! generate mutual indices when copying data between self and crv.
197                //! Data are copied via: data_of_this(selfi) = data_of_rv2(rv2i)
198                void dataind (const RV &rv2, ivec &selfi, ivec &rv2i) const;
199                //! Minimum time-offset
200                int mint() const {
201                        return min (times);
202                }
203                //!@}
204
205                // TODO aktualizovat dle soucasneho UI
206                /*! \brief UI for class RV (description of data vectors)
207
208                \code
209                rv = {
210                  type = "rv"; //identifier of the description
211                  // UNIQUE IDENTIFIER same names = same variable
212                  names = ["a", "b", "c", ...];   // which will be used e.g. in loggers
213
214                  //optional arguments
215                  sizes = [1, 2, 3, ...];         // (optional) default = ones()
216                  times = [-1, -2, 0, ...];       // time shifts with respect to current time (optional) default = zeros()
217                }
218                \endcode
219                */
220                void from_setting (const Setting &set);
221
222                // TODO dodelat void to_setting( Setting &set ) const;
223
224                //! Invalidate all named RVs. Use before initializing any RV instances, with care...
225                static void clear_all();
226};
227UIREGISTER (RV);
228
229//! Concat two random variables
230RV concat (const RV &rv1, const RV &rv2);
231
232//!Default empty RV that can be used as default argument
233extern RV RV0;
234
235//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
236
237class fnc : public root
238{
239        protected:
240                //! Length of the output vector
241                int dimy;
242        public:
243                //!default constructor
244                fnc() {};
245                //! function evaluates numerical value of \f$f(x)\f$ at \f$x=\f$ \c cond
246                virtual vec eval (const vec &cond) {
247                        return vec (0);
248                };
249
250                //! function substitutes given value into an appropriate position
251                virtual void condition (const vec &val) {};
252
253                //! access function
254                int dimension() const {
255                        return dimy;
256                }
257};
258
259class mpdf;
260
261//! Probability density function with numerical statistics, e.g. posterior density.
262
263class epdf : public root
264{
265        protected:
266                //! dimension of the random variable
267                int dim;
268                //! Description of the random variable
269                RV rv;
270
271        public:
272                /*! \name Constructors
273                 Construction of each epdf should support two types of constructors:
274                \li empty constructor,
275                \li copy constructor,
276
277                The following constructors should be supported for convenience:
278                \li constructor followed by calling \c set_parameters()
279                \li constructor accepting random variables calling \c set_rv()
280
281                 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.
282                @{*/
283                epdf() : dim (0), rv() {};
284                epdf (const epdf &e) : dim (e.dim), rv (e.rv) {};
285                epdf (const RV &rv0) : dim (rv0._dsize()) {
286                        set_rv (rv0);
287                };
288                void set_parameters (int dim0) {
289                        dim = dim0;
290                }
291                //!@}
292
293                //! \name Matematical Operations
294                //!@{
295
296                //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
297                virtual vec sample() const {
298                        it_error ("not implemented");
299                        return vec (0);
300                }
301
302                //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
303                virtual mat sample_m (int N) const;
304
305                //! Compute log-probability of argument \c val
306                //! In case the argument is out of suport return -Infinity
307                virtual double evallog (const vec &val) const {
308                        it_error ("not implemented");
309                        return 0.0;
310                }
311
312                //! Compute log-probability of multiple values argument \c val
313                virtual vec evallog_m (const mat &Val) const;
314
315                //! Compute log-probability of multiple values argument \c val
316                virtual vec evallog_m (const Array<vec> &Avec) const;
317
318                //! Return conditional density on the given RV, the remaining rvs will be in conditioning
319                virtual shared_ptr<mpdf> condition (const RV &rv) const;
320
321                //! Return marginal density on the given RV, the remainig rvs are intergrated out
322                virtual shared_ptr<epdf> marginal (const RV &rv) const;
323
324                //! return expected value
325                virtual vec mean() const {
326                        it_error ("not implemneted");
327                        return vec (0);
328                };
329
330                //! return expected variance (not covariance!)
331                virtual vec variance() const {
332                        it_error ("not implemneted");
333                        return vec (0);
334                };
335                //! Lower and upper bounds of \c percentage % quantile, returns mean-2*sigma as default
336                virtual void qbounds (vec &lb, vec &ub, double percentage = 0.95) const {
337                        vec mea = mean();
338                        vec std = sqrt (variance());
339                        lb = mea - 2 * std;
340                        ub = mea + 2 * std;
341                };
342                //!@}
343
344                //! \name Connection to other classes
345                //! Description of the random quantity via attribute \c rv is optional.
346                //! For operations such as sampling \c rv does not need to be set. However, for \c marginalization
347                //! and \c conditioning \c rv has to be set. NB:
348                //! @{
349
350                //!Name its rv
351                void set_rv (const RV &rv0) {
352                        rv = rv0;
353                }   //it_assert_debug(isnamed(),""); };
354                //! True if rv is assigned
355                bool isnamed() const {
356                        bool b = (dim == rv._dsize());
357                        return b;
358                }
359                //! Return name (fails when isnamed is false)
360                const RV& _rv() const {
361                        it_assert_debug (isnamed(), "");
362                        return rv;
363                }
364                //!@}
365
366                //! \name Access to attributes
367                //! @{
368
369                //! Size of the random variable
370                int dimension() const {
371                        return dim;
372                }
373                //! Load from structure with elements:
374                //!  \code
375                //! { rv = {class="RV", names=(...),}; // RV describing meaning of random variable
376                //!   // elements of offsprings
377                //! }
378                //! \endcode
379                //!@}
380                void from_setting (const Setting &set) {
381                        RV* r = UI::build<RV> (set, "rv");
382                        if (r) {
383                                set_rv (*r);
384                                delete r;
385                        }
386                }
387
388};
389
390
391//! Conditional probability density, e.g. modeling some dependencies.
392//TODO Samplecond can be generalized
393class mpdf : public root
394{
395        protected:
396                //!dimension of the condition
397                int dimc;
398                //! random variable in condition
399                RV rvc;
400        private:
401                //! internal epdf, used only as cache to avoid virtual calls of \c _rv() and \c _dimension()
402                epdf* ep;
403
404        protected:
405                void set_ep (epdf &iepdf) {
406                        ep = &iepdf;
407                }
408                void set_ep (epdf *iepdfp) {
409                        ep = iepdfp;
410                }
411
412        public:
413                //! \name Constructors
414                //! @{
415
416                mpdf() : dimc (0), rvc(), ep (NULL) { }
417
418                mpdf (const mpdf &m) : dimc (m.dimc), rvc (m.rvc), ep (m.ep) { }
419                //!@}
420
421                //! \name Matematical operations
422                //!@{
423
424                //! 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
425                virtual vec samplecond (const vec &cond) {it_error ("Not implemented");return vec (0);};
426
427                //! 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
428                virtual mat samplecond_m (const vec &cond, int N) {
429                        mat M(dimension(), N);
430                        for(int i=0;i<N;i++){M.set_col(i, samplecond(cond));}
431                        return M;
432                }
433
434
435                //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
436                virtual double evallogcond (const vec &dt, const vec &cond) {it_error ("Not implemented");return 0.0;}
437
438                //! Matrix version of evallogcond
439                virtual vec evallogcond_m (const mat &Dt, const vec &cond) {
440                        vec v(Dt.cols());
441                        for(int i=0;i<Dt.cols();i++){v(i)= evallogcond(Dt.get_col(i),cond);}
442                        return v;
443                }
444
445                //! Array<vec> version of evallogcond
446                virtual vec evallogcond_m (const Array<vec> &Dt, const vec &cond) {it_error ("Not implemented");return vec (0);}
447
448                //! \name Access to attributes
449                //! @{
450
451                RV _rv() const {
452                        return ep->_rv();
453                }
454                RV _rvc() {
455                        it_assert_debug (isnamed(), "");
456                        return rvc;
457                }
458                int dimension() {
459                        return ep->dimension();
460                }
461                int dimensionc() {
462                        return dimc;
463                }
464
465                //! Load from structure with elements:
466                //!  \code
467                //! { class = "mpdf_offspring",
468                //!   rv = {class="RV", names=(...),}; // RV describing meaning of random variable
469                //!   rvc= {class="RV", names=(...),}; // RV describing meaning of random variable in condition
470                //!   // elements of offsprings
471                //! }
472                //! \endcode
473                //!@}
474                void from_setting (const Setting &set);
475                //!@}
476
477                //! \name Connection to other objects
478                //!@{
479                void set_rvc (const RV &rvc0) {
480                        rvc = rvc0;
481                }
482                void set_rv (const RV &rv0) {
483                        ep->set_rv (rv0);
484                }
485                bool isnamed() {
486                        return (ep->isnamed()) && (dimc == rvc._dsize());
487                }
488                //!@}
489};
490
491template <class EPDF>
492class mpdf_internal: public mpdf
493{
494        protected :
495                EPDF iepdf;
496        public:
497                //! constructor
498                mpdf_internal() : mpdf(), iepdf() {set_ep (iepdf);}
499                //! Update \c iepdf so that it represents this mpdf conditioned on \c rvc = cond
500                //! This function provides convenient reimplementation in offsprings
501                virtual void condition (const vec &cond) {
502                        it_error ("Not implemented");
503                };
504                //!access function to iepdf
505                EPDF& e() {return iepdf;}
506
507                //! Reimplements samplecond using \c condition()
508                vec samplecond (const vec &cond);
509                //! Reimplements evallogcond using \c condition()
510                double evallogcond (const vec &val, const vec &cond);
511                //! Efficient version of evallogcond for matrices
512                virtual vec evallogcond_m (const mat &Dt, const vec &cond);
513                //! Efficient version of evallogcond for Array<vec>
514                virtual vec evallogcond_m (const Array<vec> &Dt, const vec &cond);
515                //! Efficient version of samplecond
516                virtual mat samplecond_m (const vec &cond, int N);
517};
518
519/*! \brief DataLink is a connection between two data vectors Up and Down
520
521Up can be longer than Down. Down must be fully present in Up (TODO optional)
522See chart:
523\dot
524digraph datalink {
525  node [shape=record];
526  subgraph cluster0 {
527    label = "Up";
528      up [label="<1>|<2>|<3>|<4>|<5>"];
529    color = "white"
530}
531  subgraph cluster1{
532    label = "Down";
533    labelloc = b;
534      down [label="<1>|<2>|<3>"];
535    color = "white"
536}
537    up:1 -> down:1;
538    up:3 -> down:2;
539    up:5 -> down:3;
540}
541\enddot
542
543*/
544class datalink
545{
546        protected:
547                //! Remember how long val should be
548                int downsize;
549
550                //! Remember how long val of "Up" should be
551                int upsize;
552
553                //! val-to-val link, indices of the upper val
554                ivec v2v_up;
555
556        public:
557                //! Constructor
558                datalink() : downsize (0), upsize (0) { }
559                datalink (const RV &rv, const RV &rv_up) {
560                        set_connection (rv, rv_up);
561                }
562
563                //! set connection, rv must be fully present in rv_up
564                void set_connection (const RV &rv, const RV &rv_up) {
565                        downsize = rv._dsize();
566                        upsize = rv_up._dsize();
567                        v2v_up = rv.dataind (rv_up);
568
569                        it_assert_debug (v2v_up.length() == downsize, "rv is not fully in rv_up");
570                }
571
572                //! set connection using indices
573                void set_connection (int ds, int us, const ivec &upind) {
574                        downsize = ds;
575                        upsize = us;
576                        v2v_up = upind;
577
578                        it_assert_debug (v2v_up.length() == downsize, "rv is not fully in rv_up");
579                }
580
581                //! Get val for myself from val of "Up"
582                vec pushdown (const vec &val_up) {
583                        it_assert_debug (upsize == val_up.length(), "Wrong val_up");
584                        return get_vec (val_up, v2v_up);
585                }
586
587                //! Fill val of "Up" by my pieces
588                void pushup (vec &val_up, const vec &val) {
589                        it_assert_debug (downsize == val.length(), "Wrong val");
590                        it_assert_debug (upsize == val_up.length(), "Wrong val_up");
591                        set_subvector (val_up, v2v_up, val);
592                }
593};
594
595//! Data link with a condition.
596class datalink_m2e: public datalink
597{
598        protected:
599                //! Remember how long cond should be
600                int condsize;
601
602                //!upper_val-to-local_cond link, indices of the upper val
603                ivec v2c_up;
604
605                //!upper_val-to-local_cond link, indices of the local cond
606                ivec v2c_lo;
607
608        public:
609                //! Constructor
610                datalink_m2e() : condsize (0) { }
611
612                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up) {
613                        datalink::set_connection (rv, rv_up);
614                        condsize = rvc._dsize();
615                        //establish v2c connection
616                        rvc.dataind (rv_up, v2c_lo, v2c_up);
617                }
618
619                //!Construct condition
620                vec get_cond (const vec &val_up) {
621                        vec tmp (condsize);
622                        set_subvector (tmp, v2c_lo, val_up (v2c_up));
623                        return tmp;
624                }
625
626                void pushup_cond (vec &val_up, const vec &val, const vec &cond) {
627                        it_assert_debug (downsize == val.length(), "Wrong val");
628                        it_assert_debug (upsize == val_up.length(), "Wrong val_up");
629                        set_subvector (val_up, v2v_up, val);
630                        set_subvector (val_up, v2c_up, cond);
631                }
632};
633
634//!DataLink is a connection between mpdf and its superordinate (Up)
635//! This class links
636class datalink_m2m: public datalink_m2e
637{
638        protected:
639                //!cond-to-cond link, indices of the upper cond
640                ivec c2c_up;
641                //!cond-to-cond link, indices of the local cond
642                ivec c2c_lo;
643
644        public:
645                //! Constructor
646                datalink_m2m() {};
647                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up) {
648                        datalink_m2e::set_connection (rv, rvc, rv_up);
649                        //establish c2c connection
650                        rvc.dataind (rvc_up, c2c_lo, c2c_up);
651                        it_assert_debug (c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given");
652                }
653
654                //! Get cond for myself from val and cond of "Up"
655                vec get_cond (const vec &val_up, const vec &cond_up) {
656                        vec tmp (condsize);
657                        set_subvector (tmp, v2c_lo, val_up (v2c_up));
658                        set_subvector (tmp, c2c_lo, cond_up (c2c_up));
659                        return tmp;
660                }
661                //! Fill
662
663};
664
665/*!
666@brief Class for storing results (and semi-results) of an experiment
667
668This 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.
669 */
670class logger : public root
671{
672        protected:
673                //! RVs of all logged variables.
674                Array<RV> entries;
675                //! Names of logged quantities, e.g. names of algorithm variants
676                Array<string> names;
677        public:
678                //!Default constructor
679                logger() : entries (0), names (0) {}
680
681                //! returns an identifier which will be later needed for calling the \c logit() function
682                //! For empty RV it returns -1, this entry will be ignored by \c logit().
683                virtual int add (const RV &rv, string prefix = "") {
684                        int id;
685                        if (rv._dsize() > 0) {
686                                id = entries.length();
687                                names = concat (names, prefix);   // diff
688                                entries.set_length (id + 1, true);
689                                entries (id) = rv;
690                        } else {
691                                id = -1;
692                        }
693                        return id; // identifier of the last entry
694                }
695
696                //! log this vector
697                virtual void logit (int id, const vec &v) = 0;
698                //! log this double
699                virtual void logit (int id, const double &d) = 0;
700
701                //! Shifts storage position for another time step.
702                virtual void step() = 0;
703
704                //! Finalize storing information
705                virtual void finalize() {};
706
707                //! Initialize the storage
708                virtual void init() {};
709
710};
711
712/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
713
714*/
715class mepdf : public mpdf
716{
717
718                shared_ptr<epdf> iepdf;
719        public:
720                //!Default constructor
721                mepdf() { }
722
723                mepdf (shared_ptr<epdf> em) {
724                        iepdf = em;
725                        set_ep (*iepdf.get());
726                        dimc = 0;
727                }
728
729                //! empty
730                vec samplecond(const vec &cond){return iepdf->sample();}
731                double evallogcond(const vec &val, const vec &cond){return iepdf->evallog(val);}
732
733                //! Load from structure with elements:
734                //!  \code
735                //! { class = "mepdf",
736                //!   epdf = {class="epdf_offspring",...}
737                //! }
738                //! \endcode
739                //!@}
740                void from_setting (const Setting &set);
741};
742UIREGISTER (mepdf);
743
744//! \brief Combines RVs from a list of mpdfs to a single one.
745RV get_composite_rv ( const Array<shared_ptr<mpdf> > &mpdfs, bool checkoverlap = false );
746
747/*! \brief Abstract class for discrete-time sources of data.
748
749The 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.
750Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
751
752*/
753
754class DS : public root
755{
756        protected:
757                int dtsize;
758                int utsize;
759                //!Description of data returned by \c getdata().
760                RV Drv;
761                //!Description of data witten by by \c write().
762                RV Urv; //
763                //! Remember its own index in Logger L
764                int L_dt, L_ut;
765        public:
766                //! default constructors
767                DS() : Drv(), Urv() {};
768                //! Returns full vector of observed data=[output, input]
769                virtual void getdata (vec &dt) {
770                        it_error ("abstract class");
771                };
772                //! Returns data records at indeces.
773                virtual void getdata (vec &dt, const ivec &indeces) {
774                        it_error ("abstract class");
775                };
776                //! Accepts action variable and schedule it for application.
777                virtual void write (vec &ut) {
778                        it_error ("abstract class");
779                };
780                //! Accepts action variables at specific indeces
781                virtual void write (vec &ut, const ivec &indeces) {
782                        it_error ("abstract class");
783                };
784
785                //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
786                virtual void step() = 0;
787
788                //! Register DS for logging into logger L
789                virtual void log_add (logger &L) {
790                        it_assert_debug (dtsize == Drv._dsize(), "");
791                        it_assert_debug (utsize == Urv._dsize(), "");
792
793                        L_dt = L.add (Drv, "");
794                        L_ut = L.add (Urv, "");
795                }
796                //! Register DS for logging into logger L
797                virtual void logit (logger &L) {
798                        vec tmp (Drv._dsize() + Urv._dsize());
799                        getdata (tmp);
800                        // d is first in getdata
801                        L.logit (L_dt, tmp.left (Drv._dsize()));
802                        // u follows after d in getdata
803                        L.logit (L_ut, tmp.mid (Drv._dsize(), Urv._dsize()));
804                }
805                //!access function
806                virtual RV _drv() const {
807                        return concat (Drv, Urv);
808                }
809                //!access function
810                const RV& _urv() const {
811                        return Urv;
812                }
813                //! set random rvariables
814                virtual void set_drv (const  RV &drv, const RV &urv) {
815                        Drv = drv;
816                        Urv = urv;
817                }
818};
819
820/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
821
822This object represents exact or approximate evaluation of the Bayes rule:
823\f[
824f(\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})}
825\f]
826
827Access to the resulting posterior density is via function \c posterior().
828
829As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
830It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
831
832Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
833\f[
834f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
835\f]
836
837The value of \f$ c_t \f$ is set by function condition().
838
839*/
840
841class BM : public root
842{
843        protected:
844                //! Random variable of the data (optional)
845                RV drv;
846                //!Logarithm of marginalized data likelihood.
847                double ll;
848                //!  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.
849                bool evalll;
850        public:
851                //! \name Constructors
852                //! @{
853
854                BM() : ll (0), evalll (true), LIDs (4), LFlags (4) {
855                        LIDs = -1;/*empty IDs*/
856                        LFlags = 0;
857                        LFlags (0) = 1;  /*log only mean*/
858                };
859                BM (const BM &B) :  drv (B.drv), ll (B.ll), evalll (B.evalll) {}
860                //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
861                //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
862                virtual BM* _copy_() const {
863                        return NULL;
864                };
865                //!@}
866
867                //! \name Mathematical operations
868                //!@{
869
870                /*! \brief Incremental Bayes rule
871                @param dt vector of input data
872                */
873                virtual void bayes (const vec &dt) = 0;
874                //! Batch Bayes rule (columns of Dt are observations)
875                virtual void bayesB (const mat &Dt);
876                //! Evaluates predictive log-likelihood of the given data record
877                //! I.e. marginal likelihood of the data with the posterior integrated out.
878                virtual double logpred (const vec &dt) const {
879                        it_error ("Not implemented");
880                        return 0.0;
881                }
882                //! Matrix version of logpred
883                vec logpred_m (const mat &dt) const {
884                        vec tmp (dt.cols());
885                        for (int i = 0; i < dt.cols(); i++) {
886                                tmp (i) = logpred (dt.get_col (i));
887                        }
888                        return tmp;
889                }
890
891                //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
892                virtual epdf* epredictor() const {
893                        it_error ("Not implemented");
894                        return NULL;
895                };
896                //!Constructs a conditional density 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t})
897                virtual mpdf* predictor() const {
898                        it_error ("Not implemented");
899                        return NULL;
900                };
901                //!@}
902
903                //! \name Extension to conditional BM
904                //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
905                //! Alternatively, it can be used for automated connection to DS when the condition is observed
906                //!@{
907
908                //! Name of extension variable
909                RV rvc;
910                //! access function
911                const RV& _rvc() const {
912                        return rvc;
913                }
914
915                //! Substitute \c val for \c rvc.
916                virtual void condition (const vec &val) {
917                        it_error ("Not implemented!");
918                };
919
920                //!@}
921
922
923                //! \name Access to attributes
924                //!@{
925
926                const RV& _drv() const {
927                        return drv;
928                }
929                void set_drv (const RV &rv) {
930                        drv = rv;
931                }
932                void set_rv (const RV &rv) {
933                        const_cast<epdf&> (posterior()).set_rv (rv);
934                }
935                double _ll() const {
936                        return ll;
937                }
938                void set_evalll (bool evl0) {
939                        evalll = evl0;
940                }
941                virtual const epdf& posterior() const = 0;
942                virtual const epdf* _e() const = 0;
943                //!@}
944
945                //! \name Logging of results
946                //!@{
947
948                //! Set boolean options from a string, recognized are: "logbounds,logll"
949                virtual void set_options (const string &opt) {
950                        LFlags (0) = 1;
951                        if (opt.find ("logbounds") != string::npos) {
952                                LFlags (1) = 1;
953                                LFlags (2) = 1;
954                        }
955                        if (opt.find ("logll") != string::npos) {
956                                LFlags (3) = 1;
957                        }
958                }
959                //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
960                ivec LIDs;
961
962                //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
963                ivec LFlags;
964                //! Add all logged variables to a logger
965                virtual void log_add (logger &L, const string &name = "") {
966                        // internal
967                        RV r;
968                        if (posterior().isnamed()) {
969                                r = posterior()._rv();
970                        } else {
971                                r = RV ("est", posterior().dimension());
972                        };
973
974                        // Add mean value
975                        if (LFlags (0)) LIDs (0) = L.add (r, name + "mean_");
976                        if (LFlags (1)) LIDs (1) = L.add (r, name + "lb_");
977                        if (LFlags (2)) LIDs (2) = L.add (r, name + "ub_");
978                        if (LFlags (3)) LIDs (3) = L.add (RV ("ll", 1), name);              //TODO: "local" RV
979                }
980                virtual void logit (logger &L) {
981                        L.logit (LIDs (0), posterior().mean());
982                        if (LFlags (1) || LFlags (2)) {        //if one of them is off, its LID==-1 and will not be stored
983                                vec ub, lb;
984                                posterior().qbounds (lb, ub);
985                                L.logit (LIDs (1), lb);
986                                L.logit (LIDs (2), ub);
987                        }
988                        if (LFlags (3)) L.logit (LIDs (3), ll);
989                }
990                //!@}
991};
992
993template<class EPDF>
994vec mpdf_internal<EPDF>::samplecond (const vec &cond)
995{
996        condition (cond);
997        vec temp = iepdf.sample();
998        return temp;
999}
1000
1001template<class EPDF>
1002mat mpdf_internal<EPDF>::samplecond_m (const vec &cond, int N)
1003{
1004        condition (cond);
1005        mat temp (dimension(), N);
1006        vec smp (dimension());
1007        for (int i = 0; i < N; i++) {
1008                smp = iepdf.sample();
1009                temp.set_col (i, smp);
1010        }
1011
1012        return temp;
1013}
1014
1015template<class EPDF>
1016double mpdf_internal<EPDF>::evallogcond (const vec &dt, const vec &cond)
1017{
1018        double tmp;
1019        condition (cond);
1020        tmp = iepdf.evallog (dt);
1021        // it_assert_debug(std::isfinite(tmp), "Infinite value");
1022        return tmp;
1023}
1024
1025template<class EPDF>
1026vec mpdf_internal<EPDF>::evallogcond_m (const mat &Dt, const vec &cond)
1027{
1028        condition (cond);
1029        return iepdf.evallog_m (Dt);
1030}
1031
1032template<class EPDF>
1033vec mpdf_internal<EPDF>::evallogcond_m (const Array<vec> &Dt, const vec &cond)
1034{
1035        condition (cond);
1036        return iepdf.evallog_m (Dt);
1037}
1038
1039}; //namespace
1040#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.