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

Revision 788, 35.0 kB (checked in by mido, 14 years ago)

sketch of class logged_options which is intendet to replace log_level in future, DOES NOT WORK AT THE MOMENT, NOT TESTED

  • 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#include <string>
18#include <bitset>
19
20#include "../itpp_ext.h"
21#include "../bdmroot.h"
22#include "../shared_ptr.h"
23#include "user_info.h"
24
25using namespace libconfig;
26using namespace itpp;
27using namespace std;
28
29namespace bdm {
30//! Structure of RV, i.e. RVs expanded into a flat list of IDs, used for debugging.
31class str {
32public:
33        //! vector id ids (non-unique!)
34        ivec ids;
35        //! vector of times
36        ivec times;
37        //!Default constructor
38        str ( ivec ids0, ivec times0 ) : ids ( ids0 ), times ( times0 ) {
39                bdm_assert ( times0.length() == ids0.length(), "Incompatible input" );
40        };
41};
42
43/*!
44* \brief Class representing variables, most often random variables
45
46The 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.
47
48The class is implemented using global variables to assure uniqueness of description:
49
50 In is a vector
51\dot
52digraph datalink {
53rankdir=LR;
54subgraph cluster0 {
55node [shape=record];
56label = "MAP \n std::map<string,int>";
57map [label="{{\"a\"| \"b\" | \"c\"} | {<3> 3 |<1> 1|<2> 2}}"];
58color = "white"
59}
60subgraph cluster1{
61node [shape=record];
62label = "NAMES";
63names [label="{<1> \"b\" | <2> \"c\" | <3>\"a\" }"];
64color = "white"
65}
66subgraph cluster2{
67node [shape=record];
68label = "SIZES";
69labelloc = b;
70sizes [label="{<1>1 |<2> 4 |<3> 1}"];
71color = "white"
72}
73map:1 -> names:1;
74map:1 -> sizes:1;
75map:3 -> names:3;
76map:3 -> sizes:3;
77}
78\enddot
79*/
80
81class RV : public root {
82private:
83        typedef std::map<string, int> str2int_map;
84
85        //! Internal global variable storing sizes of RVs
86        static ivec SIZES;
87        //! Internal global variable storing names of RVs
88        static Array<string> NAMES;
89
90        //! TODO
91        const static int BUFFER_STEP;
92
93        //! TODO
94        static str2int_map MAP;
95
96public:
97
98protected:
99        //! size of the data vector
100        int dsize;
101        //! number of individual rvs
102        int len;
103        //! Vector of unique IDs
104        ivec ids;
105        //! Vector of shifts from current time
106        ivec times;
107
108private:
109        enum enum_dummy {dummy};
110
111        //! auxiliary function used in constructor
112        void init( const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times );
113
114        //! auxiliary function assigning unique integer index related to the passed name and size of the random variable
115        int assign_id( const string &name, int size );
116
117        //! Private constructor from IDs, potentially dangerous since all ids must be valid!
118        //! dummy is there to prevent confusion with RV(" string");
119        explicit RV ( const ivec &ids0, enum_dummy dum ) : dsize ( 0 ), len ( ids0.length() ), ids ( ids0 ), times ( zeros_i ( ids0.length() ) ) {
120                dsize = countsize();
121        }
122public:
123        //! \name Constructors
124        //!@{
125
126        //! Full constructor
127        RV ( const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times ) {
128                init ( in_names, in_sizes, in_times );
129        }
130
131        //! Constructor with times=0
132        RV ( const Array<std::string> &in_names, const ivec &in_sizes ) {
133                init ( in_names, in_sizes, zeros_i ( in_names.length() ) );
134        }
135
136        //! Constructor with sizes=1, times=0
137        RV ( const Array<std::string> &in_names ) {
138                init ( in_names, ones_i ( in_names.length() ), zeros_i ( in_names.length() ) );
139        }
140
141        //! Constructor of empty RV
142        RV() : dsize ( 0 ), len ( 0 ), ids ( 0 ), times ( 0 ) {}
143
144        //! Constructor of a single RV with given id
145        RV ( string name, 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        //!separator of prefixes of entries
310        const string separator;
311        //! Root Setting for storing Settings
312        Config setting_conf;
313        //! list of Settings for specific ids
314        Array<Setting*> settings;
315public:
316        //!Default constructor
317        logger ( const string separator0 ) : entries ( 0 ), names ( 0 ), separator ( separator0 ) {}
318
319        //! returns an identifier which will be later needed for calling the \c logit() function
320        //! For empty RV it returns -1, this entry will be ignored by \c logit().
321        virtual int add_vector ( const RV &rv, string prefix = "" );
322
323        virtual int add_setting ( const string &prefix );
324
325        //! log this vector
326        virtual void log_vector ( int id, const vec &v ) = 0;
327
328        virtual Setting & log_to_setting ( int id ) {
329                return settings ( id )->add ( Setting::TypeGroup );
330        }
331        //! log this double
332        virtual void logit ( int id, const double &d ) = 0;
333
334        //! Shifts storage position for another time step.
335        virtual void step() = 0;
336
337        //! Finalize storing information
338        virtual void finalize() {};
339
340        //! Initialize the storage
341        virtual void init() {};
342
343        //!separator of prefixes for this logger
344        const string& prefix_sep() {
345                return separator;
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        //! function substitutes given value into an appropriate position
366        virtual void condition ( const vec &val ) {};
367
368        //! access function
369        int dimension() const {
370                return dimy;
371        }
372        //! access function
373        int dimensionc() const {
374                return dimc;
375        }
376};
377
378class epdf;
379
380//! Conditional probability density, e.g. modeling \f$ f( x | y) \f$, where \f$ x \f$ is random variable, \c rv, and \f$ y \f$ is conditioning variable, \c rvc.
381class pdf : public root {
382protected:
383        //!dimension of the condition
384        int dimc;
385
386        //! random variable in condition
387        RV rvc;
388
389        //! dimension of random variable
390        int dim;
391
392        //! random variable
393        RV rv;
394
395public:
396        //! \name Constructors
397        //! @{
398
399        pdf() : dimc ( 0 ), rvc(), dim ( 0 ), rv() { }
400
401        pdf ( const pdf &m ) : dimc ( m.dimc ), rvc ( m.rvc ), dim ( m.dim ), rv ( m.rv ) { }
402
403        //!@}
404
405        //! \name Matematical operations
406        //!@{
407
408        //! Returns a sample from the density conditioned on \c cond, \f$x \sim epdf(rv|cond)\f$. \param cond is numeric value of \c rv
409        virtual vec samplecond ( const vec &cond ) = 0;
410
411        //! Returns \param N samples from the density conditioned on \c cond, \f$x \sim epdf(rv|cond)\f$. \param cond is numeric value of \c rv
412        virtual mat samplecond_mat ( const vec &cond, int N );
413
414        //! Shortcut for conditioning and evaluation of the internal epdf. In some cases,  this operation can be implemented efficiently.
415        virtual double evallogcond ( const vec &yt, const vec &cond ) = 0;
416
417        //! Matrix version of evallogcond
418        virtual vec evallogcond_mat ( const mat &Yt, const vec &cond ) {
419                vec v ( Yt.cols() );
420                for ( int i = 0; i < Yt.cols(); i++ ) {
421                        v ( i ) = evallogcond ( Yt.get_col ( i ), cond );
422                }
423                return v;
424        }
425
426        //! Array<vec> version of evallogcond
427        virtual vec evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
428                vec v ( Yt.length() );
429                for ( int i = 0; i < Yt.length(); i++ ) {
430                        v ( i ) = evallogcond ( Yt( i ), cond );
431                }
432                return v;
433        }
434
435        //! \name Access to attributes
436        //! @{
437
438        const RV& _rv() const {
439                return rv;
440        }
441        const RV& _rvc() const {
442                return rvc;
443        }
444
445        int dimension() const {
446                return dim;
447        }
448        int dimensionc() {
449                return dimc;
450        }
451
452        //! access function
453        void set_dim ( int d ) {
454                dim = d;
455        }
456        //! access function
457        void set_dimc ( int d ) {
458                dimc = d;
459        }
460        //! Load from structure with elements:
461        //!  \code
462        //! { class = "pdf_offspring",
463        //!   rv = {class="RV", names=(...),}; // RV describing meaning of random variable
464        //!   rvc= {class="RV", names=(...),}; // RV describing meaning of random variable in condition
465        //!   // elements of offsprings
466        //! }
467        //! \endcode
468        //!@}
469        void from_setting ( const Setting &set );
470
471        void to_setting ( Setting &set ) const;
472        //!@}
473
474        //! \name Connection to other objects
475        //!@{
476        void set_rvc ( const RV &rvc0 ) {
477                rvc = rvc0;
478        }
479        void set_rv ( const RV &rv0 ) {
480                rv = rv0;
481        }
482
483        //! Names of variables stored in RV are considered to be valid only if their size match size of the parameters (dim).
484        bool isnamed() const {
485                return ( dim == rv._dsize() ) && ( dimc == rvc._dsize() );
486        }
487        //!@}
488};
489SHAREDPTR ( pdf );
490
491//! Probability density function with numerical statistics, e.g. posterior density.
492class epdf : public pdf {
493
494public:
495        /*! \name Constructors
496         Construction of each epdf should support two types of constructors:
497        \li empty constructor,
498        \li copy constructor,
499
500        The following constructors should be supported for convenience:
501        \li constructor followed by calling \c set_parameters()
502        \li constructor accepting random variables calling \c set_rv()
503
504         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.
505        @{*/
506        epdf() {};
507        epdf ( const epdf &e ) : pdf ( e ) {};
508       
509        virtual void    validate (int dim0){
510                dim = dim0;
511        }
512       
513        //!@}
514
515        //! \name Matematical Operations
516        //!@{
517
518        //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
519        virtual vec sample() const = 0;
520
521        //! Returns N samples, \f$ [x_1 , x_2 , \ldots \ \f$  from density \f$ f_x(rv)\f$
522        virtual mat sample_mat ( int N ) const;
523
524        //! Compute log-probability of argument \c val
525        //! In case the argument is out of suport return -Infinity
526        virtual double evallog ( const vec &val ) const = 0;
527       
528        //! Compute log-probability of multiple values argument \c val
529        virtual vec evallog_mat ( const mat &Val ) const;
530
531        //! Compute log-probability of multiple values argument \c val
532        virtual vec evallog_mat ( const Array<vec> &Avec ) const;
533
534        //! Return conditional density on the given RV, the remaining rvs will be in conditioning
535        virtual shared_ptr<pdf> condition ( const RV &rv ) const;
536
537        //! Return marginal density on the given RV, the remainig rvs are intergrated out
538        virtual shared_ptr<epdf> marginal ( const RV &rv ) const;
539
540        virtual vec mean() const = 0;
541
542        //! return expected variance (not covariance!)
543        virtual vec variance() const = 0;
544
545        //! Lower and upper bounds of \c percentage % quantile, returns mean-2*sigma as default
546        virtual void qbounds ( vec &lb, vec &ub, double percentage = 0.95 ) const {
547                vec mea = mean();
548                vec std = sqrt ( variance() );
549                lb = mea - 2 * std;
550                ub = mea + 2 * std;
551        };
552        //!@}
553
554        //! \name Connection to other classes
555        //! Description of the random quantity via attribute \c rv is optional.
556        //! For operations such as sampling \c rv does not need to be set. However, for \c marginalization
557        //! and \c conditioning \c rv has to be set. NB:
558        //! @{
559
560        //! store values of the epdf on the following levels:
561        //!  #1 mean
562        //!  #2 mean + lower & upper bound
563        void log_register ( logger &L, const string &prefix );
564
565        void log_write() const;
566        //!@}
567
568        //! \name Access to attributes
569        //! @{
570
571        //! Load from structure with elements:
572        //!  \code
573        //! { rv = {class="RV", names=(...),}; // RV describing meaning of random variable
574        //!   // elements of offsprings
575        //! }
576        //! \endcode
577        //!@}
578        void from_setting ( const Setting &set ) {
579                shared_ptr<RV> r = UI::build<RV> ( set, "rv", UI::optional );
580                if ( r ) {
581                        set_rv ( *r );
582                }
583        }
584
585        void to_setting ( Setting &set ) const {
586                // we do not want to store rvc, therfore, pdf::to_setting( set ) is omitted
587                root::to_setting(set);
588
589                UI::save( &rv, set, "rv" );
590        }
591
592        vec samplecond ( const vec &cond ) {
593                return sample();
594        }
595        double evallogcond ( const vec &val, const vec &cond ) {
596                return evallog ( val );
597        }
598};
599SHAREDPTR ( epdf );
600
601//! pdf with internal epdf that is modified by function \c condition
602template <class EPDF>
603class pdf_internal: public pdf {
604protected :
605        //! Internal epdf used for sampling
606        EPDF iepdf;
607public:
608        //! constructor
609        pdf_internal() : pdf(), iepdf() {
610        }
611
612        //! Update \c iepdf so that it represents this pdf conditioned on \c rvc = cond
613        //! This function provides convenient reimplementation in offsprings
614        virtual void condition ( const vec &cond ) = 0;
615
616        //!access function to iepdf
617        EPDF& e() {
618                return iepdf;
619        }
620
621        //! Reimplements samplecond using \c condition()
622        vec samplecond ( const vec &cond );
623        //! Reimplements evallogcond using \c condition()
624        double evallogcond ( const vec &val, const vec &cond );
625        //! Efficient version of evallogcond for matrices
626        virtual vec evallogcond_mat ( const mat &Dt, const vec &cond );
627        //! Efficient version of evallogcond for Array<vec>
628        virtual vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
629        //! Efficient version of samplecond
630        virtual mat samplecond_mat ( const vec &cond, int N );
631
632        void validate() {
633                iepdf.validate();
634                if ( rv._dsize() < iepdf._rv()._dsize() ) {
635                        rv = iepdf._rv();
636                };
637                dim = iepdf.dimension();
638        }
639};
640
641/*! \brief DataLink is a connection between two data vectors Up and Down
642
643Up can be longer than Down. Down must be fully present in Up (TODO optional)
644See chart:
645\dot
646digraph datalink {
647  node [shape=record];
648  subgraph cluster0 {
649    label = "Up";
650      up [label="<1>|<2>|<3>|<4>|<5>"];
651    color = "white"
652}
653  subgraph cluster1{
654    label = "Down";
655    labelloc = b;
656      down [label="<1>|<2>|<3>"];
657    color = "white"
658}
659    up:1 -> down:1;
660    up:3 -> down:2;
661    up:5 -> down:3;
662}
663\enddot
664
665*/
666class datalink {
667protected:
668        //! Remember how long val should be
669        int downsize;
670
671        //! Remember how long val of "Up" should be
672        int upsize;
673
674        //! val-to-val link, indices of the upper val
675        ivec v2v_up;
676
677public:
678        //! Constructor
679        datalink() : downsize ( 0 ), upsize ( 0 ) { }
680
681        //! Convenience constructor
682        datalink ( const RV &rv, const RV &rv_up ) {
683                set_connection ( rv, rv_up );
684        }
685
686        //! set connection, rv must be fully present in rv_up
687        virtual void set_connection ( const RV &rv, const RV &rv_up );
688
689        //! set connection using indices
690        virtual void set_connection ( int ds, int us, const ivec &upind );
691
692        //! Get val for myself from val of "Up"
693        vec pushdown ( const vec &val_up ) {
694                vec tmp ( downsize );
695                filldown ( val_up, tmp );
696                return tmp;
697        }
698        //! Get val for vector val_down from val of "Up"
699        virtual void filldown ( const vec &val_up, vec &val_down ) {
700                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
701                val_down = val_up ( v2v_up );
702        }
703        //! Fill val of "Up" by my pieces
704        virtual void pushup ( vec &val_up, const vec &val ) {
705                bdm_assert_debug ( downsize == val.length(), "Wrong val" );
706                bdm_assert_debug ( upsize == val_up.length(), "Wrong val_up" );
707                set_subvector ( val_up, v2v_up, val );
708        }
709        //! access functions
710        int _upsize() {
711                return upsize;
712        }
713        //! access functions
714        int _downsize() {
715                return downsize;
716        }
717        //! for future use
718        virtual ~datalink() {}
719};
720
721/*! Extension of datalink to fill only part of Down
722*/
723class datalink_part : public datalink {
724protected:
725        //! indeces of values in vector downsize
726        ivec v2v_down;
727public:
728        void set_connection ( const RV &rv, const RV &rv_up );
729        //! Get val for vector val_down from val of "Up"
730        void filldown ( const vec &val_up, vec &val_down ) {
731                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) );
732        }
733};
734
735/*! \brief Datalink that buffers delayed values - do not forget to call step()
736
737Up is current data, Down is their subset with possibly delayed values
738*/
739class datalink_buffered: public datalink_part {
740protected:
741        //! History, ordered as \f$[Up_{t-1},Up_{t-2}, \ldots]\f$
742        vec history;
743        //! rv of the history
744        RV Hrv;
745        //! h2v : indeces in down
746        ivec h2v_down;
747        //! h2v : indeces in history
748        ivec h2v_hist;
749        //! v2h: indeces of up too be pushed to h
750        ivec v2h_up;
751public:
752
753        datalink_buffered() : datalink_part(), history ( 0 ), h2v_down ( 0 ), h2v_hist ( 0 ) {};
754        //! push current data to history
755        void store_data ( const vec &val_up ) {
756                if ( v2h_up.length() > 0 ) {
757                        history.shift_right ( 0, v2h_up.length() );
758                        history.set_subvector ( 0, val_up ( v2h_up ) );
759                }
760        }
761        //! Get val for myself from val of "Up"
762        vec pushdown ( const vec &val_up ) {
763                vec tmp ( downsize );
764                filldown ( val_up, tmp );
765                return tmp;
766        }
767
768        void filldown ( const vec &val_up, vec &val_down ) {
769                bdm_assert_debug ( val_down.length() >= downsize, "short val_down" );
770
771                set_subvector ( val_down, v2v_down, val_up ( v2v_up ) ); // copy direct values
772                set_subvector ( val_down, h2v_down, history ( h2v_hist ) ); // copy delayed values
773        }
774
775        void set_connection ( const RV &rv, const RV &rv_up );
776       
777        //! set history of variable given by \c rv1 to values of \c hist.
778        void set_history ( const RV& rv1, const vec &hist0 );
779};
780
781//! buffered datalink from 2 vectors to 1
782class datalink_2to1_buffered {
783protected:
784        //! link 1st vector to down
785        datalink_buffered dl1;
786        //! link 2nd vector to down
787        datalink_buffered dl2;
788public:
789        //! set connection between RVs
790        void set_connection ( const RV &rv, const RV &rv_up1, const RV &rv_up2 ) {
791                dl1.set_connection ( rv, rv_up1 );
792                dl2.set_connection ( rv, rv_up2 );
793        }
794        //! fill values of down from the values of the two up vectors
795        void filldown ( const vec &val1, const vec &val2, vec &val_down ) {
796                bdm_assert_debug ( val_down.length() >= dl1._downsize() + dl2._downsize(), "short val_down" );
797                dl1.filldown ( val1, val_down );
798                dl2.filldown ( val2, val_down );
799        }
800        //! update buffer
801        void step ( const vec &dt, const vec &ut ) {
802                dl1.store_data ( dt );
803                dl2.store_data ( ut );
804        }
805};
806
807
808
809//! Data link with a condition.
810class datalink_m2e: public datalink {
811protected:
812        //! Remember how long cond should be
813        int condsize;
814
815        //!upper_val-to-local_cond link, indices of the upper val
816        ivec v2c_up;
817
818        //!upper_val-to-local_cond link, indices of the local cond
819        ivec v2c_lo;
820
821public:
822        //! Constructor
823        datalink_m2e() : condsize ( 0 ) { }
824
825        //! Set connection between vectors
826        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
827
828        //!Construct condition
829        vec get_cond ( const vec &val_up );
830
831        //! Copy corresponding values to Up.condition
832        void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
833};
834
835//!DataLink is a connection between pdf and its superordinate (Up)
836//! This class links
837class datalink_m2m: public datalink_m2e {
838protected:
839        //!cond-to-cond link, indices of the upper cond
840        ivec c2c_up;
841        //!cond-to-cond link, indices of the local cond
842        ivec c2c_lo;
843
844public:
845        //! Constructor
846        datalink_m2m() {};
847        //! Set connection between the vectors
848        void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up, const RV &rvc_up ) {
849                datalink_m2e::set_connection ( rv, rvc, rv_up );
850                //establish c2c connection
851                rvc.dataind ( rvc_up, c2c_lo, c2c_up );
852//              bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
853        }
854
855        //! Get cond for myself from val and cond of "Up"
856        vec get_cond ( const vec &val_up, const vec &cond_up ) {
857                vec tmp ( condsize );
858                fill_cond ( val_up, cond_up, tmp );
859                return tmp;
860        }
861        //! fill condition
862        void fill_cond ( const vec &val_up, const vec &cond_up, vec& cond_out ) {
863                bdm_assert_debug ( cond_out.length() >= condsize, "dl.fill_cond: cond_out is too small" );
864                set_subvector ( cond_out, v2c_lo, val_up ( v2c_up ) );
865                set_subvector ( cond_out, c2c_lo, cond_up ( c2c_up ) );
866        }
867        //! Fill
868
869};
870
871
872//! \brief Combines RVs from a list of pdfs to a single one.
873RV get_composite_rv ( const Array<shared_ptr<pdf> > &pdfs, bool checkoverlap = false );
874
875/*! \brief Abstract class for discrete-time sources of data.
876
877The class abstracts operations of:
878\li  data aquisition,
879\li  data-preprocessing, such as  scaling of data,
880\li  data resampling from the task of estimation and control.
881Moreover, for controlled systems, it is able to receive the desired control action and perform it in the next step. (Or as soon as possible).
882
883The DataSource has three main data interaction structures:
884\li input, \f$ u_t \f$,
885\li output \f$ y_t \f$,
886\li data, \f$ d_t=[y_t,u_t, \ldots ]\f$ a collection of all inputs and outputs and possibly some internal variables too.
887
888*/
889
890class DS : public root {
891protected:
892        //! size of data returned by \c getdata()
893        int dtsize;
894        //! size of data
895        int utsize;
896        //!size of output
897        int ytsize;
898        //!Description of data returned by \c getdata().
899        RV Drv;
900        //!Description of data witten by by \c write().
901        RV Urv; //
902        //!Description of output data
903        RV Yrv; //
904public:
905        //! default constructors
906        DS() : dtsize ( 0 ), utsize ( 0 ), ytsize ( 0 ), Drv(), Urv(), Yrv() {
907                log_level = 1;
908        };
909
910        //! 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().
911        virtual int max_length() {
912                return std::numeric_limits< int >::max();
913        }
914        //! Returns full vector of observed data=[output, input]
915        virtual void getdata ( vec &dt ) const = 0;
916
917        //! Returns data records at indeces.
918        virtual void getdata ( vec &dt, const ivec &indeces ) = 0;
919
920        //! Accepts action variable and schedule it for application.   
921        virtual void write ( const vec &ut ) = 0;
922
923        //! Accepts action variables at specific indeces
924        virtual void write ( const vec &ut, const ivec &indeces ) = 0;
925
926        //! Moves from \f$ t \f$ to \f$ t+1 \f$, i.e. perfroms the actions and reads response of the system.
927        virtual void step() = 0;
928
929        //! Register DS for logging into logger L
930        virtual void log_register ( logger &L,  const string &prefix );
931        //! Register DS for logging into logger L
932        virtual void log_write ( ) const;
933        //!access function
934        virtual const RV& _drv() const {
935                return Drv;
936        }
937        //!access function
938        const RV& _urv() const {
939                return Urv;
940        }
941        //!access function
942        const RV& _yrv() const {
943                return Yrv;
944        }
945        //! set random variables
946        virtual void set_drv ( const  RV &yrv, const RV &urv ) {
947                Yrv = yrv;
948                Drv = concat ( yrv, urv );
949                Urv = urv;
950        }
951};
952
953/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
954
955This object represents exact or approximate evaluation of the Bayes rule:
956\f[
957f(\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})}
958\f]
959where:
960 * \f$ y_t \f$ is the variable
961Access to the resulting posterior density is via function \c posterior().
962
963As a "side-effect" it also evaluates log-likelihood of the data, which can be accessed via function _ll().
964It can also evaluate predictors of future values of \f$y_t\f$, see functions epredictor() and predictor().
965
966Alternatively, it can evaluate posterior density with rvc replaced by the given values, \f$ c_t \f$:
967\f[
968f(\theta_t | c_t, d_1,\ldots,d_t) \propto  f(y_t,\theta_t|c_t,\cdot, d_1,\ldots,d_{t-1})
969\f]
970
971
972*/
973
974#ifndef BDMLIB
975// MUZEME INTERNE POUZIVAT ENUMY, A KLIDNE MENIT JEJICH PORADI, DIKY TOMUHLE MAKRU SE VZDY NAMAPUJI NA TY SPRAVNE STRINGY
976#define DEFINED_OPTIONS(...) enum defined_options { __VA_ARGS__ }; const Array<string> logged_options::names( "{"#__VA_ARGS__"}" )
977// TODO: ROZPARESUJE TO KONSTRUKTOR ARRAYE NA JEDNOTLIVE STRINGY?? NUTNO OTESTOVAT!!
978#else
979#define DEFINED_OPTIONS(...) enum defined_options { __VA_ARGS__ };
980#endif
981
982enum defined_options;
983
984class logged_options : public root
985// TODO: HA, TADY TO MAME!! POKUD ZDE CHCEME TEZ UZIVAT FROMSETTING A TOSETTING, NEMUZOU BYT LOGOVACI
986// VECI PRIMO V ROOTU.. RESENIM BUDE ZREJME KOMPOZICE - FUNKCNOST SOUVISEJICI S LOGGERAMA UMISTENA V ROOTU
987// PREJDE DO TETO TRIDY, A KDO BUDE MIT ZAJEM O NAPOJENI NA LOGGERY MUSI OBSAHOVAT LOGGED_OPTIONS INSTANCI...
988// TZN. TRIDU LOGGED OPTIONS BUDE JESTE TREBA LEHCE ROZSIRIT..
989// KOMPOZICE TAKY UMOZNI NEKOLIK RUZNYCH LOGGERU PRO JEDEN OBJEKT.. PROSTE BUDE OBSHOVAT NEKOLIK RUZNYCH
990// LOGGED_OPTIONS INSTANCI NAPOJENYCH NA RUZNE LOGGERY.. HMM, ALE TO JE TREBA JESTE DOMYSLET.)
991{
992private:
993        bitset<32> values;
994
995        static const Array<string> names; 
996
997public:
998       
999        bool operator [] (const defined_options &option )
1000        {
1001                return values[option];
1002        }
1003
1004        void from_setting ( const Setting &set )
1005        {
1006                values.reset();
1007                Array<string> true_options;
1008                UI::get( true_options, set );
1009                for( int i = 0; i < true_options.length(); i++ )
1010                        for( int j = 0; j < names.length(); j++ )
1011                                if( true_options(i) == names(j)  ) 
1012                                {
1013                                        values[j] = true;
1014                                        break;
1015                                } // TODO kdyz ho to vubec nenajde, nic se nedeje.. coz radeji vyhodit UI vyjimku??!
1016        }
1017       
1018        void to_setting( Setting &set ) const
1019        {
1020                Array<string> true_options( values.count() );
1021                int true_options_count = 0;
1022                for( unsigned int i = 0; i < values.size(); i++ )
1023                        if( values[i] ) 
1024                                true_options( true_options_count++ ) = names(i);
1025                UI::save( true_options, set );
1026        }
1027};
1028UIREGISTER(logged_options);
1029DEFINED_OPTIONS(bounds,likelyhood,full);
1030
1031
1032class BM : public root {
1033protected:
1034        //! Random variable of the data (optional)
1035        RV yrv;
1036        //! size of the data record
1037        int dimy;
1038        //! Name of extension variable
1039        RV rvc;
1040        //! size of the conditioning vector
1041        int dimc;
1042
1043        //!Logarithm of marginalized data likelihood.
1044        double ll;
1045        //!  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.
1046        bool evalll;
1047
1048public:
1049        //! \name Constructors
1050        //! @{
1051
1052        BM() : yrv(), dimy ( 0 ), rvc(), dimc ( 0 ), ll ( 0 ), evalll ( true ) { };
1053//      BM ( const BM &B ) :  yrv ( B.yrv ), dimy(B.dimy), rvc ( B.rvc ),dimc(B.dimc), ll ( B.ll ), evalll ( B.evalll ) {}
1054        //! \brief Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
1055        //! Prototype: \code BM* _copy() const {return new BM(*this);} \endcode
1056        virtual BM* _copy() const {             return NULL;    }; // TODO NEBUDE TU TAKY LEPSI BDM_ERROR??!
1057        //!@}
1058
1059        //! \name Mathematical operations
1060        //!@{
1061
1062        /*! \brief Incremental Bayes rule
1063        @param dt vector of input data
1064        */
1065        virtual void bayes ( const vec &yt, const vec &cond = empty_vec ) = 0;
1066        //! Batch Bayes rule (columns of Dt are observations)
1067        virtual void bayes_batch ( const mat &Dt, const vec &cond = empty_vec );
1068        //! Batch Bayes rule (columns of Dt are observations, columns of Cond are conditions)
1069        virtual void bayes_batch ( const mat &Dt, const mat &Cond );
1070        //! Evaluates predictive log-likelihood of the given data record
1071        //! I.e. marginal likelihood of the data with the posterior integrated out.
1072        //! This function evaluates only \f$ y_t \f$, condition is assumed to be the last used in bayes().
1073        //! See bdm::BM::predictor for conditional version.
1074        virtual double logpred ( const vec &yt ) const = 0;
1075
1076        //! Matrix version of logpred
1077        vec logpred_mat ( const mat &Yt ) const {
1078                vec tmp ( Yt.cols() );
1079                for ( int i = 0; i < Yt.cols(); i++ ) {
1080                        tmp ( i ) = logpred ( Yt.get_col ( i ) );
1081                }
1082                return tmp;
1083        }
1084
1085        //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1086        virtual epdf* epredictor() const = 0;
1087
1088        //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1089        virtual pdf* predictor() const = 0;
1090
1091        //!@}
1092
1093
1094        //! \name Access to attributes
1095        //!@{
1096        //! access function
1097        const RV& _rvc() const {
1098                return rvc;
1099        }
1100        //! access function
1101        int dimensionc() const {
1102                return dimc;
1103        }
1104        //! access function
1105        int dimensiony() const {
1106                return dimy;
1107        }
1108        //! access function
1109        int dimension() const {
1110                return posterior().dimension();
1111        }
1112        //! access function
1113        const RV& _yrv() const {
1114                return yrv;
1115        }
1116        //! access function
1117        void set_yrv ( const RV &rv ) {
1118                yrv = rv;
1119        }
1120        //! access function
1121        void set_rvc ( const RV &rv ) {
1122                rvc = rv;
1123        }
1124        //! access to rv of the posterior
1125        void set_rv ( const RV &rv ) {
1126                const_cast<epdf&> ( posterior() ).set_rv ( rv );
1127        }
1128        //! access function
1129        void set_dim ( int dim ) {
1130                const_cast<epdf&> ( posterior() ).set_dim ( dim );
1131        }
1132        //! return internal log-likelihood of the last data vector
1133        double _ll() const {
1134                return ll;
1135        }
1136        //! switch evaluation of log-likelihood on/off
1137        void set_evalll ( bool evl0 ) {
1138                evalll = evl0;
1139        }
1140        //! return posterior density
1141        virtual const epdf& posterior() const = 0;
1142        //!@}
1143
1144        //! \name Logging of results
1145        //!@{
1146
1147        //! Add all logged variables to a logger
1148        //! Log levels two digits: xy where
1149        //!  * y = 0/1 log-likelihood is to be logged
1150        //!  * x = level of the posterior (typically 0/1/2 for nothing/mean/bounds)
1151        virtual void log_register ( logger &L, const string &prefix = "" );
1152
1153        //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
1154        virtual void log_write ( ) const;
1155
1156
1157        // TOHLE EFEKTIVNE NAHRAZUJE loglevel
1158        // TODO pozdeji dat private
1159        logged_options logged;
1160
1161        //!@}
1162        void from_setting ( const Setting &set ) {
1163                shared_ptr<RV> r = UI::build<RV> ( set, "yrv", UI::optional );
1164                if ( r ) {
1165                        set_yrv ( *r );
1166                }
1167                shared_ptr<RV> r2 = UI::build<RV> ( set, "rvc", UI::optional );
1168                if ( r2 ) {
1169                        rvc =   *r2;
1170                }
1171                shared_ptr<RV> r3 = UI::build<RV> ( set, "rv", UI::optional );
1172                if ( r3 ) {
1173                        set_rv ( *r3 );
1174                }
1175
1176                UI::get ( logged, set, "logged", UI::optional );
1177        }
1178
1179
1180        void to_setting ( Setting &set ) const {
1181                root::to_setting( set );
1182                UI::save( &yrv, set, "yrv" );
1183                UI::save( &rvc, set, "rvc" );           
1184                UI::save( &posterior()._rv(), set, "rv" );
1185                UI::save( &posterior()._rv(), set, "rv" );
1186                UI::save( &logged, set, "logged" );
1187        }
1188
1189        virtual void set_options ( const string &  ); 
1190       
1191        // TODO JEN JAKO UKAZKA POUZIT LOGGED[..], NAKONEC ODSTRANIT CELOU METODU, A TAKY JEJI ORIGINAL VYSE
1192        // jen co zavedeme logged_options i do dalsich objektu, pak se vse muze nastavovat primo
1193        // ve from_settingu, bude to tak ok?
1194        // nejlepsi by bylo, kdyby se options posterioru() nastavovaly v jeho from_settingu,
1195        // aby nevznikala takovahle kaskada zavislosti.. pujde to? domyslet
1196        virtual void SHOWING_ROOM( const string &  )
1197        {
1198                if ( logged[full] ) {
1199                        const_cast<epdf&> ( posterior() ).set_log_level ( 10 ) ;
1200                } else {
1201                        if ( logged[bounds]  ) {
1202                                const_cast<epdf&> ( posterior() ).set_log_level ( 2 ) ;
1203                        } else {
1204                                const_cast<epdf&> ( posterior() ).set_log_level ( 1 ) ;
1205                        }
1206                        if ( logged[likelyhood]  ) {
1207                                log_level = 1;
1208                        }
1209                }
1210        }
1211
1212
1213};
1214
1215//! array of pointers to epdf
1216typedef Array<shared_ptr<epdf> > epdf_array;
1217//! array of pointers to pdf
1218typedef Array<shared_ptr<pdf> > pdf_array;
1219
1220template<class EPDF>
1221vec pdf_internal<EPDF>::samplecond ( const vec &cond ) {
1222        condition ( cond );
1223        vec temp = iepdf.sample();
1224        return temp;
1225}
1226
1227template<class EPDF>
1228mat pdf_internal<EPDF>::samplecond_mat ( const vec &cond, int N ) {
1229        condition ( cond );
1230        mat temp ( dimension(), N );
1231        vec smp ( dimension() );
1232        for ( int i = 0; i < N; i++ ) {
1233                smp = iepdf.sample();
1234                temp.set_col ( i, smp );
1235        }
1236
1237        return temp;
1238}
1239
1240template<class EPDF>
1241double pdf_internal<EPDF>::evallogcond ( const vec &yt, const vec &cond ) {
1242        double tmp;
1243        condition ( cond );
1244        tmp = iepdf.evallog ( yt );
1245        return tmp;
1246}
1247
1248template<class EPDF>
1249vec pdf_internal<EPDF>::evallogcond_mat ( const mat &Yt, const vec &cond ) {
1250        condition ( cond );
1251        return iepdf.evallog_mat ( Yt );
1252}
1253
1254template<class EPDF>
1255vec pdf_internal<EPDF>::evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
1256        condition ( cond );
1257        return iepdf.evallog_mat ( Yt );
1258}
1259
1260}; //namespace
1261#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.