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

Revision 565, 27.2 kB (checked in by vbarta, 15 years ago)

using own error macros (basically copied from IT++, but never aborting)

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