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

Revision 504, 28.0 kB (checked in by vbarta, 15 years ago)

returning shared pointers from epdf::marginal & epdf::condition; testsuite run leaks down from 8402 to 6510 bytes

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