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

Revision 598, 31.8 kB (checked in by smidl, 15 years ago)

new buffered datalink ( #32 ) and new datasources - all with minor trivial tests

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