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

Revision 586, 27.5 kB (checked in by smidl, 15 years ago)

redesign of ctrl LQ control for arx

  • 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                //! access function
143                const ivec& _ids() const { return ids;}
144
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                //!@}
167
168                //! \name Algebra on Random Variables
169                //!@{
170
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;
181
182                //! Select only variables at indices ind
183                RV operator() (const ivec &ind) const {
184                        return subselect (ind);
185                }
186
187                //! Select from data vector starting at di1 to di2
188                RV operator() (int di1, int di2) const;
189
190                //! Shift \c time by delta.
191                void t (int delta);
192                //!@}
193
194                //!\name Relation to vectors
195                //!@{
196
197                //! generate \c str from rv, by expanding sizes
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                //!@}
210
211                /*! \brief UI for class RV (description of data vectors)
212
213                \code
214                rv = {
215                  class = "RV"; // class name
216                  // UNIQUE IDENTIFIER same names = same variable
217                  names = ( "a", "b", "c", ...);   // which will be used e.g. in loggers
218
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);
226
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();
230};
231UIREGISTER (RV);
232SHAREDPTR (RV);
233
234//! Concat two random variables
235RV concat (const RV &rv1, const RV &rv2);
236
237//!Default empty RV that can be used as default argument
238extern RV RV0;
239
240//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
241
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                };
254
255                //! function substitutes given value into an appropriate position
256                virtual void condition (const vec &val) {};
257
258                //! access function
259                int dimension() const {
260                        return dimy;
261                }
262};
263
264class mpdf;
265
266//! Probability density function with numerical statistics, e.g. posterior density.
267
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;
275
276        public:
277                /*! \name Constructors
278                 Construction of each epdf should support two types of constructors:
279                \li empty constructor,
280                \li copy constructor,
281
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()
285
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                //!@}
297
298                //! \name Matematical Operations
299                //!@{
300
301                //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
302                virtual vec sample() const {
303                        bdm_error ("not implemented");
304                        return vec();
305                }
306
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;
309
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 {
313                        bdm_error ("not implemented");
314                        return 0.0;
315                }
316
317                //! Compute log-probability of multiple values argument \c val
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
323                //! Return conditional density on the given RV, the remaining rvs will be in conditioning
324                virtual shared_ptr<mpdf> condition (const RV &rv) const;
325
326                //! Return marginal density on the given RV, the remainig rvs are intergrated out
327                virtual shared_ptr<epdf> marginal (const RV &rv) const;
328
329                //! return expected value
330                virtual vec mean() const {
331                        bdm_error ("not implemneted");
332                        return vec();
333                }
334
335                //! return expected variance (not covariance!)
336                virtual vec variance() const {
337                        bdm_error ("not implemneted");
338                        return vec();
339                }
340
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                //!@}
349
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                //! @{
355
356                //!Name its rv
357                void set_rv (const RV &rv0) {
358                        rv = rv0;
359                }
360
361                //! True if rv is assigned
362                bool isnamed() const {
363                        bool b = (dim == rv._dsize());
364                        return b;
365                }
366
367                //! Return name (fails when isnamed is false)
368                const RV& _rv() const {
369                        bdm_assert_debug (isnamed(), "");
370                        return rv;
371                }
372                //!@}
373
374                //! \name Access to attributes
375                //! @{
376
377                //! Size of the random variable
378                int dimension() const {
379                        return dim;
380                }
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) {
389                        shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
390                        if (r) {
391                                set_rv (*r);
392                        }
393                }
394
395};
396SHAREDPTR(epdf);
397
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.
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;
409
410        protected:
411                //! set internal pointer \c ep to point to given \c iepdf
412                void set_ep (epdf &iepdf) {
413                        ep = &iepdf;
414                }
415                //! set internal pointer \c ep to point to given \c iepdf
416                void set_ep (epdf *iepdfp) {
417                        ep = iepdfp;
418                }
419
420        public:
421                //! \name Constructors
422                //! @{
423
424                mpdf() : dimc (0), rvc(), ep (NULL) { }
425
426                mpdf (const mpdf &m) : dimc (m.dimc), rvc (m.rvc), ep (m.ep) { }
427                //!@}
428
429                //! \name Matematical operations
430                //!@{
431
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
433                virtual vec samplecond (const vec &cond) {
434                        bdm_error ("Not implemented");
435                        return vec();
436                }
437
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
439                virtual mat samplecond_m (const vec &cond, int N);
440
441                //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
442                virtual double evallogcond (const vec &dt, const vec &cond) {
443                        bdm_error ("Not implemented");
444                        return 0.0;
445                }
446
447                //! Matrix version of evallogcond
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                }
453
454                //! Array<vec> version of evallogcond
455                virtual vec evallogcond_m (const Array<vec> &Dt, const vec &cond) {
456                        bdm_error ("Not implemented");
457                        return vec();
458                }
459
460                //! \name Access to attributes
461                //! @{
462
463                RV _rv() const {
464                        return ep->_rv();
465                }
466                RV _rvc() {
467                        return rvc;
468                }
469
470                int dimension() const {
471                        return ep->dimension();
472                }
473                int dimensionc() {
474                        return dimc;
475                }
476
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                //!@}
501};
502SHAREDPTR(mpdf);
503
504//! Mpdf with internal epdf that is modified by function \c condition
505template <class EPDF>
506class mpdf_internal: public mpdf
507{
508        protected :
509                //! Internal epdf used for sampling
510                EPDF iepdf;
511        public:
512                //! constructor
513                mpdf_internal() : mpdf(), iepdf() {set_ep (iepdf);}
514
515                //! Update \c iepdf so that it represents this mpdf conditioned on \c rvc = cond
516                //! This function provides convenient reimplementation in offsprings
517                virtual void condition (const vec &cond) {
518                        bdm_error ("Not implemented");
519                }
520
521                //!access function to iepdf
522                EPDF& e() {return iepdf;}
523
524                //! Reimplements samplecond using \c condition()
525                vec samplecond (const vec &cond);
526                //! Reimplements evallogcond using \c condition()
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);
530                //! Efficient version of evallogcond for Array<vec>
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);
534};
535
536/*! \brief DataLink is a connection between two data vectors Up and Down
537
538Up can be longer than Down. Down must be fully present in Up (TODO optional)
539See chart:
540\dot
541digraph datalink {
542  node [shape=record];
543  subgraph cluster0 {
544    label = "Up";
545      up [label="<1>|<2>|<3>|<4>|<5>"];
546    color = "white"
547}
548  subgraph cluster1{
549    label = "Down";
550    labelloc = b;
551      down [label="<1>|<2>|<3>"];
552    color = "white"
553}
554    up:1 -> down:1;
555    up:3 -> down:2;
556    up:5 -> down:3;
557}
558\enddot
559
560*/
561class datalink
562{
563        protected:
564                //! Remember how long val should be
565                int downsize;
566
567                //! Remember how long val of "Up" should be
568                int upsize;
569
570                //! val-to-val link, indices of the upper val
571                ivec v2v_up;
572
573        public:
574                //! Constructor
575                datalink() : downsize (0), upsize (0) { }
576
577                //! Convenience constructor
578                datalink (const RV &rv, const RV &rv_up) {
579                        set_connection (rv, rv_up);
580                }
581
582                //! set connection, rv must be fully present in rv_up
583                void set_connection (const RV &rv, const RV &rv_up);
584
585                //! set connection using indices
586                void set_connection (int ds, int us, const ivec &upind);
587
588                //! Get val for myself from val of "Up"
589                vec pushdown (const vec &val_up) {
590                        bdm_assert_debug (upsize == val_up.length(), "Wrong val_up");
591                        return get_vec (val_up, v2v_up);
592                }
593
594                //! Fill val of "Up" by my pieces
595                void pushup (vec &val_up, const vec &val) {
596                        bdm_assert_debug (downsize == val.length(), "Wrong val");
597                        bdm_assert_debug (upsize == val_up.length(), "Wrong val_up");
598                        set_subvector (val_up, v2v_up, val);
599                }
600};
601
602//! Data link with a condition.
603class datalink_m2e: public datalink
604{
605        protected:
606                //! Remember how long cond should be
607                int condsize;
608
609                //!upper_val-to-local_cond link, indices of the upper val
610                ivec v2c_up;
611
612                //!upper_val-to-local_cond link, indices of the local cond
613                ivec v2c_lo;
614
615        public:
616                //! Constructor
617                datalink_m2e() : condsize (0) { }
618
619                //! Set connection between vectors
620                void set_connection (const RV &rv, const RV &rvc, const RV &rv_up);
621
622                //!Construct condition
623                vec get_cond (const vec &val_up);
624
625                //! Copy corresponding values to Up.condition
626                void pushup_cond (vec &val_up, const vec &val, const vec &cond);
627};
628
629//!DataLink is a connection between mpdf and its superordinate (Up)
630//! This class links
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;
638
639        public:
640                //! Constructor
641                datalink_m2m() {};
642                //! Set connection between the vectors
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);
647                        bdm_assert_debug (c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given");
648                }
649
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
658
659};
660
661/*!
662@brief Class for storing results (and semi-results) of an experiment
663
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 */
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) {}
676
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
690                }
691
692                //! log this vector
693                virtual void logit (int id, const vec &v) = 0;
694                //! log this double
695                virtual void logit (int id, const double &d) = 0;
696
697                //! Shifts storage position for another time step.
698                virtual void step() = 0;
699
700                //! Finalize storing information
701                virtual void finalize() {};
702
703                //! Initialize the storage
704                virtual void init() {};
705
706};
707
708/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
709
710*/
711class mepdf : public mpdf
712{
713                //! Internal shared pointer to epdf
714                shared_ptr<epdf> iepdf;
715        public:
716                //!Default constructor
717                mepdf() { }
718                //! Set internal shared pointer
719                mepdf (shared_ptr<epdf> em) {
720                        iepdf = em;
721                        set_ep (*iepdf.get());
722                        dimc = 0;
723                }
724
725                //! empty
726                vec samplecond(const vec &cond){return iepdf->sample();}
727                double evallogcond(const vec &val, const vec &cond){return iepdf->evallog(val);}
728
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);
737};
738UIREGISTER (mepdf);
739SHAREDPTR (mepdf);
740
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 );
743
744/*! \brief Abstract class for discrete-time sources of data.
745
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).
748
749*/
750
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() {};
765
766                //! Returns full vector of observed data=[output, input]
767                virtual void getdata (vec &dt) {
768                        bdm_error ("abstract class");
769                }
770
771                //! Returns data records at indeces.
772                virtual void getdata (vec &dt, const ivec &indeces) {
773                        bdm_error ("abstract class");
774                }
775
776                //! Accepts action variable and schedule it for application.
777                virtual void write (vec &ut) {
778                        bdm_error ("abstract class");
779                }
780
781                //! Accepts action variables at specific indeces
782                virtual void write (vec &ut, const ivec &indeces) {
783                        bdm_error ("abstract class");
784                }
785
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;
788
789                //! Register DS for logging into logger L
790                virtual void log_add (logger &L) {
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");
793
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                }
819};
820
821/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
822
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
840*/
841
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                //! @{
854
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                //!@}
867
868                //! \name Mathematical operations
869                //!@{
870
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 {
880                        bdm_error ("Not implemented");
881                        return 0.0;
882                }
883
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                }
892
893                //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
894                virtual epdf* epredictor() const {
895                        bdm_error ("Not implemented");
896                        return NULL;
897                };
898                //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
899                virtual mpdf* predictor() const {
900                        bdm_error ("Not implemented");
901                        return NULL;
902                };
903                //!@}
904
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                //!@{
909
910                //! Name of extension variable
911                RV rvc;
912                //! access function
913                const RV& _rvc() const {
914                        return rvc;
915                }
916
917                //! Substitute \c val for \c rvc.
918                virtual void condition (const vec &val) {
919                        bdm_error ("Not implemented!");
920                }
921
922                //!@}
923
924
925                //! \name Access to attributes
926                //!@{
927
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                //!@}
945
946                //! \name Logging of results
947                //!@{
948
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                        }
959                }
960                //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
961                ivec LIDs;
962
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                        };
974
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
980                }
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                //!@}
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                        }
997                        string opt;
998                        if(!UI::get(opt, set, "options", UI::optional)) {
999                                set_options(opt);
1000                        }
1001                }
1002
1003};
1004
1005typedef Array<shared_ptr<epdf> > epdf_array;
1006
1007typedef Array<shared_ptr<mpdf> > mpdf_array;
1008
1009template<class EPDF>
1010vec mpdf_internal<EPDF>::samplecond (const vec &cond)
1011{
1012        condition (cond);
1013        vec temp = iepdf.sample();
1014        return temp;
1015}
1016
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
1054}; //namespace
1055#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.