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

Revision 713, 35.9 kB (checked in by mido, 15 years ago)

_m changed to _mat

emix.cfg prepared, but it is not yet debugged!

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