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

Revision 536, 27.9 kB (checked in by smidl, 15 years ago)

removal of unused functions _e() and samplecond(,) and added documentation lines

  • 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                //! Conevnience constructor
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                //! Set connection between vectors
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                //! Copy corresponding values to Up.condition
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                //! Set connection between the vectors
649                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up) {
650                        datalink_m2e::set_connection (rv, rvc, rv_up);
651                        //establish c2c connection
652                        rvc.dataind (rvc_up, c2c_lo, c2c_up);
653                        it_assert_debug (c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given");
654                }
655
656                //! Get cond for myself from val and cond of "Up"
657                vec get_cond (const vec &val_up, const vec &cond_up) {
658                        vec tmp (condsize);
659                        set_subvector (tmp, v2c_lo, val_up (v2c_up));
660                        set_subvector (tmp, c2c_lo, cond_up (c2c_up));
661                        return tmp;
662                }
663                //! Fill
664
665};
666
667/*!
668@brief Class for storing results (and semi-results) of an experiment
669
670This 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.
671 */
672class logger : public root
673{
674        protected:
675                //! RVs of all logged variables.
676                Array<RV> entries;
677                //! Names of logged quantities, e.g. names of algorithm variants
678                Array<string> names;
679        public:
680                //!Default constructor
681                logger() : entries (0), names (0) {}
682
683                //! returns an identifier which will be later needed for calling the \c logit() function
684                //! For empty RV it returns -1, this entry will be ignored by \c logit().
685                virtual int add (const RV &rv, string prefix = "") {
686                        int id;
687                        if (rv._dsize() > 0) {
688                                id = entries.length();
689                                names = concat (names, prefix);   // diff
690                                entries.set_length (id + 1, true);
691                                entries (id) = rv;
692                        } else {
693                                id = -1;
694                        }
695                        return id; // identifier of the last entry
696                }
697
698                //! log this vector
699                virtual void logit (int id, const vec &v) = 0;
700                //! log this double
701                virtual void logit (int id, const double &d) = 0;
702
703                //! Shifts storage position for another time step.
704                virtual void step() = 0;
705
706                //! Finalize storing information
707                virtual void finalize() {};
708
709                //! Initialize the storage
710                virtual void init() {};
711
712};
713
714/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
715
716*/
717class mepdf : public mpdf
718{
719                //! Internal shared pointer to epdf
720                shared_ptr<epdf> iepdf;
721        public:
722                //!Default constructor
723                mepdf() { }
724                //! Set internal shared pointer
725                mepdf (shared_ptr<epdf> em) {
726                        iepdf = em;
727                        set_ep (*iepdf.get());
728                        dimc = 0;
729                }
730
731                //! empty
732                vec samplecond(const vec &cond){return iepdf->sample();}
733                double evallogcond(const vec &val, const vec &cond){return iepdf->evallog(val);}
734
735                //! Load from structure with elements:
736                //!  \code
737                //! { class = "mepdf",
738                //!   epdf = {class="epdf_offspring",...}
739                //! }
740                //! \endcode
741                //!@}
742                void from_setting (const Setting &set);
743};
744UIREGISTER (mepdf);
745SHAREDPTR (mepdf);
746
747//! \brief Combines RVs from a list of mpdfs to a single one.
748RV get_composite_rv ( const Array<shared_ptr<mpdf> > &mpdfs, bool checkoverlap = false );
749
750/*! \brief Abstract class for discrete-time sources of data.
751
752The 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.
753Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
754
755*/
756
757class DS : public root
758{
759        protected:
760                int dtsize;
761                int utsize;
762                //!Description of data returned by \c getdata().
763                RV Drv;
764                //!Description of data witten by by \c write().
765                RV Urv; //
766                //! Remember its own index in Logger L
767                int L_dt, L_ut;
768        public:
769                //! default constructors
770                DS() : Drv(), Urv() {};
771                //! Returns full vector of observed data=[output, input]
772                virtual void getdata (vec &dt) {
773                        it_error ("abstract class");
774                };
775                //! Returns data records at indeces.
776                virtual void getdata (vec &dt, const ivec &indeces) {
777                        it_error ("abstract class");
778                };
779                //! Accepts action variable and schedule it for application.
780                virtual void write (vec &ut) {
781                        it_error ("abstract class");
782                };
783                //! Accepts action variables at specific indeces
784                virtual void write (vec &ut, const ivec &indeces) {
785                        it_error ("abstract class");
786                };
787
788                //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
789                virtual void step() = 0;
790
791                //! Register DS for logging into logger L
792                virtual void log_add (logger &L) {
793                        it_assert_debug (dtsize == Drv._dsize(), "");
794                        it_assert_debug (utsize == Urv._dsize(), "");
795
796                        L_dt = L.add (Drv, "");
797                        L_ut = L.add (Urv, "");
798                }
799                //! Register DS for logging into logger L
800                virtual void logit (logger &L) {
801                        vec tmp (Drv._dsize() + Urv._dsize());
802                        getdata (tmp);
803                        // d is first in getdata
804                        L.logit (L_dt, tmp.left (Drv._dsize()));
805                        // u follows after d in getdata
806                        L.logit (L_ut, tmp.mid (Drv._dsize(), Urv._dsize()));
807                }
808                //!access function
809                virtual RV _drv() const {
810                        return concat (Drv, Urv);
811                }
812                //!access function
813                const RV& _urv() const {
814                        return Urv;
815                }
816                //! set random rvariables
817                virtual void set_drv (const  RV &drv, const RV &urv) {
818                        Drv = drv;
819                        Urv = urv;
820                }
821};
822
823/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
824
825This object represents exact or approximate evaluation of the Bayes rule:
826\f[
827f(\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})}
828\f]
829
830Access to the resulting posterior density is via function \c posterior().
831
832As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
833It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
834
835Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
836\f[
837f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
838\f]
839
840The value of \f$ c_t \f$ is set by function condition().
841
842*/
843
844class BM : public root
845{
846        protected:
847                //! Random variable of the data (optional)
848                RV drv;
849                //!Logarithm of marginalized data likelihood.
850                double ll;
851                //!  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.
852                bool evalll;
853        public:
854                //! \name Constructors
855                //! @{
856
857                BM() : ll (0), evalll (true), LIDs (4), LFlags (4) {
858                        LIDs = -1;/*empty IDs*/
859                        LFlags = 0;
860                        LFlags (0) = 1;  /*log only mean*/
861                };
862                BM (const BM &B) :  drv (B.drv), ll (B.ll), evalll (B.evalll) {}
863                //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
864                //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
865                virtual BM* _copy_() const {
866                        return NULL;
867                };
868                //!@}
869
870                //! \name Mathematical operations
871                //!@{
872
873                /*! \brief Incremental Bayes rule
874                @param dt vector of input data
875                */
876                virtual void bayes (const vec &dt) = 0;
877                //! Batch Bayes rule (columns of Dt are observations)
878                virtual void bayesB (const mat &Dt);
879                //! Evaluates predictive log-likelihood of the given data record
880                //! I.e. marginal likelihood of the data with the posterior integrated out.
881                virtual double logpred (const vec &dt) const {
882                        it_error ("Not implemented");
883                        return 0.0;
884                }
885                //! Matrix version of logpred
886                vec logpred_m (const mat &dt) const {
887                        vec tmp (dt.cols());
888                        for (int i = 0; i < dt.cols(); i++) {
889                                tmp (i) = logpred (dt.get_col (i));
890                        }
891                        return tmp;
892                }
893
894                //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
895                virtual epdf* epredictor() const {
896                        it_error ("Not implemented");
897                        return NULL;
898                };
899                //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
900                virtual mpdf* predictor() const {
901                        it_error ("Not implemented");
902                        return NULL;
903                };
904                //!@}
905
906                //! \name Extension to conditional BM
907                //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
908                //! Alternatively, it can be used for automated connection to DS when the condition is observed
909                //!@{
910
911                //! Name of extension variable
912                RV rvc;
913                //! access function
914                const RV& _rvc() const {
915                        return rvc;
916                }
917
918                //! Substitute \c val for \c rvc.
919                virtual void condition (const vec &val) {
920                        it_error ("Not implemented!");
921                };
922
923                //!@}
924
925
926                //! \name Access to attributes
927                //!@{
928
929                const RV& _drv() const {
930                        return drv;
931                }
932                void set_drv (const RV &rv) {
933                        drv = rv;
934                }
935                void set_rv (const RV &rv) {
936                        const_cast<epdf&> (posterior()).set_rv (rv);
937                }
938                double _ll() const {
939                        return ll;
940                }
941                void set_evalll (bool evl0) {
942                        evalll = evl0;
943                }
944                virtual const epdf& posterior() 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.