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

Revision 942, 41.1 kB (checked in by mido, 14 years ago)

the functionality of user info was improved, it supports an initialization of root descendant via UI::get directly, however it is save only for static attributes, for dynamically allocated attributes UI::build should be called to handle with intahrence issues

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