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

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

moved mpdf::samplecond_m body to .cpp

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