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
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 {
[502]298                        it_error ("not implemented");
[488]299                        return vec (0);
[502]300                }
301
[488]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;
[502]304
[488]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 {
[502]308                        it_error ("not implemented");
[488]309                        return 0.0;
[477]310                }
[502]311
[488]312                //! Compute log-probability of multiple values argument \c val
[502]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
[488]318                //! Return conditional density on the given RV, the remaining rvs will be in conditioning
[504]319                virtual shared_ptr<mpdf> condition (const RV &rv) const;
[271]320
[488]321                //! Return marginal density on the given RV, the remainig rvs are intergrated out
[504]322                virtual shared_ptr<epdf> marginal (const RV &rv) const;
[271]323
[488]324                //! return expected value
325                virtual vec mean() const {
326                        it_error ("not implemneted");
327                        return vec (0);
328                };
[271]329
[488]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                //!@}
[271]343
[488]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                //! @{
[271]349
[488]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                //!@}
[377]365
[488]366                //! \name Access to attributes
367                //! @{
[377]368
[488]369                //! Size of the random variable
370                int dimension() const {
371                        return dim;
[477]372                }
[488]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                }
[377]387
[270]388};
[32]389
[190]390
[5]391//! Conditional probability density, e.g. modeling some dependencies.
[32]392//TODO Samplecond can be generalized
[488]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;
[461]403
[488]404        protected:
405                void set_ep (epdf &iepdf) {
406                        ep = &iepdf;
407                }
[489]408                void set_ep (epdf *iepdfp) {
409                        ep = iepdfp;
410                }
[271]411
[488]412        public:
413                //! \name Constructors
414                //! @{
[2]415
[488]416                mpdf() : dimc (0), rvc(), ep (NULL) { }
[271]417
[488]418                mpdf (const mpdf &m) : dimc (m.dimc), rvc (m.rvc), ep (m.ep) { }
419                //!@}
[102]420
[488]421                //! \name Matematical operations
422                //!@{
[461]423
[488]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);};
[461]426
[488]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
[489]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                }
[461]433
[32]434
[488]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;}
[201]437
[488]438                //! Matrix version of evallogcond
[489]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                }
[271]444
[488]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);}
[271]447
[488]448                //! \name Access to attributes
449                //! @{
[461]450
[488]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                }
[461]464
[488]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                //!@}
[270]489};
[32]490
[487]491template <class EPDF>
[488]492class mpdf_internal: public mpdf
493{
[487]494        protected :
495                EPDF iepdf;
496        public:
497                //! constructor
[488]498                mpdf_internal() : mpdf(), iepdf() {set_ep (iepdf);}
[487]499                //! Update \c iepdf so that it represents this mpdf conditioned on \c rvc = cond
500                //! This function provides convenient reimplementation in offsprings
[488]501                virtual void condition (const vec &cond) {
502                        it_error ("Not implemented");
503                };
[487]504                //!access function to iepdf
[488]505                EPDF& e() {return iepdf;}
506
[487]507                //! Reimplements samplecond using \c condition()
[488]508                vec samplecond (const vec &cond);
[487]509                //! Reimplements evallogcond using \c condition()
[488]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);
[487]513                //! Efficient version of evallogcond for Array<vec>
[488]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);
[487]517};
518
[270]519/*! \brief DataLink is a connection between two data vectors Up and Down
[2]520
[270]521Up can be longer than Down. Down must be fully present in Up (TODO optional)
522See chart:
523\dot
524digraph datalink {
[377]525  node [shape=record];
526  subgraph cluster0 {
527    label = "Up";
528      up [label="<1>|<2>|<3>|<4>|<5>"];
529    color = "white"
[270]530}
[377]531  subgraph cluster1{
532    label = "Down";
533    labelloc = b;
534      down [label="<1>|<2>|<3>"];
535    color = "white"
[270]536}
537    up:1 -> down:1;
538    up:3 -> down:2;
539    up:5 -> down:3;
540}
541\enddot
[263]542
[270]543*/
[488]544class datalink
545{
546        protected:
547                //! Remember how long val should be
548                int downsize;
[424]549
[488]550                //! Remember how long val of "Up" should be
551                int upsize;
[424]552
[488]553                //! val-to-val link, indices of the upper val
554                ivec v2v_up;
[424]555
[488]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                }
[424]562
[488]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);
[271]568
[488]569                        it_assert_debug (v2v_up.length() == downsize, "rv is not fully in rv_up");
570                }
[424]571
[488]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;
[286]577
[488]578                        it_assert_debug (v2v_up.length() == downsize, "rv is not fully in rv_up");
579                }
[424]580
[488]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                }
[424]586
[488]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                }
[270]593};
[115]594
[424]595//! Data link with a condition.
[488]596class datalink_m2e: public datalink
597{
598        protected:
599                //! Remember how long cond should be
600                int condsize;
[424]601
[488]602                //!upper_val-to-local_cond link, indices of the upper val
603                ivec v2c_up;
[424]604
[488]605                //!upper_val-to-local_cond link, indices of the local cond
606                ivec v2c_lo;
[192]607
[488]608        public:
609                //! Constructor
610                datalink_m2e() : condsize (0) { }
[424]611
[488]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                }
[424]618
[488]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                }
[424]625
[488]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                }
[270]632};
[424]633
[192]634//!DataLink is a connection between mpdf and its superordinate (Up)
635//! This class links
[488]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;
[424]643
[488]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                }
[424]653
[488]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
[190]662
[270]663};
[190]664
[270]665/*!
666@brief Class for storing results (and semi-results) of an experiment
[267]667
[270]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 */
[488]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) {}
[267]680
[488]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
[477]694                }
[267]695
[488]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;
[267]700
[488]701                //! Shifts storage position for another time step.
702                virtual void step() = 0;
[267]703
[488]704                //! Finalize storing information
705                virtual void finalize() {};
[267]706
[488]707                //! Initialize the storage
708                virtual void init() {};
[267]709
[270]710};
[267]711
[270]712/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
[190]713
[270]714*/
[488]715class mepdf : public mpdf
716{
[487]717
[489]718                shared_ptr<epdf> iepdf;
[488]719        public:
720                //!Default constructor
721                mepdf() { }
[461]722
[488]723                mepdf (shared_ptr<epdf> em) {
[489]724                        iepdf = em;
725                        set_ep (*iepdf.get());
[488]726                        dimc = 0;
727                }
[461]728
[488]729                //! empty
[489]730                vec samplecond(const vec &cond){return iepdf->sample();}
731                double evallogcond(const vec &val, const vec &cond){return iepdf->evallog(val);}
[461]732
[488]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);
[270]741};
[488]742UIREGISTER (mepdf);
[115]743
[477]744//!\brief Chain rule of pdfs - abstract part common for mprod and merger.
[192]745//!this abstract class is common to epdf and mpdf
[384]746//!\todo Think of better design - global functions rv=get_rv(Array<mpdf*> mpdfs); ??
[488]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                };
[270]771};
[175]772
[270]773/*! \brief Abstract class for discrete-time sources of data.
[12]774
[270]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).
[12]777
[270]778*/
[32]779
[488]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                };
[32]810
[488]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;
[32]813
[488]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(), "");
[32]818
[488]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                }
[270]844};
[18]845
[270]846/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
[32]847
[283]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
[270]865*/
[32]866
[488]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                //! @{
[271]879
[488]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                //!@}
[18]892
[488]893                //! \name Mathematical operations
894                //!@{
[271]895
[488]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;
[477]907                }
[488]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                }
[32]916
[488]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                //!@}
[271]928
[488]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                //!@{
[283]933
[488]934                //! Name of extension variable
935                RV rvc;
936                //! access function
937                const RV& _rvc() const {
938                        return rvc;
939                }
[283]940
[488]941                //! Substitute \c val for \c rvc.
942                virtual void condition (const vec &val) {
943                        it_error ("Not implemented!");
944                };
[283]945
[488]946                //!@}
[283]947
948
[488]949                //! \name Access to attributes
950                //!@{
[271]951
[488]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                //!@}
[28]970
[488]971                //! \name Logging of results
972                //!@{
[200]973
[488]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                        }
[477]984                }
[488]985                //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
986                ivec LIDs;
[190]987
[488]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                        };
[190]999
[488]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
[477]1005                }
[488]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                //!@}
[270]1017};
[32]1018
[488]1019template<class EPDF>
1020vec mpdf_internal<EPDF>::samplecond (const vec &cond)
1021{
1022        condition (cond);
1023        vec temp = iepdf.sample();
1024        return temp;
1025}
[339]1026
[488]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
[254]1065}; //namespace
[384]1066#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.