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
Line 
1/*!
2  \file
3  \brief Basic structures of probability calculus: random variables, probability densities, Bayes rule
4  \author Vaclav Smidl.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
13#ifndef BDMBASE_H
14#define BDMBASE_H
15
16#include <map>
17
18#include "../itpp_ext.h"
19#include "../bdmroot.h"
20#include "../shared_ptr.h"
21#include "user_info.h"
22
23using namespace libconfig;
24using namespace itpp;
25using namespace std;
26
27namespace bdm
28{
29
30typedef std::map<string, int> RVmap;
31//! Internal global variable storing sizes of RVs
32extern ivec RV_SIZES;
33//! Internal global variable storing names of RVs
34extern Array<string> RV_NAMES;
35
36//! Structure of RV, i.e. RVs expanded into a flat list of IDs, used for debugging.
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) {
46                        bdm_assert_debug (times0.length() == ids0.length(), "Incompatible input");
47                };
48};
49
50/*!
51* \brief Class representing variables, most often random variables
52
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.
54
55The class is implemented using global variables to assure uniqueness of description:
56
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*/
87
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;
99
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                //!@{
107
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                }
112
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                }
117
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                }
122
123                //! Constructor of empty RV
124                RV() : dsize (0), len (0), ids (0), times (0) {}
125
126                //! Constructor of a single RV with given id
127                RV (string name, int sz, int tm = 0);
128
129                // compiler-generated copy constructor is used
130                //!@}
131
132                //! \name Access functions
133                //!@{
134
135                //! State output, e.g. for debugging.
136                friend std::ostream &operator<< (std::ostream &os, const RV &rv);
137
138                int _dsize() const {
139                        return dsize;
140                }
141
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                //!@}
164
165                //! \name Algebra on Random Variables
166                //!@{
167
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;
178
179                //! Select only variables at indices ind
180                RV operator() (const ivec &ind) const {
181                        return subselect (ind);
182                }
183
184                //! Select from data vector starting at di1 to di2
185                RV operator() (int di1, int di2) const;
186
187                //! Shift \c time by delta.
188                void t (int delta);
189                //!@}
190
191                //!\name Relation to vectors
192                //!@{
193
194                //! generate \c str from rv, by expanding sizes
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                //!@}
207
208                /*! \brief UI for class RV (description of data vectors)
209
210                \code
211                rv = {
212                  class = "RV"; // class name
213                  // UNIQUE IDENTIFIER same names = same variable
214                  names = ( "a", "b", "c", ...);   // which will be used e.g. in loggers
215
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);
223
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();
227};
228UIREGISTER (RV);
229SHAREDPTR (RV);
230
231//! Concat two random variables
232RV concat (const RV &rv1, const RV &rv2);
233
234//!Default empty RV that can be used as default argument
235extern RV RV0;
236
237//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
238
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                };
251
252                //! function substitutes given value into an appropriate position
253                virtual void condition (const vec &val) {};
254
255                //! access function
256                int dimension() const {
257                        return dimy;
258                }
259};
260
261class mpdf;
262
263//! Probability density function with numerical statistics, e.g. posterior density.
264
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;
272
273        public:
274                /*! \name Constructors
275                 Construction of each epdf should support two types of constructors:
276                \li empty constructor,
277                \li copy constructor,
278
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()
282
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                //!@}
294
295                //! \name Matematical Operations
296                //!@{
297
298                //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
299                virtual vec sample() const {
300                        bdm_error ("not implemented");
301                        return vec();
302                }
303
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;
306
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 {
310                        bdm_error ("not implemented");
311                        return 0.0;
312                }
313
314                //! Compute log-probability of multiple values argument \c val
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
320                //! Return conditional density on the given RV, the remaining rvs will be in conditioning
321                virtual shared_ptr<mpdf> condition (const RV &rv) const;
322
323                //! Return marginal density on the given RV, the remainig rvs are intergrated out
324                virtual shared_ptr<epdf> marginal (const RV &rv) const;
325
326                //! return expected value
327                virtual vec mean() const {
328                        bdm_error ("not implemneted");
329                        return vec();
330                }
331
332                //! return expected variance (not covariance!)
333                virtual vec variance() const {
334                        bdm_error ("not implemneted");
335                        return vec();
336                }
337
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                //!@}
346
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                //! @{
352
353                //!Name its rv
354                void set_rv (const RV &rv0) {
355                        rv = rv0;
356                }
357
358                //! True if rv is assigned
359                bool isnamed() const {
360                        bool b = (dim == rv._dsize());
361                        return b;
362                }
363
364                //! Return name (fails when isnamed is false)
365                const RV& _rv() const {
366                        bdm_assert_debug (isnamed(), "");
367                        return rv;
368                }
369                //!@}
370
371                //! \name Access to attributes
372                //! @{
373
374                //! Size of the random variable
375                int dimension() const {
376                        return dim;
377                }
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) {
386                        shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
387                        if (r) {
388                                set_rv (*r);
389                        }
390                }
391
392};
393SHAREDPTR(epdf);
394
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.
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;
406
407        protected:
408                //! set internal pointer \c ep to point to given \c iepdf
409                void set_ep (epdf &iepdf) {
410                        ep = &iepdf;
411                }
412                //! set internal pointer \c ep to point to given \c iepdf
413                void set_ep (epdf *iepdfp) {
414                        ep = iepdfp;
415                }
416
417        public:
418                //! \name Constructors
419                //! @{
420
421                mpdf() : dimc (0), rvc(), ep (NULL) { }
422
423                mpdf (const mpdf &m) : dimc (m.dimc), rvc (m.rvc), ep (m.ep) { }
424                //!@}
425
426                //! \name Matematical operations
427                //!@{
428
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
430                virtual vec samplecond (const vec &cond) {
431                        bdm_error ("Not implemented");
432                        return vec();
433                }
434
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
436                virtual mat samplecond_m (const vec &cond, int N);
437
438                //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
439                virtual double evallogcond (const vec &dt, const vec &cond) {
440                        bdm_error ("Not implemented");
441                        return 0.0;
442                }
443
444                //! Matrix version of evallogcond
445                virtual vec evallogcond_m (const mat &Dt, const vec &cond) {
446                        vec v(Dt.cols());
447                        for(int i=0;i<Dt.cols();i++){v(i)= evallogcond(Dt.get_col(i),cond);}
448                        return v;
449                }
450
451                //! Array<vec> version of evallogcond
452                virtual vec evallogcond_m (const Array<vec> &Dt, const vec &cond) {
453                        bdm_error ("Not implemented");
454                        return vec();
455                }
456
457                //! \name Access to attributes
458                //! @{
459
460                RV _rv() const {
461                        return ep->_rv();
462                }
463                RV _rvc() {
464                        return rvc;
465                }
466
467                int dimension() const {
468                        return ep->dimension();
469                }
470                int dimensionc() {
471                        return dimc;
472                }
473
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                //!@}
498};
499SHAREDPTR(mpdf);
500
501//! Mpdf with internal epdf that is modified by function \c condition
502template <class EPDF>
503class mpdf_internal: public mpdf
504{
505        protected :
506                //! Internal epdf used for sampling
507                EPDF iepdf;
508        public:
509                //! constructor
510                mpdf_internal() : mpdf(), iepdf() {set_ep (iepdf);}
511
512                //! Update \c iepdf so that it represents this mpdf conditioned on \c rvc = cond
513                //! This function provides convenient reimplementation in offsprings
514                virtual void condition (const vec &cond) {
515                        bdm_error ("Not implemented");
516                }
517
518                //!access function to iepdf
519                EPDF& e() {return iepdf;}
520
521                //! Reimplements samplecond using \c condition()
522                vec samplecond (const vec &cond);
523                //! Reimplements evallogcond using \c condition()
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);
527                //! Efficient version of evallogcond for Array<vec>
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);
531};
532
533/*! \brief DataLink is a connection between two data vectors Up and Down
534
535Up can be longer than Down. Down must be fully present in Up (TODO optional)
536See chart:
537\dot
538digraph datalink {
539  node [shape=record];
540  subgraph cluster0 {
541    label = "Up";
542      up [label="<1>|<2>|<3>|<4>|<5>"];
543    color = "white"
544}
545  subgraph cluster1{
546    label = "Down";
547    labelloc = b;
548      down [label="<1>|<2>|<3>"];
549    color = "white"
550}
551    up:1 -> down:1;
552    up:3 -> down:2;
553    up:5 -> down:3;
554}
555\enddot
556
557*/
558class datalink
559{
560        protected:
561                //! Remember how long val should be
562                int downsize;
563
564                //! Remember how long val of "Up" should be
565                int upsize;
566
567                //! val-to-val link, indices of the upper val
568                ivec v2v_up;
569
570        public:
571                //! Constructor
572                datalink() : downsize (0), upsize (0) { }
573
574                //! Convenience constructor
575                datalink (const RV &rv, const RV &rv_up) {
576                        set_connection (rv, rv_up);
577                }
578
579                //! set connection, rv must be fully present in rv_up
580                void set_connection (const RV &rv, const RV &rv_up);
581
582                //! set connection using indices
583                void set_connection (int ds, int us, const ivec &upind);
584
585                //! Get val for myself from val of "Up"
586                vec pushdown (const vec &val_up) {
587                        bdm_assert_debug (upsize == val_up.length(), "Wrong val_up");
588                        return get_vec (val_up, v2v_up);
589                }
590
591                //! Fill val of "Up" by my pieces
592                void pushup (vec &val_up, const vec &val) {
593                        bdm_assert_debug (downsize == val.length(), "Wrong val");
594                        bdm_assert_debug (upsize == val_up.length(), "Wrong val_up");
595                        set_subvector (val_up, v2v_up, val);
596                }
597};
598
599//! Data link with a condition.
600class datalink_m2e: public datalink
601{
602        protected:
603                //! Remember how long cond should be
604                int condsize;
605
606                //!upper_val-to-local_cond link, indices of the upper val
607                ivec v2c_up;
608
609                //!upper_val-to-local_cond link, indices of the local cond
610                ivec v2c_lo;
611
612        public:
613                //! Constructor
614                datalink_m2e() : condsize (0) { }
615
616                //! Set connection between vectors
617                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up);
618
619                //!Construct condition
620                vec get_cond (const vec &val_up);
621
622                //! Copy corresponding values to Up.condition
623                void pushup_cond (vec &val_up, const vec &val, const vec &cond);
624};
625
626//!DataLink is a connection between mpdf and its superordinate (Up)
627//! This class links
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;
635
636        public:
637                //! Constructor
638                datalink_m2m() {};
639                //! Set connection between the vectors
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);
644                        bdm_assert_debug (c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given");
645                }
646
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
655
656};
657
658/*!
659@brief Class for storing results (and semi-results) of an experiment
660
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 */
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) {}
673
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
687                }
688
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;
693
694                //! Shifts storage position for another time step.
695                virtual void step() = 0;
696
697                //! Finalize storing information
698                virtual void finalize() {};
699
700                //! Initialize the storage
701                virtual void init() {};
702
703};
704
705/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
706
707*/
708class mepdf : public mpdf
709{
710                //! Internal shared pointer to epdf
711                shared_ptr<epdf> iepdf;
712        public:
713                //!Default constructor
714                mepdf() { }
715                //! Set internal shared pointer
716                mepdf (shared_ptr<epdf> em) {
717                        iepdf = em;
718                        set_ep (*iepdf.get());
719                        dimc = 0;
720                }
721
722                //! empty
723                vec samplecond(const vec &cond){return iepdf->sample();}
724                double evallogcond(const vec &val, const vec &cond){return iepdf->evallog(val);}
725
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);
734};
735UIREGISTER (mepdf);
736SHAREDPTR (mepdf);
737
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 );
740
741/*! \brief Abstract class for discrete-time sources of data.
742
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).
745
746*/
747
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() {};
762
763                //! Returns full vector of observed data=[output, input]
764                virtual void getdata (vec &dt) {
765                        bdm_error ("abstract class");
766                }
767
768                //! Returns data records at indeces.
769                virtual void getdata (vec &dt, const ivec &indeces) {
770                        bdm_error ("abstract class");
771                }
772
773                //! Accepts action variable and schedule it for application.
774                virtual void write (vec &ut) {
775                        bdm_error ("abstract class");
776                }
777
778                //! Accepts action variables at specific indeces
779                virtual void write (vec &ut, const ivec &indeces) {
780                        bdm_error ("abstract class");
781                }
782
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;
785
786                //! Register DS for logging into logger L
787                virtual void log_add (logger &L) {
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");
790
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                }
816};
817
818/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
819
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
837*/
838
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                //! @{
851
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                //!@}
864
865                //! \name Mathematical operations
866                //!@{
867
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 {
877                        bdm_error ("Not implemented");
878                        return 0.0;
879                }
880
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                }
889
890                //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
891                virtual epdf* epredictor() const {
892                        bdm_error ("Not implemented");
893                        return NULL;
894                };
895                //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
896                virtual mpdf* predictor() const {
897                        bdm_error ("Not implemented");
898                        return NULL;
899                };
900                //!@}
901
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                //!@{
906
907                //! Name of extension variable
908                RV rvc;
909                //! access function
910                const RV& _rvc() const {
911                        return rvc;
912                }
913
914                //! Substitute \c val for \c rvc.
915                virtual void condition (const vec &val) {
916                        bdm_error ("Not implemented!");
917                }
918
919                //!@}
920
921
922                //! \name Access to attributes
923                //!@{
924
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                //!@}
942
943                //! \name Logging of results
944                //!@{
945
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                        }
956                }
957                //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
958                ivec LIDs;
959
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                        };
971
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
977                }
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                //!@}
989};
990
991typedef Array<shared_ptr<epdf> > epdf_array;
992
993typedef Array<shared_ptr<mpdf> > mpdf_array;
994
995template<class EPDF>
996vec mpdf_internal<EPDF>::samplecond (const vec &cond)
997{
998        condition (cond);
999        vec temp = iepdf.sample();
1000        return temp;
1001}
1002
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
1040}; //namespace
1041#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.