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

Revision 600, 31.9 kB (checked in by mido, 15 years ago)

presun globalnich veci v RV dovnitr tridy kde byly zadefinovany jako staticke promenne
(plus drobne zacisteni dokumentace a adresarove struktury)

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