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

Revision 588, 27.6 kB (checked in by smidl, 15 years ago)

win32 compilation fixes

  • Property svn:eol-style set to native
RevLine 
[2]1/*!
[5]2  \file
[508]3  \brief Basic structures of probability calculus: random variables, probability densities, Bayes rule
[5]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;
[536]31//! Internal global variable storing sizes of RVs
[270]32extern ivec RV_SIZES;
[536]33//! Internal global variable storing names of RVs
[270]34extern Array<string> RV_NAMES;
35
[422]36//! Structure of RV, i.e. RVs expanded into a flat list of IDs, used for debugging.
[488]37class str
38{
39        public:
40                //! vector id ids (non-unique!)
41                ivec ids;
42                //! vector of times
43                ivec times;
44                //!Default constructor
45                str (ivec ids0, ivec times0) : ids (ids0), times (times0) {
[565]46                        bdm_assert_debug (times0.length() == ids0.length(), "Incompatible input");
[488]47                };
[270]48};
[145]49
[270]50/*!
51* \brief Class representing variables, most often random variables
[5]52
[270]53The purpose of this class is to decribe a vector of data. Such description is used for connecting various vectors between each other, see class datalink.
[32]54
[270]55The class is implemented using global variables to assure uniqueness of description:
[2]56
[270]57 In is a vector
58\dot
59digraph datalink {
60rankdir=LR;
61subgraph cluster0 {
62node [shape=record];
63label = "RV_MAP \n std::map<string,int>";
64map [label="{{\"a\"| \"b\" | \"c\"} | {<3> 3 |<1> 1|<2> 2}}"];
65color = "white"
66}
67subgraph cluster1{
68node [shape=record];
69label = "RV_NAMES";
70names [label="{<1> \"b\" | <2> \"c\" | <3>\"a\" }"];
71color = "white"
72}
73subgraph cluster2{
74node [shape=record];
75label = "RV_SIZES";
76labelloc = b;
77sizes [label="{<1>1 |<2> 4 |<3> 1}"];
78color = "white"
79}
80map:1 -> names:1;
81map:1 -> sizes:1;
82map:3 -> names:3;
83map:3 -> sizes:3;
84}
85\enddot
86*/
[32]87
[488]88class RV : public root
89{
90        protected:
91                //! size of the data vector
92                int dsize;
93                //! number of individual rvs
94                int len;
95                //! Vector of unique IDs
96                ivec ids;
97                //! Vector of shifts from current time
98                ivec times;
[5]99
[488]100        private:
101                //! auxiliary function used in constructor
102                void init (const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times);
103                int init (const string &name, int size);
104        public:
105                //! \name Constructors
106                //!@{
[271]107
[488]108                //! Full constructor
109                RV (const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times) {
110                        init (in_names, in_sizes, in_times);
111                }
[422]112
[488]113                //! Constructor with times=0
114                RV (const Array<std::string> &in_names, const ivec &in_sizes) {
115                        init (in_names, in_sizes, zeros_i (in_names.length()));
116                }
[422]117
[488]118                //! Constructor with sizes=1, times=0
119                RV (const Array<std::string> &in_names) {
120                        init (in_names, ones_i (in_names.length()), zeros_i (in_names.length()));
121                }
[422]122
[488]123                //! Constructor of empty RV
124                RV() : dsize (0), len (0), ids (0), times (0) {}
[532]125
[488]126                //! Constructor of a single RV with given id
127                RV (string name, int sz, int tm = 0);
[532]128
129                // compiler-generated copy constructor is used
[488]130                //!@}
[271]131
[488]132                //! \name Access functions
133                //!@{
[271]134
[488]135                //! State output, e.g. for debugging.
136                friend std::ostream &operator<< (std::ostream &os, const RV &rv);
[422]137
[488]138                int _dsize() const {
139                        return dsize;
140                }
[584]141               
142                //! access function
143                const ivec& _ids() const { return ids;}
[422]144
[488]145                //! Recount size of the corresponding data vector
146                int countsize() const;
147                ivec cumsizes() const;
148                int length() const {
149                        return len;
150                }
151                int id (int at) const {
152                        return ids (at);
153                }
154                int size (int at) const {
155                        return RV_SIZES (ids (at));
156                }
157                int time (int at) const {
158                        return times (at);
159                }
160                std::string name (int at) const {
161                        return RV_NAMES (ids (at));
162                }
163                void set_time (int at, int time0) {
164                        times (at) = time0;
165                }
166                //!@}
[271]167
[488]168                //! \name Algebra on Random Variables
169                //!@{
[271]170
[488]171                //! Find indices of self in another rv, \return ivec of the same size as self.
172                ivec findself (const RV &rv2) const;
173                //! Compare if \c rv2 is identical to this \c RV
174                bool equal (const RV &rv2) const;
175                //! Add (concat) another variable to the current one, \return true if all rv2 were added, false if rv2 is in conflict
176                bool add (const RV &rv2);
177                //! Subtract  another variable from the current one
178                RV subt (const RV &rv2) const;
179                //! Select only variables at indices ind
180                RV subselect (const ivec &ind) const;
[422]181
[488]182                //! Select only variables at indices ind
183                RV operator() (const ivec &ind) const {
184                        return subselect (ind);
185                }
[422]186
[488]187                //! Select from data vector starting at di1 to di2
188                RV operator() (int di1, int di2) const;
[422]189
[488]190                //! Shift \c time by delta.
191                void t (int delta);
192                //!@}
[271]193
[488]194                //!\name Relation to vectors
195                //!@{
[271]196
[536]197                //! generate \c str from rv, by expanding sizes
[488]198                str tostr() const;
199                //! when this rv is a part of bigger rv, this function returns indices of self in the data vector of the bigger crv.
200                //! Then, data can be copied via: data_of_this = cdata(ind);
201                ivec dataind (const RV &crv) const;
202                //! generate mutual indices when copying data between self and crv.
203                //! Data are copied via: data_of_this(selfi) = data_of_rv2(rv2i)
204                void dataind (const RV &rv2, ivec &selfi, ivec &rv2i) const;
205                //! Minimum time-offset
206                int mint() const {
207                        return min (times);
208                }
209                //!@}
[271]210
[488]211                /*! \brief UI for class RV (description of data vectors)
[357]212
[488]213                \code
214                rv = {
[531]215                  class = "RV"; // class name
[488]216                  // UNIQUE IDENTIFIER same names = same variable
[531]217                  names = ( "a", "b", "c", ...);   // which will be used e.g. in loggers
[357]218
[488]219                  //optional arguments
220                  sizes = [1, 2, 3, ...];         // (optional) default = ones()
221                  times = [-1, -2, 0, ...];       // time shifts with respect to current time (optional) default = zeros()
222                }
223                \endcode
224                */
225                void from_setting (const Setting &set);
[357]226
[488]227                // TODO dodelat void to_setting( Setting &set ) const;
228                //! Invalidate all named RVs. Use before initializing any RV instances, with care...
229                static void clear_all();
[270]230};
[488]231UIREGISTER (RV);
[529]232SHAREDPTR (RV);
[32]233
[145]234//! Concat two random variables
[488]235RV concat (const RV &rv1, const RV &rv2);
[2]236
[211]237//!Default empty RV that can be used as default argument
[270]238extern RV RV0;
[145]239
[85]240//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
[2]241
[488]242class fnc : public root
243{
244        protected:
245                //! Length of the output vector
246                int dimy;
247        public:
248                //!default constructor
249                fnc() {};
250                //! function evaluates numerical value of \f$f(x)\f$ at \f$x=\f$ \c cond
251                virtual vec eval (const vec &cond) {
252                        return vec (0);
253                };
[27]254
[488]255                //! function substitutes given value into an appropriate position
256                virtual void condition (const vec &val) {};
[28]257
[488]258                //! access function
259                int dimension() const {
260                        return dimy;
261                }
[270]262};
[2]263
[270]264class mpdf;
[7]265
[4]266//! Probability density function with numerical statistics, e.g. posterior density.
[32]267
[488]268class epdf : public root
269{
270        protected:
271                //! dimension of the random variable
272                int dim;
273                //! Description of the random variable
274                RV rv;
[32]275
[488]276        public:
277                /*! \name Constructors
278                 Construction of each epdf should support two types of constructors:
279                \li empty constructor,
280                \li copy constructor,
[271]281
[488]282                The following constructors should be supported for convenience:
283                \li constructor followed by calling \c set_parameters()
284                \li constructor accepting random variables calling \c set_rv()
[271]285
[488]286                 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.
287                @{*/
288                epdf() : dim (0), rv() {};
289                epdf (const epdf &e) : dim (e.dim), rv (e.rv) {};
290                epdf (const RV &rv0) : dim (rv0._dsize()) {
291                        set_rv (rv0);
292                };
293                void set_parameters (int dim0) {
294                        dim = dim0;
295                }
296                //!@}
[271]297
[488]298                //! \name Matematical Operations
299                //!@{
[271]300
[488]301                //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
302                virtual vec sample() const {
[565]303                        bdm_error ("not implemented");
304                        return vec();
[502]305                }
306
[488]307                //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
308                virtual mat sample_m (int N) const;
[502]309
[488]310                //! Compute log-probability of argument \c val
311                //! In case the argument is out of suport return -Infinity
312                virtual double evallog (const vec &val) const {
[565]313                        bdm_error ("not implemented");
[488]314                        return 0.0;
[477]315                }
[502]316
[488]317                //! Compute log-probability of multiple values argument \c val
[502]318                virtual vec evallog_m (const mat &Val) const;
319
320                //! Compute log-probability of multiple values argument \c val
321                virtual vec evallog_m (const Array<vec> &Avec) const;
322
[488]323                //! Return conditional density on the given RV, the remaining rvs will be in conditioning
[504]324                virtual shared_ptr<mpdf> condition (const RV &rv) const;
[271]325
[488]326                //! Return marginal density on the given RV, the remainig rvs are intergrated out
[504]327                virtual shared_ptr<epdf> marginal (const RV &rv) const;
[271]328
[488]329                //! return expected value
330                virtual vec mean() const {
[565]331                        bdm_error ("not implemneted");
332                        return vec();
333                }
[271]334
[488]335                //! return expected variance (not covariance!)
336                virtual vec variance() const {
[565]337                        bdm_error ("not implemneted");
338                        return vec();
339                }
340
[488]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                //!@}
[271]349
[488]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                //! @{
[271]355
[488]356                //!Name its rv
357                void set_rv (const RV &rv0) {
358                        rv = rv0;
[565]359                }
360
[488]361                //! True if rv is assigned
362                bool isnamed() const {
363                        bool b = (dim == rv._dsize());
364                        return b;
365                }
[565]366
[488]367                //! Return name (fails when isnamed is false)
368                const RV& _rv() const {
[565]369                        bdm_assert_debug (isnamed(), "");
[488]370                        return rv;
371                }
372                //!@}
[377]373
[488]374                //! \name Access to attributes
375                //! @{
[377]376
[488]377                //! Size of the random variable
378                int dimension() const {
379                        return dim;
[477]380                }
[488]381                //! Load from structure with elements:
382                //!  \code
383                //! { rv = {class="RV", names=(...),}; // RV describing meaning of random variable
384                //!   // elements of offsprings
385                //! }
386                //! \endcode
387                //!@}
388                void from_setting (const Setting &set) {
[527]389                        shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
[488]390                        if (r) {
391                                set_rv (*r);
392                        }
393                }
[377]394
[270]395};
[529]396SHAREDPTR(epdf);
[32]397
[536]398//! Conditional probability density, e.g. modeling \f$ f( x | y) \f$, where \f$ x \f$ is random variable, \c rv, and \f$ y \f$ is conditioning variable, \c rvc.
[488]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;
[461]409
[488]410        protected:
[536]411                //! set internal pointer \c ep to point to given \c iepdf
[488]412                void set_ep (epdf &iepdf) {
413                        ep = &iepdf;
414                }
[536]415                //! set internal pointer \c ep to point to given \c iepdf
[489]416                void set_ep (epdf *iepdfp) {
417                        ep = iepdfp;
418                }
[271]419
[488]420        public:
421                //! \name Constructors
422                //! @{
[2]423
[488]424                mpdf() : dimc (0), rvc(), ep (NULL) { }
[271]425
[488]426                mpdf (const mpdf &m) : dimc (m.dimc), rvc (m.rvc), ep (m.ep) { }
427                //!@}
[102]428
[488]429                //! \name Matematical operations
430                //!@{
[461]431
[488]432                //! 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
[565]433                virtual vec samplecond (const vec &cond) {
434                        bdm_error ("Not implemented");
435                        return vec();
436                }
[461]437
[488]438                //! 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
[532]439                virtual mat samplecond_m (const vec &cond, int N);
[461]440
[488]441                //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
[565]442                virtual double evallogcond (const vec &dt, const vec &cond) {
443                        bdm_error ("Not implemented");
444                        return 0.0;
445                }
[201]446
[488]447                //! Matrix version of evallogcond
[489]448                virtual vec evallogcond_m (const mat &Dt, const vec &cond) {
449                        vec v(Dt.cols());
450                        for(int i=0;i<Dt.cols();i++){v(i)= evallogcond(Dt.get_col(i),cond);}
451                        return v;
452                }
[271]453
[488]454                //! Array<vec> version of evallogcond
[565]455                virtual vec evallogcond_m (const Array<vec> &Dt, const vec &cond) {
456                        bdm_error ("Not implemented");
457                        return vec();
458                }
[271]459
[488]460                //! \name Access to attributes
461                //! @{
[461]462
[507]463                RV _rv() const {
[488]464                        return ep->_rv();
465                }
466                RV _rvc() {
467                        return rvc;
468                }
[527]469
470                int dimension() const {
[488]471                        return ep->dimension();
472                }
473                int dimensionc() {
474                        return dimc;
475                }
[461]476
[488]477                //! Load from structure with elements:
478                //!  \code
479                //! { class = "mpdf_offspring",
480                //!   rv = {class="RV", names=(...),}; // RV describing meaning of random variable
481                //!   rvc= {class="RV", names=(...),}; // RV describing meaning of random variable in condition
482                //!   // elements of offsprings
483                //! }
484                //! \endcode
485                //!@}
486                void from_setting (const Setting &set);
487                //!@}
488
489                //! \name Connection to other objects
490                //!@{
491                void set_rvc (const RV &rvc0) {
492                        rvc = rvc0;
493                }
494                void set_rv (const RV &rv0) {
495                        ep->set_rv (rv0);
496                }
497                bool isnamed() {
498                        return (ep->isnamed()) && (dimc == rvc._dsize());
499                }
500                //!@}
[270]501};
[529]502SHAREDPTR(mpdf);
[32]503
[536]504//! Mpdf with internal epdf that is modified by function \c condition
[487]505template <class EPDF>
[488]506class mpdf_internal: public mpdf
507{
[487]508        protected :
[536]509                //! Internal epdf used for sampling
[487]510                EPDF iepdf;
511        public:
512                //! constructor
[488]513                mpdf_internal() : mpdf(), iepdf() {set_ep (iepdf);}
[565]514
[487]515                //! Update \c iepdf so that it represents this mpdf conditioned on \c rvc = cond
516                //! This function provides convenient reimplementation in offsprings
[488]517                virtual void condition (const vec &cond) {
[565]518                        bdm_error ("Not implemented");
519                }
520
[487]521                //!access function to iepdf
[488]522                EPDF& e() {return iepdf;}
523
[487]524                //! Reimplements samplecond using \c condition()
[488]525                vec samplecond (const vec &cond);
[487]526                //! Reimplements evallogcond using \c condition()
[488]527                double evallogcond (const vec &val, const vec &cond);
528                //! Efficient version of evallogcond for matrices
529                virtual vec evallogcond_m (const mat &Dt, const vec &cond);
[487]530                //! Efficient version of evallogcond for Array<vec>
[488]531                virtual vec evallogcond_m (const Array<vec> &Dt, const vec &cond);
532                //! Efficient version of samplecond
533                virtual mat samplecond_m (const vec &cond, int N);
[487]534};
535
[270]536/*! \brief DataLink is a connection between two data vectors Up and Down
[2]537
[270]538Up can be longer than Down. Down must be fully present in Up (TODO optional)
539See chart:
540\dot
541digraph datalink {
[377]542  node [shape=record];
543  subgraph cluster0 {
544    label = "Up";
545      up [label="<1>|<2>|<3>|<4>|<5>"];
546    color = "white"
[270]547}
[377]548  subgraph cluster1{
549    label = "Down";
550    labelloc = b;
551      down [label="<1>|<2>|<3>"];
552    color = "white"
[270]553}
554    up:1 -> down:1;
555    up:3 -> down:2;
556    up:5 -> down:3;
557}
558\enddot
[263]559
[270]560*/
[488]561class datalink
562{
563        protected:
564                //! Remember how long val should be
565                int downsize;
[424]566
[488]567                //! Remember how long val of "Up" should be
568                int upsize;
[424]569
[488]570                //! val-to-val link, indices of the upper val
571                ivec v2v_up;
[424]572
[488]573        public:
574                //! Constructor
575                datalink() : downsize (0), upsize (0) { }
[545]576
577                //! Convenience constructor
[488]578                datalink (const RV &rv, const RV &rv_up) {
579                        set_connection (rv, rv_up);
580                }
[424]581
[488]582                //! set connection, rv must be fully present in rv_up
[545]583                void set_connection (const RV &rv, const RV &rv_up);
[271]584
[488]585                //! set connection using indices
[545]586                void set_connection (int ds, int us, const ivec &upind);
[286]587
[488]588                //! Get val for myself from val of "Up"
589                vec pushdown (const vec &val_up) {
[565]590                        bdm_assert_debug (upsize == val_up.length(), "Wrong val_up");
[488]591                        return get_vec (val_up, v2v_up);
592                }
[424]593
[488]594                //! Fill val of "Up" by my pieces
595                void pushup (vec &val_up, const vec &val) {
[565]596                        bdm_assert_debug (downsize == val.length(), "Wrong val");
597                        bdm_assert_debug (upsize == val_up.length(), "Wrong val_up");
[488]598                        set_subvector (val_up, v2v_up, val);
599                }
[270]600};
[115]601
[424]602//! Data link with a condition.
[488]603class datalink_m2e: public datalink
604{
605        protected:
606                //! Remember how long cond should be
607                int condsize;
[424]608
[488]609                //!upper_val-to-local_cond link, indices of the upper val
610                ivec v2c_up;
[424]611
[488]612                //!upper_val-to-local_cond link, indices of the local cond
613                ivec v2c_lo;
[192]614
[488]615        public:
616                //! Constructor
617                datalink_m2e() : condsize (0) { }
[545]618
[536]619                //! Set connection between vectors
[545]620                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up);
[424]621
[488]622                //!Construct condition
[545]623                vec get_cond (const vec &val_up);
624
[536]625                //! Copy corresponding values to Up.condition
[545]626                void pushup_cond (vec &val_up, const vec &val, const vec &cond);
[270]627};
[424]628
[192]629//!DataLink is a connection between mpdf and its superordinate (Up)
630//! This class links
[488]631class datalink_m2m: public datalink_m2e
632{
633        protected:
634                //!cond-to-cond link, indices of the upper cond
635                ivec c2c_up;
636                //!cond-to-cond link, indices of the local cond
637                ivec c2c_lo;
[424]638
[488]639        public:
640                //! Constructor
641                datalink_m2m() {};
[536]642                //! Set connection between the vectors
[488]643                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up) {
644                        datalink_m2e::set_connection (rv, rvc, rv_up);
645                        //establish c2c connection
646                        rvc.dataind (rvc_up, c2c_lo, c2c_up);
[565]647                        bdm_assert_debug (c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given");
[488]648                }
[424]649
[488]650                //! Get cond for myself from val and cond of "Up"
651                vec get_cond (const vec &val_up, const vec &cond_up) {
652                        vec tmp (condsize);
653                        set_subvector (tmp, v2c_lo, val_up (v2c_up));
654                        set_subvector (tmp, c2c_lo, cond_up (c2c_up));
655                        return tmp;
656                }
657                //! Fill
[190]658
[270]659};
[190]660
[270]661/*!
662@brief Class for storing results (and semi-results) of an experiment
[267]663
[270]664This 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.
665 */
[488]666class logger : public root
667{
668        protected:
669                //! RVs of all logged variables.
670                Array<RV> entries;
671                //! Names of logged quantities, e.g. names of algorithm variants
672                Array<string> names;
673        public:
674                //!Default constructor
675                logger() : entries (0), names (0) {}
[267]676
[488]677                //! returns an identifier which will be later needed for calling the \c logit() function
678                //! For empty RV it returns -1, this entry will be ignored by \c logit().
679                virtual int add (const RV &rv, string prefix = "") {
680                        int id;
681                        if (rv._dsize() > 0) {
682                                id = entries.length();
683                                names = concat (names, prefix);   // diff
684                                entries.set_length (id + 1, true);
685                                entries (id) = rv;
686                        } else {
687                                id = -1;
688                        }
689                        return id; // identifier of the last entry
[477]690                }
[267]691
[488]692                //! log this vector
[588]693                virtual void logit (int id, const vec &v) {bdm_error("Not implemented");};
[488]694                //! log this double
[588]695                virtual void logit (int id, const double &d) {bdm_error("Not implemented");};
[267]696
[488]697                //! Shifts storage position for another time step.
[588]698                virtual void step() {bdm_error("Not implemneted");};
[267]699
[488]700                //! Finalize storing information
701                virtual void finalize() {};
[267]702
[488]703                //! Initialize the storage
704                virtual void init() {};
[267]705
[270]706};
[267]707
[270]708/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
[190]709
[270]710*/
[488]711class mepdf : public mpdf
712{
[536]713                //! Internal shared pointer to epdf
[489]714                shared_ptr<epdf> iepdf;
[488]715        public:
716                //!Default constructor
717                mepdf() { }
[536]718                //! Set internal shared pointer
[488]719                mepdf (shared_ptr<epdf> em) {
[489]720                        iepdf = em;
721                        set_ep (*iepdf.get());
[488]722                        dimc = 0;
723                }
[461]724
[488]725                //! empty
[489]726                vec samplecond(const vec &cond){return iepdf->sample();}
727                double evallogcond(const vec &val, const vec &cond){return iepdf->evallog(val);}
[461]728
[488]729                //! Load from structure with elements:
730                //!  \code
731                //! { class = "mepdf",
732                //!   epdf = {class="epdf_offspring",...}
733                //! }
734                //! \endcode
735                //!@}
736                void from_setting (const Setting &set);
[270]737};
[488]738UIREGISTER (mepdf);
[529]739SHAREDPTR (mepdf);
[115]740
[507]741//! \brief Combines RVs from a list of mpdfs to a single one.
742RV get_composite_rv ( const Array<shared_ptr<mpdf> > &mpdfs, bool checkoverlap = false );
[175]743
[270]744/*! \brief Abstract class for discrete-time sources of data.
[12]745
[270]746The 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.
747Moreover, 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]748
[270]749*/
[32]750
[488]751class DS : public root
752{
753        protected:
754                int dtsize;
755                int utsize;
756                //!Description of data returned by \c getdata().
757                RV Drv;
758                //!Description of data witten by by \c write().
759                RV Urv; //
760                //! Remember its own index in Logger L
761                int L_dt, L_ut;
762        public:
763                //! default constructors
764                DS() : Drv(), Urv() {};
[565]765
[488]766                //! Returns full vector of observed data=[output, input]
767                virtual void getdata (vec &dt) {
[565]768                        bdm_error ("abstract class");
769                }
770
[488]771                //! Returns data records at indeces.
772                virtual void getdata (vec &dt, const ivec &indeces) {
[565]773                        bdm_error ("abstract class");
774                }
775
[488]776                //! Accepts action variable and schedule it for application.
777                virtual void write (vec &ut) {
[565]778                        bdm_error ("abstract class");
779                }
780
[488]781                //! Accepts action variables at specific indeces
782                virtual void write (vec &ut, const ivec &indeces) {
[565]783                        bdm_error ("abstract class");
784                }
[32]785
[488]786                //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
787                virtual void step() = 0;
[32]788
[488]789                //! Register DS for logging into logger L
790                virtual void log_add (logger &L) {
[565]791                        bdm_assert_debug (dtsize == Drv._dsize(), "invalid DS: dtsize different from Drv");
792                        bdm_assert_debug (utsize == Urv._dsize(), "invalid DS: utsize different from Urv");
[32]793
[488]794                        L_dt = L.add (Drv, "");
795                        L_ut = L.add (Urv, "");
796                }
797                //! Register DS for logging into logger L
798                virtual void logit (logger &L) {
799                        vec tmp (Drv._dsize() + Urv._dsize());
800                        getdata (tmp);
801                        // d is first in getdata
802                        L.logit (L_dt, tmp.left (Drv._dsize()));
803                        // u follows after d in getdata
804                        L.logit (L_ut, tmp.mid (Drv._dsize(), Urv._dsize()));
805                }
806                //!access function
807                virtual RV _drv() const {
808                        return concat (Drv, Urv);
809                }
810                //!access function
811                const RV& _urv() const {
812                        return Urv;
813                }
814                //! set random rvariables
815                virtual void set_drv (const  RV &drv, const RV &urv) {
816                        Drv = drv;
817                        Urv = urv;
818                }
[270]819};
[18]820
[270]821/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
[32]822
[283]823This object represents exact or approximate evaluation of the Bayes rule:
824\f[
825f(\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})}
826\f]
827
828Access to the resulting posterior density is via function \c posterior().
829
830As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
831It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
832
833Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
834\f[
835f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
836\f]
837
838The value of \f$ c_t \f$ is set by function condition().
839
[270]840*/
[32]841
[488]842class BM : public root
843{
844        protected:
845                //! Random variable of the data (optional)
846                RV drv;
847                //!Logarithm of marginalized data likelihood.
848                double ll;
849                //!  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.
850                bool evalll;
851        public:
852                //! \name Constructors
853                //! @{
[271]854
[488]855                BM() : ll (0), evalll (true), LIDs (4), LFlags (4) {
856                        LIDs = -1;/*empty IDs*/
857                        LFlags = 0;
858                        LFlags (0) = 1;  /*log only mean*/
859                };
860                BM (const BM &B) :  drv (B.drv), ll (B.ll), evalll (B.evalll) {}
861                //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
862                //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
863                virtual BM* _copy_() const {
864                        return NULL;
865                };
866                //!@}
[18]867
[488]868                //! \name Mathematical operations
869                //!@{
[271]870
[488]871                /*! \brief Incremental Bayes rule
872                @param dt vector of input data
873                */
874                virtual void bayes (const vec &dt) = 0;
875                //! Batch Bayes rule (columns of Dt are observations)
876                virtual void bayesB (const mat &Dt);
877                //! Evaluates predictive log-likelihood of the given data record
878                //! I.e. marginal likelihood of the data with the posterior integrated out.
879                virtual double logpred (const vec &dt) const {
[565]880                        bdm_error ("Not implemented");
[488]881                        return 0.0;
[477]882                }
[565]883
[488]884                //! Matrix version of logpred
885                vec logpred_m (const mat &dt) const {
886                        vec tmp (dt.cols());
887                        for (int i = 0; i < dt.cols(); i++) {
888                                tmp (i) = logpred (dt.get_col (i));
889                        }
890                        return tmp;
891                }
[32]892
[488]893                //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
894                virtual epdf* epredictor() const {
[565]895                        bdm_error ("Not implemented");
[488]896                        return NULL;
897                };
[536]898                //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
[488]899                virtual mpdf* predictor() const {
[565]900                        bdm_error ("Not implemented");
[488]901                        return NULL;
902                };
903                //!@}
[271]904
[488]905                //! \name Extension to conditional BM
906                //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
907                //! Alternatively, it can be used for automated connection to DS when the condition is observed
908                //!@{
[283]909
[488]910                //! Name of extension variable
911                RV rvc;
912                //! access function
913                const RV& _rvc() const {
914                        return rvc;
915                }
[283]916
[488]917                //! Substitute \c val for \c rvc.
918                virtual void condition (const vec &val) {
[565]919                        bdm_error ("Not implemented!");
920                }
[283]921
[488]922                //!@}
[283]923
924
[488]925                //! \name Access to attributes
926                //!@{
[271]927
[488]928                const RV& _drv() const {
929                        return drv;
930                }
931                void set_drv (const RV &rv) {
932                        drv = rv;
933                }
934                void set_rv (const RV &rv) {
935                        const_cast<epdf&> (posterior()).set_rv (rv);
936                }
937                double _ll() const {
938                        return ll;
939                }
940                void set_evalll (bool evl0) {
941                        evalll = evl0;
942                }
943                virtual const epdf& posterior() const = 0;
944                //!@}
[28]945
[488]946                //! \name Logging of results
947                //!@{
[200]948
[488]949                //! Set boolean options from a string, recognized are: "logbounds,logll"
950                virtual void set_options (const string &opt) {
951                        LFlags (0) = 1;
952                        if (opt.find ("logbounds") != string::npos) {
953                                LFlags (1) = 1;
954                                LFlags (2) = 1;
955                        }
956                        if (opt.find ("logll") != string::npos) {
957                                LFlags (3) = 1;
958                        }
[477]959                }
[488]960                //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
961                ivec LIDs;
[190]962
[488]963                //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
964                ivec LFlags;
965                //! Add all logged variables to a logger
966                virtual void log_add (logger &L, const string &name = "") {
967                        // internal
968                        RV r;
969                        if (posterior().isnamed()) {
970                                r = posterior()._rv();
971                        } else {
972                                r = RV ("est", posterior().dimension());
973                        };
[190]974
[488]975                        // Add mean value
976                        if (LFlags (0)) LIDs (0) = L.add (r, name + "mean_");
977                        if (LFlags (1)) LIDs (1) = L.add (r, name + "lb_");
978                        if (LFlags (2)) LIDs (2) = L.add (r, name + "ub_");
979                        if (LFlags (3)) LIDs (3) = L.add (RV ("ll", 1), name);              //TODO: "local" RV
[477]980                }
[488]981                virtual void logit (logger &L) {
982                        L.logit (LIDs (0), posterior().mean());
983                        if (LFlags (1) || LFlags (2)) {        //if one of them is off, its LID==-1 and will not be stored
984                                vec ub, lb;
985                                posterior().qbounds (lb, ub);
986                                L.logit (LIDs (1), lb);
987                                L.logit (LIDs (2), ub);
988                        }
989                        if (LFlags (3)) L.logit (LIDs (3), ll);
990                }
991                //!@}
[573]992                void from_setting (const Setting &set){
993                        shared_ptr<RV> r = UI::build<RV> ( set, "drv", UI::optional );
994                        if (r) {
995                                set_drv (*r);
996                        }
[586]997                        string opt;
998                        if(!UI::get(opt, set, "options", UI::optional)) {
999                                set_options(opt);
1000                        }
[573]1001                }
1002
[270]1003};
[32]1004
[529]1005typedef Array<shared_ptr<epdf> > epdf_array;
1006
1007typedef Array<shared_ptr<mpdf> > mpdf_array;
1008
[488]1009template<class EPDF>
1010vec mpdf_internal<EPDF>::samplecond (const vec &cond)
1011{
1012        condition (cond);
1013        vec temp = iepdf.sample();
1014        return temp;
1015}
[339]1016
[488]1017template<class EPDF>
1018mat mpdf_internal<EPDF>::samplecond_m (const vec &cond, int N)
1019{
1020        condition (cond);
1021        mat temp (dimension(), N);
1022        vec smp (dimension());
1023        for (int i = 0; i < N; i++) {
1024                smp = iepdf.sample();
1025                temp.set_col (i, smp);
1026        }
1027
1028        return temp;
1029}
1030
1031template<class EPDF>
1032double mpdf_internal<EPDF>::evallogcond (const vec &dt, const vec &cond)
1033{
1034        double tmp;
1035        condition (cond);
1036        tmp = iepdf.evallog (dt);
1037        return tmp;
1038}
1039
1040template<class EPDF>
1041vec mpdf_internal<EPDF>::evallogcond_m (const mat &Dt, const vec &cond)
1042{
1043        condition (cond);
1044        return iepdf.evallog_m (Dt);
1045}
1046
1047template<class EPDF>
1048vec mpdf_internal<EPDF>::evallogcond_m (const Array<vec> &Dt, const vec &cond)
1049{
1050        condition (cond);
1051        return iepdf.evallog_m (Dt);
1052}
1053
[254]1054}; //namespace
[384]1055#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.