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

Revision 603, 32.6 kB (checked in by smidl, 15 years ago)

datasources revisited...

  • 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 times.length()>0 ? min (times) : 0;
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;
678        //! v2h: indeces of up too be pushed to h
679        ivec v2h_up;
680public:
681
682        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
683        //! push current data to history
684        void step ( const vec &val_up ) {
685                if ( Hrv._dsize() > 0 ) {
686                        history.shift_right ( 0, Hrv._dsize() );
687                  history.set_subvector ( 0, val_up(v2h_up) ); // write U after Drv
688                }
689        }
690        //! Get val for myself from val of "Up"
691        vec pushdown ( const vec &val_up ) {
692                vec tmp ( downsize );
693                filldown ( val_up, tmp );
694                return tmp;
695        }
696
697        void filldown ( const vec &val_up, vec &val_down ) {
698                bdm_assert_debug ( val_down.length() >= downsize, "short val_down" );
699
700                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) ); // copy direct values
701                set_subvector ( val_down, h2v_down, history ( h2v_hist ) ); // copy delayed values
702        }
703
704        void set_connection ( const RV &rv, const RV &rv_up ) {
705                // create link between up and down
706                datalink_part::set_connection ( rv, rv_up );
707
708                // create rvs of history
709                // we can store only what we get in rv_up - everything else is removed
710                ivec valid_ids = rv.findself_ids ( rv_up );
711                RV rv_hist = rv.subselect ( find ( valid_ids >= 0 ) ); // select only rvs that are in rv_up
712          RV rv_hist0 =rv_hist.remove_time();  // these RVs will form history at time =0
713          v2h_up = rv_hist0.dataind(rv_up); // indeces of elements of rv_up to be copied
714          // now we need to know what is needed from Up
715                rv_hist = rv_hist.expand_delayes(); // full regressor - including time 0
716          Hrv=rv_hist.subt(rv_hist0);   // remove time 0
717                history = zeros ( Hrv._dsize() );
718
719                Hrv.dataind ( rv, h2v_hist, h2v_down );
720
721                downsize = v2v_down.length() + h2v_down.length();
722                upsize = v2v_up.length();
723        }
724};
725
726//! buffered datalink from 2 vectors to 1
727class datalink_2to1_buffered {
728protected:
729        datalink_buffered dl1;
730        datalink_buffered dl2;
731public:
732        //! set connection between RVs
733        void set_connection ( const RV &rv, const RV &rv_up1, const RV &rv_up2 ) {
734                dl1.set_connection ( rv, rv_up1 );
735                dl2.set_connection ( rv, rv_up2 );
736        }
737        void filldown ( const vec &val1, const vec &val2, vec &val_down ) {
738                bdm_assert_debug ( val_down.length() >= dl1._downsize() + dl2._downsize(), "short val_down" );
739                dl1.filldown ( val1, val_down );
740                dl2.filldown ( val2, val_down );
741        }
742        void step ( const vec &dt, const vec &ut ) {
743                dl1.step ( dt );
744                dl2.step ( ut );
745        }
746};
747
748
749
750//! Data link with a condition.
751class datalink_m2e: public datalink {
752protected:
753        //! Remember how long cond should be
754        int condsize;
755
756        //!upper_val-to-local_cond link, indices of the upper val
757        ivec v2c_up;
758
759        //!upper_val-to-local_cond link, indices of the local cond
760        ivec v2c_lo;
761
762public:
763        //! Constructor
764        datalink_m2e() : condsize ( 0 ) { }
765
766        //! Set connection between vectors
767        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
768
769        //!Construct condition
770        vec get_cond ( const vec &val_up );
771
772        //! Copy corresponding values to Up.condition
773        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
774};
775
776//!DataLink is a connection between mpdf and its superordinate (Up)
777//! This class links
778class datalink_m2m: public datalink_m2e {
779protected:
780        //!cond-to-cond link, indices of the upper cond
781        ivec c2c_up;
782        //!cond-to-cond link, indices of the local cond
783        ivec c2c_lo;
784
785public:
786        //! Constructor
787        datalink_m2m() {};
788        //! Set connection between the vectors
789        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
790                datalink_m2e::set_connection ( rv, rvc, rv_up );
791                //establish c2c connection
792                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
793                bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
794        }
795
796        //! Get cond for myself from val and cond of "Up"
797        vec get_cond ( const vec &val_up, const vec &cond_up ) {
798                vec tmp ( condsize );
799                set_subvector ( tmp, v2c_lo, val_up ( v2c_up ) );
800                set_subvector ( tmp, c2c_lo, cond_up ( c2c_up ) );
801                return tmp;
802        }
803        //! Fill
804
805};
806
807/*!
808@brief Class for storing results (and semi-results) of an experiment
809
810This 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.
811 */
812class logger : public root {
813protected:
814        //! RVs of all logged variables.
815        Array<RV> entries;
816        //! Names of logged quantities, e.g. names of algorithm variants
817        Array<string> names;
818public:
819        //!Default constructor
820        logger() : entries ( 0 ), names ( 0 ) {}
821
822        //! returns an identifier which will be later needed for calling the \c logit() function
823        //! For empty RV it returns -1, this entry will be ignored by \c logit().
824        virtual int add ( const RV &rv, string prefix = "" ) {
825                int id;
826                if ( rv._dsize() > 0 ) {
827                        id = entries.length();
828                        names = concat ( names, prefix ); // diff
829                        entries.set_length ( id + 1, true );
830                        entries ( id ) = rv;
831                } else {
832                        id = -1;
833                }
834                return id; // identifier of the last entry
835        }
836
837        //! log this vector
838        virtual void logit ( int id, const vec &v ) {
839                bdm_error ( "Not implemented" );
840        };
841        //! log this double
842        virtual void logit ( int id, const double &d ) {
843                bdm_error ( "Not implemented" );
844        };
845
846        //! Shifts storage position for another time step.
847        virtual void step() {
848                bdm_error ( "Not implemneted" );
849        };
850
851        //! Finalize storing information
852        virtual void finalize() {};
853
854        //! Initialize the storage
855        virtual void init() {};
856
857};
858
859/*! \brief Unconditional mpdf, allows using epdf in the role of mpdf.
860
861*/
862class mepdf : public mpdf {
863        //! Internal shared pointer to epdf
864        shared_ptr<epdf> iepdf;
865public:
866        //!Default constructor
867        mepdf() { }
868        //! Set internal shared pointer
869        mepdf ( shared_ptr<epdf> em ) {
870                iepdf = em;
871                set_ep ( *iepdf.get() );
872                dimc = 0;
873        }
874
875        //! empty
876        vec samplecond ( const vec &cond ) {
877                return iepdf->sample();
878        }
879        double evallogcond ( const vec &val, const vec &cond ) {
880                return iepdf->evallog ( val );
881        }
882
883        //! Load from structure with elements:
884        //!  \code
885        //! { class = "mepdf",
886        //!   epdf = {class="epdf_offspring",...}
887        //! }
888        //! \endcode
889        //!@}
890        void from_setting ( const Setting &set );
891};
892UIREGISTER ( mepdf );
893SHAREDPTR ( mepdf );
894
895//! \brief Combines RVs from a list of mpdfs to a single one.
896RV get_composite_rv ( const Array<shared_ptr<mpdf> > &mpdfs, bool checkoverlap = false );
897
898/*! \brief Abstract class for discrete-time sources of data.
899
900The class abstracts operations of:
901\li  data aquisition,
902\li  data-preprocessing, such as  scaling of data,
903\li  data resampling from the task of estimation and control.
904Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
905
906The DataSource has three main data interaction structures:
907\li input, \f$ u_t \f$,
908\li output \f$ y_t \f$,
909\li data, \f$ d_t=[y_t,u_t, \ldots ]\f$ a collection of all inputs and outputs and possibly some internal variables too.
910
911*/
912
913class DS : public root {
914protected:
915                //! size of data returned by \c getdata()
916        int dtsize;
917                //! size of data
918        int utsize;
919                //!size of output
920                int ytsize;
921        //!Description of data returned by \c getdata().
922        RV Drv;
923        //!Description of data witten by by \c write().
924        RV Urv; //
925                //!Description of output data
926                RV Yrv; //
927        //! Remember its own index in Logger L
928        int L_dt, L_ut;
929public:
930        //! default constructors
931                DS() : Drv(), Urv(),Yrv() {};
932
933        //! Returns full vector of observed data=[output, input]
934        virtual void getdata ( vec &dt ) {
935                bdm_error ( "abstract class" );
936        }
937
938        //! Returns data records at indeces.
939        virtual void getdata ( vec &dt, const ivec &indeces ) {
940                bdm_error ( "abstract class" );
941        }
942
943        //! Accepts action variable and schedule it for application.
944        virtual void write ( vec &ut ) {
945                bdm_error ( "abstract class" );
946        }
947
948        //! Accepts action variables at specific indeces
949        virtual void write ( vec &ut, const ivec &indeces ) {
950                bdm_error ( "abstract class" );
951        }
952
953        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
954        virtual void step() = 0;
955
956        //! Register DS for logging into logger L
957        virtual void log_add ( logger &L ) {
958                bdm_assert_debug ( dtsize == Drv._dsize(), "invalid DS: dtsize (" + num2str ( dtsize ) + ") different from Drv " + num2str ( Drv._dsize() ) );
959                bdm_assert_debug ( utsize == Urv._dsize(), "invalid DS: utsize (" + num2str ( utsize ) + ") different from Urv " + num2str ( Urv._dsize() ) );
960
961                L_dt = L.add ( Drv, "" );
962                L_ut = L.add ( Urv, "" );
963        }
964        //! Register DS for logging into logger L
965        virtual void logit ( logger &L ) {
966                vec tmp ( Drv._dsize() + Urv._dsize() );
967                getdata ( tmp );
968                // d is first in getdata
969                L.logit ( L_dt, tmp.left ( Drv._dsize() ) );
970                // u follows after d in getdata
971                L.logit ( L_ut, tmp.mid ( Drv._dsize(), Urv._dsize() ) );
972        }
973        //!access function
974        virtual const RV& _drv() const {
975                //              return concat (Drv, Urv);// why!!!
976                return Drv;// why!!!
977        }
978        //!access function
979        const RV& _urv() const {
980                return Urv;
981        }
982                //!access function
983                const RV& _yrv() const {
984                        return Yrv;
985                }
986        //! set random variables
987                virtual void set_drv (const  RV &yrv, const RV &urv) {
988                    Yrv = yrv;
989                        Drv = concat(yrv,urv);
990                Urv = urv;
991        }
992};
993
994/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
995
996This object represents exact or approximate evaluation of the Bayes rule:
997\f[
998f(\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})}
999\f]
1000
1001Access to the resulting posterior density is via function \c posterior().
1002
1003As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
1004It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
1005
1006Alternatively, it can evaluate posterior density conditioned by a known constant, \f$ c_t \f$:
1007\f[
1008f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
1009\f]
1010
1011The value of \f$ c_t \f$ is set by function condition().
1012
1013*/
1014
1015class BM : public root {
1016protected:
1017        //! Random variable of the data (optional)
1018        RV drv;
1019        //!Logarithm of marginalized data likelihood.
1020        double ll;
1021        //!  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.
1022        bool evalll;
1023public:
1024        //! \name Constructors
1025        //! @{
1026
1027        BM() : ll ( 0 ), evalll ( true ), LIDs ( 4 ), LFlags ( 4 ) {
1028                LIDs = -1;/*empty IDs*/
1029                LFlags = 0;
1030                LFlags ( 0 ) = 1;  /*log only mean*/
1031        };
1032        BM ( const BM &B ) :  drv ( B.drv ), ll ( B.ll ), evalll ( B.evalll ) {}
1033        //! Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
1034        //! Prototype: \code BM* _copy_() const {return new BM(*this);} \endcode
1035        virtual BM* _copy_() const {
1036                return NULL;
1037        };
1038        //!@}
1039
1040        //! \name Mathematical operations
1041        //!@{
1042
1043        /*! \brief Incremental Bayes rule
1044        @param dt vector of input data
1045        */
1046        virtual void bayes ( const vec &dt ) = 0;
1047        //! Batch Bayes rule (columns of Dt are observations)
1048        virtual void bayesB ( const mat &Dt );
1049        //! Evaluates predictive log-likelihood of the given data record
1050        //! I.e. marginal likelihood of the data with the posterior integrated out.
1051        virtual double logpred ( const vec &dt ) const {
1052                bdm_error ( "Not implemented" );
1053                return 0.0;
1054        }
1055
1056        //! Matrix version of logpred
1057        vec logpred_m ( const mat &dt ) const {
1058                vec tmp ( dt.cols() );
1059                for ( int i = 0; i < dt.cols(); i++ ) {
1060                        tmp ( i ) = logpred ( dt.get_col ( i ) );
1061                }
1062                return tmp;
1063        }
1064
1065        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1066        virtual epdf* epredictor() const {
1067                bdm_error ( "Not implemented" );
1068                return NULL;
1069        };
1070        //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1071        virtual mpdf* predictor() const {
1072                bdm_error ( "Not implemented" );
1073                return NULL;
1074        };
1075        //!@}
1076
1077        //! \name Extension to conditional BM
1078        //! This extension is useful e.g. in Marginalized Particle Filter (\ref bdm::MPF).
1079        //! Alternatively, it can be used for automated connection to DS when the condition is observed
1080        //!@{
1081
1082        //! Name of extension variable
1083        RV rvc;
1084        //! access function
1085        const RV& _rvc() const {
1086                return rvc;
1087        }
1088
1089        //! Substitute \c val for \c rvc.
1090        virtual void condition ( const vec &val ) {
1091                bdm_error ( "Not implemented!" );
1092        }
1093
1094        //!@}
1095
1096
1097        //! \name Access to attributes
1098        //!@{
1099
1100        const RV& _drv() const {
1101                return drv;
1102        }
1103        void set_drv ( const RV &rv ) {
1104                drv = rv;
1105        }
1106        void set_rv ( const RV &rv ) {
1107                const_cast<epdf&> ( posterior() ).set_rv ( rv );
1108        }
1109        double _ll() const {
1110                return ll;
1111        }
1112        void set_evalll ( bool evl0 ) {
1113                evalll = evl0;
1114        }
1115        virtual const epdf& posterior() const = 0;
1116        //!@}
1117
1118        //! \name Logging of results
1119        //!@{
1120
1121        //! Set boolean options from a string, recognized are: "logbounds,logll"
1122        virtual void set_options ( const string &opt ) {
1123                LFlags ( 0 ) = 1;
1124                if ( opt.find ( "logbounds" ) != string::npos ) {
1125                        LFlags ( 1 ) = 1;
1126                        LFlags ( 2 ) = 1;
1127                }
1128                if ( opt.find ( "logll" ) != string::npos ) {
1129                        LFlags ( 3 ) = 1;
1130                }
1131        }
1132        //! IDs of storages in loggers 4:[1=mean,2=lb,3=ub,4=ll]
1133        ivec LIDs;
1134
1135        //! Flags for logging - same size as LIDs, each entry correspond to the same in LIDs
1136        ivec LFlags;
1137        //! Add all logged variables to a logger
1138        virtual void log_add ( logger &L, const string &name = "" ) {
1139                // internal
1140                RV r;
1141                if ( posterior().isnamed() ) {
1142                        r = posterior()._rv();
1143                } else {
1144                        r = RV ( "est", posterior().dimension() );
1145                };
1146
1147                // Add mean value
1148                if ( LFlags ( 0 ) ) LIDs ( 0 ) = L.add ( r, name + "mean_" );
1149                if ( LFlags ( 1 ) ) LIDs ( 1 ) = L.add ( r, name + "lb_" );
1150                if ( LFlags ( 2 ) ) LIDs ( 2 ) = L.add ( r, name + "ub_" );
1151                if ( LFlags ( 3 ) ) LIDs ( 3 ) = L.add ( RV ( "ll", 1 ), name );    //TODO: "local" RV
1152        }
1153        virtual void logit ( logger &L ) {
1154                L.logit ( LIDs ( 0 ), posterior().mean() );
1155                if ( LFlags ( 1 ) || LFlags ( 2 ) ) {  //if one of them is off, its LID==-1 and will not be stored
1156                        vec ub, lb;
1157                        posterior().qbounds ( lb, ub );
1158                        L.logit ( LIDs ( 1 ), lb );
1159                        L.logit ( LIDs ( 2 ), ub );
1160                }
1161                if ( LFlags ( 3 ) ) L.logit ( LIDs ( 3 ), ll );
1162        }
1163        //!@}
1164        void from_setting ( const Setting &set ) {
1165                shared_ptr<RV> r = UI::build<RV> ( set, "drv", UI::optional );
1166                if ( r ) {
1167                        set_drv ( *r );
1168                }
1169                string opt;
1170                if ( !UI::get ( opt, set, "options", UI::optional ) ) {
1171                        set_options ( opt );
1172                }
1173        }
1174
1175};
1176
1177typedef Array<shared_ptr<epdf> > epdf_array;
1178
1179typedef Array<shared_ptr<mpdf> > mpdf_array;
1180
1181template<class EPDF>
1182vec mpdf_internal<EPDF>::samplecond ( const vec &cond ) {
1183        condition ( cond );
1184        vec temp = iepdf.sample();
1185        return temp;
1186}
1187
1188template<class EPDF>
1189mat mpdf_internal<EPDF>::samplecond_m ( const vec &cond, int N ) {
1190        condition ( cond );
1191        mat temp ( dimension(), N );
1192        vec smp ( dimension() );
1193        for ( int i = 0; i < N; i++ ) {
1194                smp = iepdf.sample();
1195                temp.set_col ( i, smp );
1196        }
1197
1198        return temp;
1199}
1200
1201template<class EPDF>
1202double mpdf_internal<EPDF>::evallogcond ( const vec &dt, const vec &cond ) {
1203        double tmp;
1204        condition ( cond );
1205        tmp = iepdf.evallog ( dt );
1206        return tmp;
1207}
1208
1209template<class EPDF>
1210vec mpdf_internal<EPDF>::evallogcond_m ( const mat &Dt, const vec &cond ) {
1211        condition ( cond );
1212        return iepdf.evallog_m ( Dt );
1213}
1214
1215template<class EPDF>
1216vec mpdf_internal<EPDF>::evallogcond_m ( const Array<vec> &Dt, const vec &cond ) {
1217        condition ( cond );
1218        return iepdf.evallog_m ( Dt );
1219}
1220
1221}; //namespace
1222#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.