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

Revision 529, 27.5 kB (checked in by vbarta, 15 years ago)

defined *_ptr wrappers of shared pointers

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