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

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

LOG_LEVEL final cut (or rather semifinal? I hope to improve work with ids soon)
and also it rests to adapt applications, work is in progress

  • 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        //!separator of prefixes of entries
309        const string separator;
310        //! Root Setting for storing Settings
311        Config setting_conf;
312        //! list of Settings for specific ids
313        Array<Setting*> settings;
314public:
315        //!Default constructor
316        logger ( const string separator0 ) : entries ( 0 ), names ( 0 ), separator ( separator0 ) {}
317
318        //! returns an identifier which will be later needed for calling the \c logit() function
319        //! For empty RV it returns -1, this entry will be ignored by \c logit().
320        virtual int add_vector ( const RV &rv, string prefix = "" );
321
322        virtual int add_setting ( const string &prefix );
323
324        //! log this vector
325        virtual void log_vector ( int id, const vec &v ) = 0;
326
327        virtual Setting & log_to_setting ( int id ) {
328                return settings ( id )->add ( Setting::TypeGroup );
329        }
330        //! log this double
331        virtual void logit ( int id, const double &d ) = 0;
332
333        //! Shifts storage position for another time step.
334        virtual void step() = 0;
335
336        //! Finalize storing information
337        virtual void finalize() {};
338
339        //! Initialize the storage
340        virtual void init() {};
341
342        //!separator of prefixes for this logger
343        const string& prefix_sep() {
344                return separator;
345        }
346};
347
348
349
350//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
351class fnc : public root {       
352protected:
353        //! Length of the output vector
354        int dimy;
355        //! Length of the input vector
356        int dimc;
357public:
358        //!default constructor
359        fnc() {};
360        //! function evaluates numerical value of \f$f(x)\f$ at \f$x=\f$ \c cond
361        virtual vec eval ( const vec &cond ) {
362                return vec ( 0 );
363        };
364
365        //! access function
366        int dimension() const {
367                return dimy;
368        }
369        //! access function
370        int dimensionc() const {
371                return dimc;
372        }
373        void from_setting(const Setting &set){
374                UI::get(dimy, set, "dim", UI::optional);
375                UI::get(dimc, set, "dimc", UI::optional);
376        }
377};
378
379class epdf;
380
381//! 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.
382class pdf : public root {
383protected:
384        //!dimension of the condition
385        int dimc;
386
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        //!@}
405
406        //! \name Matematical operations
407        //!@{
408
409        //! 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
410        virtual vec samplecond ( const vec &cond ) = 0;
411
412        //! 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
413        virtual mat samplecond_mat ( const vec &cond, int N );
414
415        //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
416        virtual double evallogcond ( const vec &yt, const vec &cond ) = 0;
417
418        //! Matrix version of evallogcond
419        virtual vec evallogcond_mat ( const mat &Yt, const vec &cond ) {
420                vec v ( Yt.cols() );
421                for ( int i = 0; i < Yt.cols(); i++ ) {
422                        v ( i ) = evallogcond ( Yt.get_col ( i ), cond );
423                }
424                return v;
425        }
426
427        //! Array<vec> version of evallogcond
428        virtual vec evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
429                vec v ( Yt.length() );
430                for ( int i = 0; i < Yt.length(); i++ ) {
431                        v ( i ) = evallogcond ( Yt( i ), cond );
432                }
433                return v;
434        }
435
436        //! \name Access to attributes
437        //! @{
438
439        const RV& _rv() const {
440                return rv;
441        }
442        const RV& _rvc() const {
443                return rvc;
444        }
445
446        int dimension() const {
447                return dim;
448        }
449        int dimensionc() {
450                return dimc;
451        }
452
453        //! access function
454        void set_dim ( int d ) {
455                dim = d;
456        }
457        //! access function
458        void set_dimc ( int d ) {
459                dimc = d;
460        }
461        //! Load from structure with elements:
462        //!  \code
463        //! { class = "pdf_offspring",
464        //!   rv = {class="RV", names=(...),}; // RV describing meaning of random variable
465        //!   rvc= {class="RV", names=(...),}; // RV describing meaning of random variable in condition
466        //!   // elements of offsprings
467        //! }
468        //! \endcode
469        //!@}
470        void from_setting ( const Setting &set );
471
472        void to_setting ( Setting &set ) const;
473        //!@}
474
475        //! \name Connection to other objects
476        //!@{
477        void set_rvc ( const RV &rvc0 ) {
478                rvc = rvc0;
479        }
480        void set_rv ( const RV &rv0 ) {
481                rv = rv0;
482        }
483
484        //! Names of variables stored in RV are considered to be valid only if their size match size of the parameters (dim).
485        bool isnamed() const {
486                return ( dim == rv._dsize() ) && ( dimc == rvc._dsize() );
487        }
488        //!@}
489};
490SHAREDPTR ( pdf );
491
492//! Probability density function with numerical statistics, e.g. posterior density.
493class epdf : public pdf {
494        //! \var log_level_enums logmean
495        //! TODO DOPLNIT       
496       
497        //! \var log_level_enums loglb
498        //! TODO DOPLNIT
499       
500        //! \var log_level_enums logub
501        //! TODO DOPLNIT
502       
503        //! \var log_level_enums logfull
504        //! TODO DOPLNIT
505        LOG_LEVEL(epdf,logmean,loglb,logub,logfull);
506
507public:
508        /*! \name Constructors
509         Construction of each epdf should support two types of constructors:
510        \li empty constructor,
511        \li copy constructor,
512
513        The following constructors should be supported for convenience:
514        \li constructor followed by calling \c set_parameters()
515        \li constructor accepting random variables calling \c set_rv()
516
517         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.
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                shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
597                if ( r ) {
598                        set_rv ( *r );
599                }
600        }
601
602        void to_setting ( Setting &set ) const {
603                // we do not want to store rvc, therfore, pdf::to_setting( set ) is omitted
604                root::to_setting(set);
605
606                UI::save( &rv, set, "rv" );
607        }
608
609        vec samplecond ( const vec &cond ) {
610                return sample();
611        }
612        double evallogcond ( const vec &val, const vec &cond ) {
613                return evallog ( val );
614        }
615};
616SHAREDPTR ( epdf );
617
618//! pdf with internal epdf that is modified by function \c condition
619template <class EPDF>
620class pdf_internal: public pdf {
621protected :
622        //! Internal epdf used for sampling
623        EPDF iepdf;
624public:
625        //! constructor
626        pdf_internal() : pdf(), iepdf() {
627        }
628
629        //! Update \c iepdf so that it represents this pdf conditioned on \c rvc = cond
630        //! This function provides convenient reimplementation in offsprings
631        virtual void condition ( const vec &cond ) = 0;
632
633        //!access function to iepdf
634        EPDF& e() {
635                return iepdf;
636        }
637
638        //! Reimplements samplecond using \c condition()
639        vec samplecond ( const vec &cond );
640        //! Reimplements evallogcond using \c condition()
641        double evallogcond ( const vec &val, const vec &cond );
642        //! Efficient version of evallogcond for matrices
643        virtual vec evallogcond_mat ( const mat &Dt, const vec &cond );
644        //! Efficient version of evallogcond for Array<vec>
645        virtual vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
646        //! Efficient version of samplecond
647        virtual mat samplecond_mat ( const vec &cond, int N );
648
649        void validate() {
650                iepdf.validate();
651                if ( rv._dsize() < iepdf._rv()._dsize() ) {
652                        rv = iepdf._rv();
653                };
654                dim = iepdf.dimension();
655        }
656};
657
658/*! \brief DataLink is a connection between two data vectors Up and Down
659
660Up can be longer than Down. Down must be fully present in Up (TODO optional)
661See chart:
662\dot
663digraph datalink {
664  node [shape=record];
665  subgraph cluster0 {
666    label = "Up";
667      up [label="<1>|<2>|<3>|<4>|<5>"];
668    color = "white"
669}
670  subgraph cluster1{
671    label = "Down";
672    labelloc = b;
673      down [label="<1>|<2>|<3>"];
674    color = "white"
675}
676    up:1 -> down:1;
677    up:3 -> down:2;
678    up:5 -> down:3;
679}
680\enddot
681
682*/
683class datalink {
684protected:
685        //! Remember how long val should be
686        int downsize;
687
688        //! Remember how long val of "Up" should be
689        int upsize;
690
691        //! val-to-val link, indices of the upper val
692        ivec v2v_up;
693
694public:
695        //! Constructor
696        datalink() : downsize ( 0 ), upsize ( 0 ) { }
697
698        //! Convenience constructor
699        datalink ( const RV &rv, const RV &rv_up ) {
700                set_connection ( rv, rv_up );
701        }
702
703        //! set connection, rv must be fully present in rv_up
704        virtual void set_connection ( const RV &rv, const RV &rv_up );
705
706        //! set connection using indices
707        virtual void set_connection ( int ds, int us, const ivec &upind );
708
709        //! Get val for myself from val of "Up"
710        vec pushdown ( const vec &val_up ) {
711                vec tmp ( downsize );
712                filldown ( val_up, tmp );
713                return tmp;
714        }
715        //! Get val for vector val_down from val of "Up"
716        virtual void filldown ( const vec &val_up, vec &val_down ) {
717                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
718                val_down = val_up ( v2v_up );
719        }
720        //! Fill val of "Up" by my pieces
721        virtual void pushup ( vec &val_up, const vec &val ) {
722                bdm_assert_debug ( downsize == val.length(), "Wrong val" );
723                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
724                set_subvector ( val_up, v2v_up, val );
725        }
726        //! access functions
727        int _upsize() {
728                return upsize;
729        }
730        //! access functions
731        int _downsize() {
732                return downsize;
733        }
734        //! for future use
735        virtual ~datalink() {}
736};
737
738/*! Extension of datalink to fill only part of Down
739*/
740class datalink_part : public datalink {
741protected:
742        //! indeces of values in vector downsize
743        ivec v2v_down;
744public:
745        void set_connection ( const RV &rv, const RV &rv_up );
746        //! Get val for vector val_down from val of "Up"
747        void filldown ( const vec &val_up, vec &val_down ) {
748                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) );
749        }
750};
751
752/*! \brief Datalink that buffers delayed values - do not forget to call step()
753
754Up is current data, Down is their subset with possibly delayed values
755*/
756class datalink_buffered: public datalink_part {
757protected:
758        //! History, ordered as \f$[Up_{t-1},Up_{t-2}, \ldots]\f$
759        vec history;
760        //! rv of the history
761        RV Hrv;
762        //! h2v : indeces in down
763        ivec h2v_down;
764        //! h2v : indeces in history
765        ivec h2v_hist;
766        //! v2h: indeces of up too be pushed to h
767        ivec v2h_up;
768public:
769
770        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
771        //! push current data to history
772        void store_data ( const vec &val_up ) {
773                if ( v2h_up.length() > 0 ) {
774                        history.shift_right ( 0, v2h_up.length() );
775                        history.set_subvector ( 0, val_up ( v2h_up ) );
776                }
777        }
778        //! Get val for myself from val of "Up"
779        vec pushdown ( const vec &val_up ) {
780                vec tmp ( downsize );
781                filldown ( val_up, tmp );
782                return tmp;
783        }
784
785        void filldown ( const vec &val_up, vec &val_down ) {
786                bdm_assert_debug ( val_down.length() >= downsize, "short val_down" );
787
788                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) ); // copy direct values
789                set_subvector ( val_down, h2v_down, history ( h2v_hist ) ); // copy delayed values
790        }
791
792        void set_connection ( const RV &rv, const RV &rv_up );
793       
794        //! set history of variable given by \c rv1 to values of \c hist.
795        void set_history ( const RV& rv1, const vec &hist0 );
796};
797
798//! buffered datalink from 2 vectors to 1
799class datalink_2to1_buffered {
800protected:
801        //! link 1st vector to down
802        datalink_buffered dl1;
803        //! link 2nd vector to down
804        datalink_buffered dl2;
805public:
806        //! set connection between RVs
807        void set_connection ( const RV &rv, const RV &rv_up1, const RV &rv_up2 ) {
808                dl1.set_connection ( rv, rv_up1 );
809                dl2.set_connection ( rv, rv_up2 );
810        }
811        //! fill values of down from the values of the two up vectors
812        void filldown ( const vec &val1, const vec &val2, vec &val_down ) {
813                bdm_assert_debug ( val_down.length() >= dl1._downsize() + dl2._downsize(), "short val_down" );
814                dl1.filldown ( val1, val_down );
815                dl2.filldown ( val2, val_down );
816        }
817        //! update buffer
818        void step ( const vec &dt, const vec &ut ) {
819                dl1.store_data ( dt );
820                dl2.store_data ( ut );
821        }
822};
823
824
825
826//! Data link with a condition.
827class datalink_m2e: public datalink {
828protected:
829        //! Remember how long cond should be
830        int condsize;
831
832        //!upper_val-to-local_cond link, indices of the upper val
833        ivec v2c_up;
834
835        //!upper_val-to-local_cond link, indices of the local cond
836        ivec v2c_lo;
837
838public:
839        //! Constructor
840        datalink_m2e() : condsize ( 0 ) { }
841
842        //! Set connection between vectors
843        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
844
845        //!Construct condition
846        vec get_cond ( const vec &val_up );
847
848        //! Copy corresponding values to Up.condition
849        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
850};
851
852//!DataLink is a connection between pdf and its superordinate (Up)
853//! This class links
854class datalink_m2m: public datalink_m2e {
855protected:
856        //!cond-to-cond link, indices of the upper cond
857        ivec c2c_up;
858        //!cond-to-cond link, indices of the local cond
859        ivec c2c_lo;
860
861public:
862        //! Constructor
863        datalink_m2m() {};
864        //! Set connection between the vectors
865        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
866                datalink_m2e::set_connection ( rv, rvc, rv_up );
867                //establish c2c connection
868                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
869//              bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
870        }
871
872        //! Get cond for myself from val and cond of "Up"
873        vec get_cond ( const vec &val_up, const vec &cond_up ) {
874                vec tmp ( condsize );
875                fill_cond ( val_up, cond_up, tmp );
876                return tmp;
877        }
878        //! fill condition
879        void fill_cond ( const vec &val_up, const vec &cond_up, vec& cond_out ) {
880                bdm_assert_debug ( cond_out.length() >= condsize, "dl.fill_cond: cond_out is too small" );
881                set_subvector ( cond_out, v2c_lo, val_up ( v2c_up ) );
882                set_subvector ( cond_out, c2c_lo, cond_up ( c2c_up ) );
883        }
884        //! Fill
885
886};
887
888
889//! \brief Combines RVs from a list of pdfs to a single one.
890RV get_composite_rv ( const Array<shared_ptr<pdf> > &pdfs, bool checkoverlap = false );
891
892/*! \brief Abstract class for discrete-time sources of data.
893
894The class abstracts operations of:
895\li  data aquisition,
896\li  data-preprocessing, such as  scaling of data,
897\li  data resampling from the task of estimation and control.
898Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
899
900The DataSource has three main data interaction structures:
901\li input, \f$ u_t \f$,
902\li output \f$ y_t \f$,
903\li data, \f$ d_t=[y_t,u_t, \ldots ]\f$ a collection of all inputs and outputs and possibly some internal variables too.
904
905*/
906
907class DS : public root {
908        //! \var log_level_enums dt
909        //! TODO DOPLNIT
910        LOG_LEVEL(DS, dt);
911
912protected:
913        //! size of data returned by \c getdata()
914        int dtsize;
915        //! size of data
916        int utsize;
917        //!size of output
918        int ytsize;
919        //!Description of data returned by \c getdata().
920        RV Drv;
921        //!Description of data witten by by \c write().
922        RV Urv; //
923        //!Description of output data
924        RV Yrv; //
925public:
926        //! default constructors
927        DS() : dtsize ( 0 ), utsize ( 0 ), ytsize ( 0 ), Drv(), Urv(), Yrv() {
928                log_level[dt] = true;
929        };
930
931        //! 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().
932        virtual int max_length() {
933                return std::numeric_limits< int >::max();
934        }
935        //! Returns full vector of observed data=[output, input]
936        virtual void getdata ( vec &dt ) const = 0;
937
938        //! Returns data records at indeces. Default is inefficent.
939        virtual void getdata ( vec &dt, const ivec &indeces ) {
940                vec tmp(dtsize);
941                getdata(tmp);
942                dt = tmp(indeces);
943        };
944
945        //! Accepts action variable and schedule it for application.   
946        virtual void write ( const vec &ut ) NOT_IMPLEMENTED_VOID;
947
948        //! Accepts action variables at specific indeces
949        virtual void write ( const vec &ut, const ivec &indeces ) NOT_IMPLEMENTED_VOID;
950
951        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
952        virtual void step() = 0;
953
954        //! Register DS for logging into logger L
955        virtual void log_register ( logger &L,  const string &prefix );
956        //! Register DS for logging into logger L
957        virtual void log_write ( ) const;
958        //!access function
959        virtual const RV& _drv() const {
960                return Drv;
961        }
962        //!access function
963        const RV& _urv() const {
964                return Urv;
965        }
966        //!access function
967        const RV& _yrv() const {
968                return Yrv;
969        }
970        //! set random variables
971        virtual void set_drv ( const  RV &yrv, const RV &urv ) {
972                Yrv = yrv;
973                Drv = concat ( yrv, urv );
974                Urv = urv;
975        }
976};
977
978/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
979
980This object represents exact or approximate evaluation of the Bayes rule:
981\f[
982f(\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})}
983\f]
984where:
985 * \f$ y_t \f$ is the variable
986Access to the resulting posterior density is via function \c posterior().
987
988As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
989It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
990
991Alternatively, it can evaluate posterior density with rvc replaced by the given values, \f$ c_t \f$:
992\f[
993f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
994\f]
995
996*/
997
998class BM : public root {
999        //! \var log_level_enums logfull
1000        //! TODO DOPLNIT
1001
1002        //! \var log_level_enums logevidence
1003        //! TODO DOPLNIT
1004       
1005        //! \var log_level_enums logbounds
1006        //! TODO DOPLNIT       
1007        LOG_LEVEL(BM,logfull,logevidence,logbounds);
1008
1009protected:
1010        //! Random variable of the data (optional)
1011        RV yrv;
1012        //! size of the data record
1013        int dimy;
1014        //! Name of extension variable
1015        RV rvc;
1016        //! size of the conditioning vector
1017        int dimc;
1018
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;
1023
1024public:
1025        //! \name Constructors
1026        //! @{
1027
1028        BM() : yrv(), dimy ( 0 ), rvc(), dimc ( 0 ), ll ( 0 ), evalll ( true ) { };
1029        //      BM ( const BM &B ) :  yrv ( B.yrv ), dimy(B.dimy), rvc ( B.rvc ),dimc(B.dimc), ll ( B.ll ), evalll ( B.evalll ) {}
1030        //! \brief Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
1031        //! Prototype: \code BM* _copy() const {return new BM(*this);} \endcode
1032        virtual BM* _copy() const NOT_IMPLEMENTED(NULL);
1033        //!@}
1034
1035        //! \name Mathematical operations
1036        //!@{
1037
1038        /*! \brief Incremental Bayes rule
1039        @param dt vector of input data
1040        */
1041        virtual void bayes ( const vec &yt, const vec &cond = empty_vec ) = 0;
1042        //! Batch Bayes rule (columns of Dt are observations)
1043        virtual void bayes_batch ( const mat &Dt, const vec &cond = empty_vec );
1044        //! Batch Bayes rule (columns of Dt are observations, columns of Cond are conditions)
1045        virtual void bayes_batch ( const mat &Dt, const mat &Cond );
1046        //! Evaluates predictive log-likelihood of the given data record
1047        //! I.e. marginal likelihood of the data with the posterior integrated out.
1048        //! This function evaluates only \f$ y_t \f$, condition is assumed to be the last used in bayes().
1049        //! See bdm::BM::predictor for conditional version.
1050        virtual double logpred ( const vec &yt ) const NOT_IMPLEMENTED(0.0);
1051
1052        //! Matrix version of logpred
1053        vec logpred_mat ( const mat &Yt ) const {
1054                vec tmp ( Yt.cols() );
1055                for ( int i = 0; i < Yt.cols(); i++ ) {
1056                        tmp ( i ) = logpred ( Yt.get_col ( i ) );
1057                }
1058                return tmp;
1059        }
1060
1061        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1062        virtual epdf* epredictor() const NOT_IMPLEMENTED(NULL);
1063
1064        //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1065        virtual pdf* predictor() const NOT_IMPLEMENTED(NULL);
1066
1067        //!@}
1068
1069
1070        //! \name Access to attributes
1071        //!@{
1072        //! access function
1073        const RV& _rvc() const {
1074                return rvc;
1075        }
1076        //! access function
1077        int dimensionc() const {
1078                return dimc;
1079        }
1080        //! access function
1081        int dimensiony() const {
1082                return dimy;
1083        }
1084        //! access function
1085        int dimension() const {
1086                return posterior().dimension();
1087        }
1088        //! access function
1089        const RV& _rv() const {
1090                return posterior()._rv();
1091        }
1092        //! access function
1093        const RV& _yrv() const {
1094                return yrv;
1095        }
1096        //! access function
1097        void set_yrv ( const RV &rv ) {
1098                yrv = rv;
1099        }
1100        //! access function
1101        void set_rvc ( const RV &rv ) {
1102                rvc = rv;
1103        }
1104        //! access to rv of the posterior
1105        void set_rv ( const RV &rv ) {
1106                const_cast<epdf&> ( posterior() ).set_rv ( rv );
1107        }
1108        //! access function
1109        void set_dim ( int dim ) {
1110                const_cast<epdf&> ( posterior() ).set_dim ( dim );
1111        }
1112        //! return internal log-likelihood of the last data vector
1113        double _ll() const {
1114                return ll;
1115        }
1116        //! switch evaluation of log-likelihood on/off
1117        void set_evalll ( bool evl0 ) {
1118                evalll = evl0;
1119        }
1120        //! return posterior density
1121        virtual const epdf& posterior() const = 0;
1122       
1123        epdf& prior() {return const_cast<epdf&>(posterior());}
1124        //! set prior density -- same as posterior but writable
1125        virtual void set_prior(const epdf *pdf0) NOT_IMPLEMENTED_VOID;
1126       
1127        //!@}
1128
1129        //! \name Logging of results
1130        //!@{
1131
1132        //! Add all logged variables to a logger
1133        //! Log levels two digits: xy where
1134        //!  * y = 0/1 log-likelihood is to be logged
1135        //!  * x = level of the posterior (typically 0/1/2 for nothing/mean/bounds)
1136        virtual void log_register ( logger &L, const string &prefix = "" );
1137
1138        //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
1139        virtual void log_write ( ) const;
1140
1141        //!@}
1142        void from_setting ( const Setting &set ) {
1143                shared_ptr<RV> r = UI::build<RV> ( set, "yrv", UI::optional );
1144                if ( r ) {
1145                        set_yrv ( *r );
1146                }
1147                shared_ptr<RV> r2 = UI::build<RV> ( set, "rvc", UI::optional );
1148                if ( r2 ) {
1149                        rvc =   *r2;
1150                }
1151                shared_ptr<RV> r3 = UI::build<RV> ( set, "rv", UI::optional );
1152                if ( r3 ) {
1153                        set_rv ( *r3 );
1154                }
1155
1156                UI::get ( log_level, set, "log_level", UI::optional );
1157        }
1158
1159        void to_setting ( Setting &set ) const {
1160                root::to_setting( set );
1161                UI::save( &yrv, set, "yrv" );
1162                UI::save( &rvc, set, "rvc" );           
1163                UI::save( &posterior()._rv(), set, "rv" );
1164                UI::save( log_level, set );
1165        }
1166
1167        void validate()
1168        {
1169                if ( log_level[logfull] ) {
1170                        const_cast<epdf&> ( posterior() ).log_level[epdf::logfull] = true;
1171                } else {
1172                        if ( log_level[logbounds] ) {
1173                                const_cast<epdf&> ( posterior() ).log_level[epdf::loglb] = true;
1174                        } else {
1175                                const_cast<epdf&> ( posterior() ).log_level[epdf::logmean] = true;;
1176                        }
1177                        if ( log_level[logevidence] ) {
1178                        }
1179                }
1180        }
1181};
1182
1183//! array of pointers to epdf
1184typedef Array<shared_ptr<epdf> > epdf_array;
1185//! array of pointers to pdf
1186typedef Array<shared_ptr<pdf> > pdf_array;
1187
1188template<class EPDF>
1189vec pdf_internal<EPDF>::samplecond ( const vec &cond ) {
1190        condition ( cond );
1191        vec temp = iepdf.sample();
1192        return temp;
1193}
1194
1195template<class EPDF>
1196mat pdf_internal<EPDF>::samplecond_mat ( const vec &cond, int N ) {
1197        condition ( cond );
1198        mat temp ( dimension(), N );
1199        vec smp ( dimension() );
1200        for ( int i = 0; i < N; i++ ) {
1201                smp = iepdf.sample();
1202                temp.set_col ( i, smp );
1203        }
1204
1205        return temp;
1206}
1207
1208template<class EPDF>
1209double pdf_internal<EPDF>::evallogcond ( const vec &yt, const vec &cond ) {
1210        double tmp;
1211        condition ( cond );
1212        tmp = iepdf.evallog ( yt );
1213        return tmp;
1214}
1215
1216template<class EPDF>
1217vec pdf_internal<EPDF>::evallogcond_mat ( const mat &Yt, const vec &cond ) {
1218        condition ( cond );
1219        return iepdf.evallog_mat ( Yt );
1220}
1221
1222template<class EPDF>
1223vec pdf_internal<EPDF>::evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
1224        condition ( cond );
1225        return iepdf.evallog_mat ( Yt );
1226}
1227
1228}; //namespace
1229#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.