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

Revision 545, 27.2 kB (checked in by vbarta, 15 years ago)

moved some datalink method bodies to bdmbase.cpp; more datalink 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;
31//! Internal global variable storing sizes of RVs
32extern ivec RV_SIZES;
33//! Internal global variable storing names of RVs
34extern Array<string> RV_NAMES;
35
36//! Structure of RV, i.e. RVs expanded into a flat list of IDs, used for debugging.
37class str
38{
39        public:
40                //! vector id ids (non-unique!)
41                ivec ids;
42                //! vector of times
43                ivec times;
44                //!Default constructor
45                str (ivec ids0, ivec times0) : ids (ids0), times (times0) {
46                        it_assert_debug (times0.length() == ids0.length(), "Incompatible input");
47                };
48};
49
50/*!
51* \brief Class representing variables, most often random variables
52
53The 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.
54
55The class is implemented using global variables to assure uniqueness of description:
56
57 In is a vector
58\dot
59digraph datalink {
60rankdir=LR;
61subgraph cluster0 {
62node [shape=record];
63label = "RV_MAP \n std::map<string,int>";
64map [label="{{\"a\"| \"b\" | \"c\"} | {<3> 3 |<1> 1|<2> 2}}"];
65color = "white"
66}
67subgraph cluster1{
68node [shape=record];
69label = "RV_NAMES";
70names [label="{<1> \"b\" | <2> \"c\" | <3>\"a\" }"];
71color = "white"
72}
73subgraph cluster2{
74node [shape=record];
75label = "RV_SIZES";
76labelloc = b;
77sizes [label="{<1>1 |<2> 4 |<3> 1}"];
78color = "white"
79}
80map:1 -> names:1;
81map:1 -> sizes:1;
82map:3 -> names:3;
83map:3 -> sizes:3;
84}
85\enddot
86*/
87
88class RV : public root
89{
90        protected:
91                //! size of the data vector
92                int dsize;
93                //! number of individual rvs
94                int len;
95                //! Vector of unique IDs
96                ivec ids;
97                //! Vector of shifts from current time
98                ivec times;
99
100        private:
101                //! auxiliary function used in constructor
102                void init (const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times);
103                int init (const string &name, int size);
104        public:
105                //! \name Constructors
106                //!@{
107
108                //! Full constructor
109                RV (const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times) {
110                        init (in_names, in_sizes, in_times);
111                }
112
113                //! Constructor with times=0
114                RV (const Array<std::string> &in_names, const ivec &in_sizes) {
115                        init (in_names, in_sizes, zeros_i (in_names.length()));
116                }
117
118                //! Constructor with sizes=1, times=0
119                RV (const Array<std::string> &in_names) {
120                        init (in_names, ones_i (in_names.length()), zeros_i (in_names.length()));
121                }
122
123                //! Constructor of empty RV
124                RV() : dsize (0), len (0), ids (0), times (0) {}
125
126                //! Constructor of a single RV with given id
127                RV (string name, int sz, int tm = 0);
128
129                // compiler-generated copy constructor is used
130                //!@}
131
132                //! \name Access functions
133                //!@{
134
135                //! State output, e.g. for debugging.
136                friend std::ostream &operator<< (std::ostream &os, const RV &rv);
137
138                int _dsize() const {
139                        return dsize;
140                }
141
142                //! Recount size of the corresponding data vector
143                int countsize() const;
144                ivec cumsizes() const;
145                int length() const {
146                        return len;
147                }
148                int id (int at) const {
149                        return ids (at);
150                }
151                int size (int at) const {
152                        return RV_SIZES (ids (at));
153                }
154                int time (int at) const {
155                        return times (at);
156                }
157                std::string name (int at) const {
158                        return RV_NAMES (ids (at));
159                }
160                void set_time (int at, int time0) {
161                        times (at) = time0;
162                }
163                //!@}
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
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                //! Invalidate all named RVs. Use before initializing any RV instances, with care...
226                static void clear_all();
227};
228UIREGISTER (RV);
229SHAREDPTR (RV);
230
231//! Concat two random variables
232RV concat (const RV &rv1, const RV &rv2);
233
234//!Default empty RV that can be used as default argument
235extern RV RV0;
236
237//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
238
239class fnc : public root
240{
241        protected:
242                //! Length of the output vector
243                int dimy;
244        public:
245                //!default constructor
246                fnc() {};
247                //! function evaluates numerical value of \f$f(x)\f$ at \f$x=\f$ \c cond
248                virtual vec eval (const vec &cond) {
249                        return vec (0);
250                };
251
252                //! function substitutes given value into an appropriate position
253                virtual void condition (const vec &val) {};
254
255                //! access function
256                int dimension() const {
257                        return dimy;
258                }
259};
260
261class mpdf;
262
263//! Probability density function with numerical statistics, e.g. posterior density.
264
265class epdf : public root
266{
267        protected:
268                //! dimension of the random variable
269                int dim;
270                //! Description of the random variable
271                RV rv;
272
273        public:
274                /*! \name Constructors
275                 Construction of each epdf should support two types of constructors:
276                \li empty constructor,
277                \li copy constructor,
278
279                The following constructors should be supported for convenience:
280                \li constructor followed by calling \c set_parameters()
281                \li constructor accepting random variables calling \c set_rv()
282
283                 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.
284                @{*/
285                epdf() : dim (0), rv() {};
286                epdf (const epdf &e) : dim (e.dim), rv (e.rv) {};
287                epdf (const RV &rv0) : dim (rv0._dsize()) {
288                        set_rv (rv0);
289                };
290                void set_parameters (int dim0) {
291                        dim = dim0;
292                }
293                //!@}
294
295                //! \name Matematical Operations
296                //!@{
297
298                //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
299                virtual vec sample() const {
300                        it_error ("not implemented");
301                        return vec (0);
302                }
303
304                //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
305                virtual mat sample_m (int N) const;
306
307                //! Compute log-probability of argument \c val
308                //! In case the argument is out of suport return -Infinity
309                virtual double evallog (const vec &val) const {
310                        it_error ("not implemented");
311                        return 0.0;
312                }
313
314                //! Compute log-probability of multiple values argument \c val
315                virtual vec evallog_m (const mat &Val) const;
316
317                //! Compute log-probability of multiple values argument \c val
318                virtual vec evallog_m (const Array<vec> &Avec) const;
319
320                //! Return conditional density on the given RV, the remaining rvs will be in conditioning
321                virtual shared_ptr<mpdf> condition (const RV &rv) const;
322
323                //! Return marginal density on the given RV, the remainig rvs are intergrated out
324                virtual shared_ptr<epdf> marginal (const RV &rv) const;
325
326                //! return expected value
327                virtual vec mean() const {
328                        it_error ("not implemneted");
329                        return vec (0);
330                };
331
332                //! return expected variance (not covariance!)
333                virtual vec variance() const {
334                        it_error ("not implemneted");
335                        return vec (0);
336                };
337                //! Lower and upper bounds of \c percentage % quantile, returns mean-2*sigma as default
338                virtual void qbounds (vec &lb, vec &ub, double percentage = 0.95) const {
339                        vec mea = mean();
340                        vec std = sqrt (variance());
341                        lb = mea - 2 * std;
342                        ub = mea + 2 * std;
343                };
344                //!@}
345
346                //! \name Connection to other classes
347                //! Description of the random quantity via attribute \c rv is optional.
348                //! For operations such as sampling \c rv does not need to be set. However, for \c marginalization
349                //! and \c conditioning \c rv has to be set. NB:
350                //! @{
351
352                //!Name its rv
353                void set_rv (const RV &rv0) {
354                        rv = rv0;
355                }   //it_assert_debug(isnamed(),""); };
356                //! True if rv is assigned
357                bool isnamed() const {
358                        bool b = (dim == rv._dsize());
359                        return b;
360                }
361                //! Return name (fails when isnamed is false)
362                const RV& _rv() const {
363                        it_assert_debug (isnamed(), "");
364                        return rv;
365                }
366                //!@}
367
368                //! \name Access to attributes
369                //! @{
370
371                //! Size of the random variable
372                int dimension() const {
373                        return dim;
374                }
375                //! Load from structure with elements:
376                //!  \code
377                //! { rv = {class="RV", names=(...),}; // RV describing meaning of random variable
378                //!   // elements of offsprings
379                //! }
380                //! \endcode
381                //!@}
382                void from_setting (const Setting &set) {
383                        shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
384                        if (r) {
385                                set_rv (*r);
386                        }
387                }
388
389};
390SHAREDPTR(epdf);
391
392//! Conditional probability density, e.g. modeling \f$ f( x | y) \f$, where \f$ x \f$ is random variable, \c rv, and \f$ y \f$ is conditioning variable, \c rvc.
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                //! set internal pointer \c ep to point to given \c iepdf
406                void set_ep (epdf &iepdf) {
407                        ep = &iepdf;
408                }
409                //! set internal pointer \c ep to point to given \c iepdf
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
489//! Mpdf with internal epdf that is modified by function \c condition
490template <class EPDF>
491class mpdf_internal: public mpdf
492{
493        protected :
494                //! Internal epdf used for sampling
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
560                //! Convenience constructor
561                datalink (const RV &rv, const RV &rv_up) {
562                        set_connection (rv, rv_up);
563                }
564
565                //! set connection, rv must be fully present in rv_up
566                void set_connection (const RV &rv, const RV &rv_up);
567
568                //! set connection using indices
569                void set_connection (int ds, int us, const ivec &upind);
570
571                //! Get val for myself from val of "Up"
572                vec pushdown (const vec &val_up) {
573                        it_assert_debug (upsize == val_up.length(), "Wrong val_up");
574                        return get_vec (val_up, v2v_up);
575                }
576
577                //! Fill val of "Up" by my pieces
578                void pushup (vec &val_up, const vec &val) {
579                        it_assert_debug (downsize == val.length(), "Wrong val");
580                        it_assert_debug (upsize == val_up.length(), "Wrong val_up");
581                        set_subvector (val_up, v2v_up, val);
582                }
583};
584
585//! Data link with a condition.
586class datalink_m2e: public datalink
587{
588        protected:
589                //! Remember how long cond should be
590                int condsize;
591
592                //!upper_val-to-local_cond link, indices of the upper val
593                ivec v2c_up;
594
595                //!upper_val-to-local_cond link, indices of the local cond
596                ivec v2c_lo;
597
598        public:
599                //! Constructor
600                datalink_m2e() : condsize (0) { }
601
602                //! Set connection between vectors
603                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up);
604
605                //!Construct condition
606                vec get_cond (const vec &val_up);
607
608                //! Copy corresponding values to Up.condition
609                void pushup_cond (vec &val_up, const vec &val, const vec &cond);
610};
611
612//!DataLink is a connection between mpdf and its superordinate (Up)
613//! This class links
614class datalink_m2m: public datalink_m2e
615{
616        protected:
617                //!cond-to-cond link, indices of the upper cond
618                ivec c2c_up;
619                //!cond-to-cond link, indices of the local cond
620                ivec c2c_lo;
621
622        public:
623                //! Constructor
624                datalink_m2m() {};
625                //! Set connection between the vectors
626                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up) {
627                        datalink_m2e::set_connection (rv, rvc, rv_up);
628                        //establish c2c connection
629                        rvc.dataind (rvc_up, c2c_lo, c2c_up);
630                        it_assert_debug (c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given");
631                }
632
633                //! Get cond for myself from val and cond of "Up"
634                vec get_cond (const vec &val_up, const vec &cond_up) {
635                        vec tmp (condsize);
636                        set_subvector (tmp, v2c_lo, val_up (v2c_up));
637                        set_subvector (tmp, c2c_lo, cond_up (c2c_up));
638                        return tmp;
639                }
640                //! Fill
641
642};
643
644/*!
645@brief Class for storing results (and semi-results) of an experiment
646
647This 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.
648 */
649class logger : public root
650{
651        protected:
652                //! RVs of all logged variables.
653                Array<RV> entries;
654                //! Names of logged quantities, e.g. names of algorithm variants
655                Array<string> names;
656        public:
657                //!Default constructor
658                logger() : entries (0), names (0) {}
659
660                //! returns an identifier which will be later needed for calling the \c logit() function
661                //! For empty RV it returns -1, this entry will be ignored by \c logit().
662                virtual int add (const RV &rv, string prefix = "") {
663                        int id;
664                        if (rv._dsize() > 0) {
665                                id = entries.length();
666                                names = concat (names, prefix);   // diff
667                                entries.set_length (id + 1, true);
668                                entries (id) = rv;
669                        } else {
670                                id = -1;
671                        }
672                        return id; // identifier of the last entry
673                }
674
675                //! log this vector
676                virtual void logit (int id, const vec &v) = 0;
677                //! log this double
678                virtual void logit (int id, const double &d) = 0;
679
680                //! Shifts storage position for another time step.
681                virtual void step() = 0;
682
683                //! Finalize storing information
684                virtual void finalize() {};
685
686                //! Initialize the storage
687                virtual void init() {};
688
689};
690
691/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
692
693*/
694class mepdf : public mpdf
695{
696                //! Internal shared pointer to epdf
697                shared_ptr<epdf> iepdf;
698        public:
699                //!Default constructor
700                mepdf() { }
701                //! Set internal shared pointer
702                mepdf (shared_ptr<epdf> em) {
703                        iepdf = em;
704                        set_ep (*iepdf.get());
705                        dimc = 0;
706                }
707
708                //! empty
709                vec samplecond(const vec &cond){return iepdf->sample();}
710                double evallogcond(const vec &val, const vec &cond){return iepdf->evallog(val);}
711
712                //! Load from structure with elements:
713                //!  \code
714                //! { class = "mepdf",
715                //!   epdf = {class="epdf_offspring",...}
716                //! }
717                //! \endcode
718                //!@}
719                void from_setting (const Setting &set);
720};
721UIREGISTER (mepdf);
722SHAREDPTR (mepdf);
723
724//! \brief Combines RVs from a list of mpdfs to a single one.
725RV get_composite_rv ( const Array<shared_ptr<mpdf> > &mpdfs, bool checkoverlap = false );
726
727/*! \brief Abstract class for discrete-time sources of data.
728
729The 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.
730Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
731
732*/
733
734class DS : public root
735{
736        protected:
737                int dtsize;
738                int utsize;
739                //!Description of data returned by \c getdata().
740                RV Drv;
741                //!Description of data witten by by \c write().
742                RV Urv; //
743                //! Remember its own index in Logger L
744                int L_dt, L_ut;
745        public:
746                //! default constructors
747                DS() : Drv(), Urv() {};
748                //! Returns full vector of observed data=[output, input]
749                virtual void getdata (vec &dt) {
750                        it_error ("abstract class");
751                };
752                //! Returns data records at indeces.
753                virtual void getdata (vec &dt, const ivec &indeces) {
754                        it_error ("abstract class");
755                };
756                //! Accepts action variable and schedule it for application.
757                virtual void write (vec &ut) {
758                        it_error ("abstract class");
759                };
760                //! Accepts action variables at specific indeces
761                virtual void write (vec &ut, const ivec &indeces) {
762                        it_error ("abstract class");
763                };
764
765                //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
766                virtual void step() = 0;
767
768                //! Register DS for logging into logger L
769                virtual void log_add (logger &L) {
770                        it_assert_debug (dtsize == Drv._dsize(), "");
771                        it_assert_debug (utsize == Urv._dsize(), "");
772
773                        L_dt = L.add (Drv, "");
774                        L_ut = L.add (Urv, "");
775                }
776                //! Register DS for logging into logger L
777                virtual void logit (logger &L) {
778                        vec tmp (Drv._dsize() + Urv._dsize());
779                        getdata (tmp);
780                        // d is first in getdata
781                        L.logit (L_dt, tmp.left (Drv._dsize()));
782                        // u follows after d in getdata
783                        L.logit (L_ut, tmp.mid (Drv._dsize(), Urv._dsize()));
784                }
785                //!access function
786                virtual RV _drv() const {
787                        return concat (Drv, Urv);
788                }
789                //!access function
790                const RV& _urv() const {
791                        return Urv;
792                }
793                //! set random rvariables
794                virtual void set_drv (const  RV &drv, const RV &urv) {
795                        Drv = drv;
796                        Urv = urv;
797                }
798};
799
800/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
801
802This object represents exact or approximate evaluation of the Bayes rule:
803\f[
804f(\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})}
805\f]
806
807Access to the resulting posterior density is via function \c posterior().
808
809As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
810It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
811
812Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
813\f[
814f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
815\f]
816
817The value of \f$ c_t \f$ is set by function condition().
818
819*/
820
821class BM : public root
822{
823        protected:
824                //! Random variable of the data (optional)
825                RV drv;
826                //!Logarithm of marginalized data likelihood.
827                double ll;
828                //!  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.
829                bool evalll;
830        public:
831                //! \name Constructors
832                //! @{
833
834                BM() : ll (0), evalll (true), LIDs (4), LFlags (4) {
835                        LIDs = -1;/*empty IDs*/
836                        LFlags = 0;
837                        LFlags (0) = 1;  /*log only mean*/
838                };
839                BM (const BM &B) :  drv (B.drv), ll (B.ll), evalll (B.evalll) {}
840                //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
841                //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
842                virtual BM* _copy_() const {
843                        return NULL;
844                };
845                //!@}
846
847                //! \name Mathematical operations
848                //!@{
849
850                /*! \brief Incremental Bayes rule
851                @param dt vector of input data
852                */
853                virtual void bayes (const vec &dt) = 0;
854                //! Batch Bayes rule (columns of Dt are observations)
855                virtual void bayesB (const mat &Dt);
856                //! Evaluates predictive log-likelihood of the given data record
857                //! I.e. marginal likelihood of the data with the posterior integrated out.
858                virtual double logpred (const vec &dt) const {
859                        it_error ("Not implemented");
860                        return 0.0;
861                }
862                //! Matrix version of logpred
863                vec logpred_m (const mat &dt) const {
864                        vec tmp (dt.cols());
865                        for (int i = 0; i < dt.cols(); i++) {
866                                tmp (i) = logpred (dt.get_col (i));
867                        }
868                        return tmp;
869                }
870
871                //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
872                virtual epdf* epredictor() const {
873                        it_error ("Not implemented");
874                        return NULL;
875                };
876                //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
877                virtual mpdf* predictor() const {
878                        it_error ("Not implemented");
879                        return NULL;
880                };
881                //!@}
882
883                //! \name Extension to conditional BM
884                //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
885                //! Alternatively, it can be used for automated connection to DS when the condition is observed
886                //!@{
887
888                //! Name of extension variable
889                RV rvc;
890                //! access function
891                const RV& _rvc() const {
892                        return rvc;
893                }
894
895                //! Substitute \c val for \c rvc.
896                virtual void condition (const vec &val) {
897                        it_error ("Not implemented!");
898                };
899
900                //!@}
901
902
903                //! \name Access to attributes
904                //!@{
905
906                const RV& _drv() const {
907                        return drv;
908                }
909                void set_drv (const RV &rv) {
910                        drv = rv;
911                }
912                void set_rv (const RV &rv) {
913                        const_cast<epdf&> (posterior()).set_rv (rv);
914                }
915                double _ll() const {
916                        return ll;
917                }
918                void set_evalll (bool evl0) {
919                        evalll = evl0;
920                }
921                virtual const epdf& posterior() const = 0;
922                //!@}
923
924                //! \name Logging of results
925                //!@{
926
927                //! Set boolean options from a string, recognized are: "logbounds,logll"
928                virtual void set_options (const string &opt) {
929                        LFlags (0) = 1;
930                        if (opt.find ("logbounds") != string::npos) {
931                                LFlags (1) = 1;
932                                LFlags (2) = 1;
933                        }
934                        if (opt.find ("logll") != string::npos) {
935                                LFlags (3) = 1;
936                        }
937                }
938                //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
939                ivec LIDs;
940
941                //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
942                ivec LFlags;
943                //! Add all logged variables to a logger
944                virtual void log_add (logger &L, const string &name = "") {
945                        // internal
946                        RV r;
947                        if (posterior().isnamed()) {
948                                r = posterior()._rv();
949                        } else {
950                                r = RV ("est", posterior().dimension());
951                        };
952
953                        // Add mean value
954                        if (LFlags (0)) LIDs (0) = L.add (r, name + "mean_");
955                        if (LFlags (1)) LIDs (1) = L.add (r, name + "lb_");
956                        if (LFlags (2)) LIDs (2) = L.add (r, name + "ub_");
957                        if (LFlags (3)) LIDs (3) = L.add (RV ("ll", 1), name);              //TODO: "local" RV
958                }
959                virtual void logit (logger &L) {
960                        L.logit (LIDs (0), posterior().mean());
961                        if (LFlags (1) || LFlags (2)) {        //if one of them is off, its LID==-1 and will not be stored
962                                vec ub, lb;
963                                posterior().qbounds (lb, ub);
964                                L.logit (LIDs (1), lb);
965                                L.logit (LIDs (2), ub);
966                        }
967                        if (LFlags (3)) L.logit (LIDs (3), ll);
968                }
969                //!@}
970};
971
972typedef Array<shared_ptr<epdf> > epdf_array;
973
974typedef Array<shared_ptr<mpdf> > mpdf_array;
975
976template<class EPDF>
977vec mpdf_internal<EPDF>::samplecond (const vec &cond)
978{
979        condition (cond);
980        vec temp = iepdf.sample();
981        return temp;
982}
983
984template<class EPDF>
985mat mpdf_internal<EPDF>::samplecond_m (const vec &cond, int N)
986{
987        condition (cond);
988        mat temp (dimension(), N);
989        vec smp (dimension());
990        for (int i = 0; i < N; i++) {
991                smp = iepdf.sample();
992                temp.set_col (i, smp);
993        }
994
995        return temp;
996}
997
998template<class EPDF>
999double mpdf_internal<EPDF>::evallogcond (const vec &dt, const vec &cond)
1000{
1001        double tmp;
1002        condition (cond);
1003        tmp = iepdf.evallog (dt);
1004        // it_assert_debug(std::isfinite(tmp), "Infinite value");
1005        return tmp;
1006}
1007
1008template<class EPDF>
1009vec mpdf_internal<EPDF>::evallogcond_m (const mat &Dt, const vec &cond)
1010{
1011        condition (cond);
1012        return iepdf.evallog_m (Dt);
1013}
1014
1015template<class EPDF>
1016vec mpdf_internal<EPDF>::evallogcond_m (const Array<vec> &Dt, const vec &cond)
1017{
1018        condition (cond);
1019        return iepdf.evallog_m (Dt);
1020}
1021
1022}; //namespace
1023#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.