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

Revision 1077, 50.8 kB (checked in by mido, 14 years ago)

another update of doc - all bayesian models until bdm::MultiModel? finished
also MixEF::MixEF_options renamed just to MixEF::Options

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