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

Revision 489, 28.4 kB (checked in by smidl, 15 years ago)

Mpdf redesing is complet - all tests pass (except mlnorm<chmat> which is irrelevant)

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