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

Revision 746, 33.4 kB (checked in by mido, 14 years ago)

mixef_init fills some data into mixef_init.out,
however, there are still some TODOs in this commit,
it is necessary to fill a few more bodies of the to_setting() method

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