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

Revision 531, 27.4 kB (checked in by vbarta, 15 years ago)

more RV tests

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Basic structures of probability calculus: random variables, probability densities, Bayes rule
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                /*! \brief UI for class RV (description of data vectors)
206
207                \code
208                rv = {
209                  class = "RV"; // class name
210                  // UNIQUE IDENTIFIER same names = same variable
211                  names = ( "a", "b", "c", ...);   // which will be used e.g. in loggers
212
213                  //optional arguments
214                  sizes = [1, 2, 3, ...];         // (optional) default = ones()
215                  times = [-1, -2, 0, ...];       // time shifts with respect to current time (optional) default = zeros()
216                }
217                \endcode
218                */
219                void from_setting (const Setting &set);
220
221                // TODO dodelat void to_setting( Setting &set ) const;
222
223                //! Invalidate all named RVs. Use before initializing any RV instances, with care...
224                static void clear_all();
225};
226UIREGISTER (RV);
227SHAREDPTR (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                        shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
382                        if (r) {
383                                set_rv (*r);
384                        }
385                }
386
387};
388SHAREDPTR(epdf);
389
390//! Conditional probability density, e.g. modeling some dependencies.
391//TODO Samplecond can be generalized
392class mpdf : public root
393{
394        protected:
395                //!dimension of the condition
396                int dimc;
397                //! random variable in condition
398                RV rvc;
399        private:
400                //! internal epdf, used only as cache to avoid virtual calls of \c _rv() and \c _dimension()
401                epdf* ep;
402
403        protected:
404                void set_ep (epdf &iepdf) {
405                        ep = &iepdf;
406                }
407                void set_ep (epdf *iepdfp) {
408                        ep = iepdfp;
409                }
410
411        public:
412                //! \name Constructors
413                //! @{
414
415                mpdf() : dimc (0), rvc(), ep (NULL) { }
416
417                mpdf (const mpdf &m) : dimc (m.dimc), rvc (m.rvc), ep (m.ep) { }
418                //!@}
419
420                //! \name Matematical operations
421                //!@{
422
423                //! 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
424                virtual vec samplecond (const vec &cond) {it_error ("Not implemented");return vec (0);};
425
426                //! 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
427                virtual mat samplecond_m (const vec &cond, int N) {
428                        mat M(dimension(), N);
429                        for(int i=0;i<N;i++){M.set_col(i, samplecond(cond));}
430                        return M;
431                }
432
433
434                //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
435                virtual double evallogcond (const vec &dt, const vec &cond) {it_error ("Not implemented");return 0.0;}
436
437                //! Matrix version of evallogcond
438                virtual vec evallogcond_m (const mat &Dt, const vec &cond) {
439                        vec v(Dt.cols());
440                        for(int i=0;i<Dt.cols();i++){v(i)= evallogcond(Dt.get_col(i),cond);}
441                        return v;
442                }
443
444                //! Array<vec> version of evallogcond
445                virtual vec evallogcond_m (const Array<vec> &Dt, const vec &cond) {it_error ("Not implemented");return vec (0);}
446
447                //! \name Access to attributes
448                //! @{
449
450                RV _rv() const {
451                        return ep->_rv();
452                }
453                RV _rvc() {
454                        return rvc;
455                }
456
457                int dimension() const {
458                        return ep->dimension();
459                }
460                int dimensionc() {
461                        return dimc;
462                }
463
464                //! Load from structure with elements:
465                //!  \code
466                //! { class = "mpdf_offspring",
467                //!   rv = {class="RV", names=(...),}; // RV describing meaning of random variable
468                //!   rvc= {class="RV", names=(...),}; // RV describing meaning of random variable in condition
469                //!   // elements of offsprings
470                //! }
471                //! \endcode
472                //!@}
473                void from_setting (const Setting &set);
474                //!@}
475
476                //! \name Connection to other objects
477                //!@{
478                void set_rvc (const RV &rvc0) {
479                        rvc = rvc0;
480                }
481                void set_rv (const RV &rv0) {
482                        ep->set_rv (rv0);
483                }
484                bool isnamed() {
485                        return (ep->isnamed()) && (dimc == rvc._dsize());
486                }
487                //!@}
488};
489SHAREDPTR(mpdf);
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);
743SHAREDPTR (mepdf);
744
745//! \brief Combines RVs from a list of mpdfs to a single one.
746RV get_composite_rv ( const Array<shared_ptr<mpdf> > &mpdfs, bool checkoverlap = false );
747
748/*! \brief Abstract class for discrete-time sources of data.
749
750The 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.
751Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
752
753*/
754
755class DS : public root
756{
757        protected:
758                int dtsize;
759                int utsize;
760                //!Description of data returned by \c getdata().
761                RV Drv;
762                //!Description of data witten by by \c write().
763                RV Urv; //
764                //! Remember its own index in Logger L
765                int L_dt, L_ut;
766        public:
767                //! default constructors
768                DS() : Drv(), Urv() {};
769                //! Returns full vector of observed data=[output, input]
770                virtual void getdata (vec &dt) {
771                        it_error ("abstract class");
772                };
773                //! Returns data records at indeces.
774                virtual void getdata (vec &dt, const ivec &indeces) {
775                        it_error ("abstract class");
776                };
777                //! Accepts action variable and schedule it for application.
778                virtual void write (vec &ut) {
779                        it_error ("abstract class");
780                };
781                //! Accepts action variables at specific indeces
782                virtual void write (vec &ut, const ivec &indeces) {
783                        it_error ("abstract class");
784                };
785
786                //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
787                virtual void step() = 0;
788
789                //! Register DS for logging into logger L
790                virtual void log_add (logger &L) {
791                        it_assert_debug (dtsize == Drv._dsize(), "");
792                        it_assert_debug (utsize == Urv._dsize(), "");
793
794                        L_dt = L.add (Drv, "");
795                        L_ut = L.add (Urv, "");
796                }
797                //! Register DS for logging into logger L
798                virtual void logit (logger &L) {
799                        vec tmp (Drv._dsize() + Urv._dsize());
800                        getdata (tmp);
801                        // d is first in getdata
802                        L.logit (L_dt, tmp.left (Drv._dsize()));
803                        // u follows after d in getdata
804                        L.logit (L_ut, tmp.mid (Drv._dsize(), Urv._dsize()));
805                }
806                //!access function
807                virtual RV _drv() const {
808                        return concat (Drv, Urv);
809                }
810                //!access function
811                const RV& _urv() const {
812                        return Urv;
813                }
814                //! set random rvariables
815                virtual void set_drv (const  RV &drv, const RV &urv) {
816                        Drv = drv;
817                        Urv = urv;
818                }
819};
820
821/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
822
823This object represents exact or approximate evaluation of the Bayes rule:
824\f[
825f(\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})}
826\f]
827
828Access to the resulting posterior density is via function \c posterior().
829
830As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
831It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
832
833Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
834\f[
835f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
836\f]
837
838The value of \f$ c_t \f$ is set by function condition().
839
840*/
841
842class BM : public root
843{
844        protected:
845                //! Random variable of the data (optional)
846                RV drv;
847                //!Logarithm of marginalized data likelihood.
848                double ll;
849                //!  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.
850                bool evalll;
851        public:
852                //! \name Constructors
853                //! @{
854
855                BM() : ll (0), evalll (true), LIDs (4), LFlags (4) {
856                        LIDs = -1;/*empty IDs*/
857                        LFlags = 0;
858                        LFlags (0) = 1;  /*log only mean*/
859                };
860                BM (const BM &B) :  drv (B.drv), ll (B.ll), evalll (B.evalll) {}
861                //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
862                //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
863                virtual BM* _copy_() const {
864                        return NULL;
865                };
866                //!@}
867
868                //! \name Mathematical operations
869                //!@{
870
871                /*! \brief Incremental Bayes rule
872                @param dt vector of input data
873                */
874                virtual void bayes (const vec &dt) = 0;
875                //! Batch Bayes rule (columns of Dt are observations)
876                virtual void bayesB (const mat &Dt);
877                //! Evaluates predictive log-likelihood of the given data record
878                //! I.e. marginal likelihood of the data with the posterior integrated out.
879                virtual double logpred (const vec &dt) const {
880                        it_error ("Not implemented");
881                        return 0.0;
882                }
883                //! Matrix version of logpred
884                vec logpred_m (const mat &dt) const {
885                        vec tmp (dt.cols());
886                        for (int i = 0; i < dt.cols(); i++) {
887                                tmp (i) = logpred (dt.get_col (i));
888                        }
889                        return tmp;
890                }
891
892                //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
893                virtual epdf* epredictor() const {
894                        it_error ("Not implemented");
895                        return NULL;
896                };
897                //!Constructs a conditional density 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t})
898                virtual mpdf* predictor() const {
899                        it_error ("Not implemented");
900                        return NULL;
901                };
902                //!@}
903
904                //! \name Extension to conditional BM
905                //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
906                //! Alternatively, it can be used for automated connection to DS when the condition is observed
907                //!@{
908
909                //! Name of extension variable
910                RV rvc;
911                //! access function
912                const RV& _rvc() const {
913                        return rvc;
914                }
915
916                //! Substitute \c val for \c rvc.
917                virtual void condition (const vec &val) {
918                        it_error ("Not implemented!");
919                };
920
921                //!@}
922
923
924                //! \name Access to attributes
925                //!@{
926
927                const RV& _drv() const {
928                        return drv;
929                }
930                void set_drv (const RV &rv) {
931                        drv = rv;
932                }
933                void set_rv (const RV &rv) {
934                        const_cast<epdf&> (posterior()).set_rv (rv);
935                }
936                double _ll() const {
937                        return ll;
938                }
939                void set_evalll (bool evl0) {
940                        evalll = evl0;
941                }
942                virtual const epdf& posterior() const = 0;
943                virtual const epdf* _e() const = 0;
944                //!@}
945
946                //! \name Logging of results
947                //!@{
948
949                //! Set boolean options from a string, recognized are: "logbounds,logll"
950                virtual void set_options (const string &opt) {
951                        LFlags (0) = 1;
952                        if (opt.find ("logbounds") != string::npos) {
953                                LFlags (1) = 1;
954                                LFlags (2) = 1;
955                        }
956                        if (opt.find ("logll") != string::npos) {
957                                LFlags (3) = 1;
958                        }
959                }
960                //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
961                ivec LIDs;
962
963                //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
964                ivec LFlags;
965                //! Add all logged variables to a logger
966                virtual void log_add (logger &L, const string &name = "") {
967                        // internal
968                        RV r;
969                        if (posterior().isnamed()) {
970                                r = posterior()._rv();
971                        } else {
972                                r = RV ("est", posterior().dimension());
973                        };
974
975                        // Add mean value
976                        if (LFlags (0)) LIDs (0) = L.add (r, name + "mean_");
977                        if (LFlags (1)) LIDs (1) = L.add (r, name + "lb_");
978                        if (LFlags (2)) LIDs (2) = L.add (r, name + "ub_");
979                        if (LFlags (3)) LIDs (3) = L.add (RV ("ll", 1), name);              //TODO: "local" RV
980                }
981                virtual void logit (logger &L) {
982                        L.logit (LIDs (0), posterior().mean());
983                        if (LFlags (1) || LFlags (2)) {        //if one of them is off, its LID==-1 and will not be stored
984                                vec ub, lb;
985                                posterior().qbounds (lb, ub);
986                                L.logit (LIDs (1), lb);
987                                L.logit (LIDs (2), ub);
988                        }
989                        if (LFlags (3)) L.logit (LIDs (3), ll);
990                }
991                //!@}
992};
993
994typedef Array<shared_ptr<epdf> > epdf_array;
995
996typedef Array<shared_ptr<mpdf> > mpdf_array;
997
998template<class EPDF>
999vec mpdf_internal<EPDF>::samplecond (const vec &cond)
1000{
1001        condition (cond);
1002        vec temp = iepdf.sample();
1003        return temp;
1004}
1005
1006template<class EPDF>
1007mat mpdf_internal<EPDF>::samplecond_m (const vec &cond, int N)
1008{
1009        condition (cond);
1010        mat temp (dimension(), N);
1011        vec smp (dimension());
1012        for (int i = 0; i < N; i++) {
1013                smp = iepdf.sample();
1014                temp.set_col (i, smp);
1015        }
1016
1017        return temp;
1018}
1019
1020template<class EPDF>
1021double mpdf_internal<EPDF>::evallogcond (const vec &dt, const vec &cond)
1022{
1023        double tmp;
1024        condition (cond);
1025        tmp = iepdf.evallog (dt);
1026        // it_assert_debug(std::isfinite(tmp), "Infinite value");
1027        return tmp;
1028}
1029
1030template<class EPDF>
1031vec mpdf_internal<EPDF>::evallogcond_m (const mat &Dt, const vec &cond)
1032{
1033        condition (cond);
1034        return iepdf.evallog_m (Dt);
1035}
1036
1037template<class EPDF>
1038vec mpdf_internal<EPDF>::evallogcond_m (const Array<vec> &Dt, const vec &cond)
1039{
1040        condition (cond);
1041        return iepdf.evallog_m (Dt);
1042}
1043
1044}; //namespace
1045#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.