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

Revision 502, 28.1 kB (checked in by vbarta, 15 years ago)

added tests of epdf::evallog_m methods, moved them out of line

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