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

Revision 489, 28.4 kB (checked in by smidl, 15 years ago)

Mpdf redesing is complet - all tests pass (except mlnorm<chmat> which is irrelevant)

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