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

Revision 896, 33.7 kB (checked in by mido, 14 years ago)

cleanup of MemDS and its descendants
bdmtoolbox/CMakeLists.txt slightly changed to avoid unnecessary MEX condition
"indeces" replaced by "indices"

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