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

Revision 1068, 50.7 kB (checked in by mido, 14 years ago)

patch of documentation - all conditional pdfs revised

  • Property svn:eol-style set to native
RevLine 
[2]1/*!
[5]2  \file
[508]3  \brief Basic structures of probability calculus: random variables, probability densities, Bayes rule
[5]4  \author Vaclav Smidl.
[2]5
[5]6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
[384]13#ifndef BDMBASE_H
14#define BDMBASE_H
[2]15
[351]16#include <map>
[263]17
[190]18#include "../itpp_ext.h"
[357]19#include "../bdmroot.h"
[461]20#include "../shared_ptr.h"
[384]21#include "user_info.h"
[2]22
[340]23using namespace libconfig;
[270]24using namespace itpp;
25using namespace std;
[2]26
[600]27namespace bdm {
[850]28
[422]29//! Structure of RV, i.e. RVs expanded into a flat list of IDs, used for debugging.
[600]30class str {
31public:
[1064]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    };
[270]40};
[145]41
[270]42/*!
43* \brief Class representing variables, most often random variables
[5]44
[270]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.
[32]46
[270]47The class is implemented using global variables to assure uniqueness of description:
[2]48
[270]49 In is a vector
50\dot
51digraph datalink {
52rankdir=LR;
53subgraph cluster0 {
54node [shape=record];
[600]55label = "MAP \n std::map<string,int>";
[270]56map [label="{{\"a\"| \"b\" | \"c\"} | {<3> 3 |<1> 1|<2> 2}}"];
57color = "white"
58}
59subgraph cluster1{
60node [shape=record];
[600]61label = "NAMES";
[270]62names [label="{<1> \"b\" | <2> \"c\" | <3>\"a\" }"];
63color = "white"
64}
65subgraph cluster2{
66node [shape=record];
[600]67label = "SIZES";
[270]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
[1020]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.
[270]80*/
[32]81
[600]82class RV : public root {
83private:
[1064]84    typedef std::map<string, int> str2int_map;
[5]85
[1064]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;
[422]94
[600]95public:
[422]96
[600]97protected:
[1064]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;
[532]106
[600]107private:
[1064]108    enum enum_dummy {dummy};
[532]109
[1064]110    //! auxiliary function used in constructor
111    void init( const Array<std::string> &in_names, const ivec &in_sizes, const ivec &in_times );
[766]112
[1064]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 );
[766]115
[1064]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    }
[600]121public:
[1064]122    //! \name Constructors
123    //!@{
[271]124
[1064]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    }
[271]129
[1064]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    }
[422]134
[1064]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    }
[422]139
[1064]140    //! Constructor of empty RV
141    RV() : dsize ( 0 ), len ( 0 ), ids ( 0 ), times ( 0 ) {}
[271]142
[1064]143    //! Constructor of a single RV
144    RV ( string name, int sz, int tm = 0 );
[271]145
[1064]146    //! Constructor of a single nameless RV
147    RV ( int sz, int tm = 0 );
[907]148
[1064]149    // compiler-generated copy constructor is used
150    //!@}
[422]151
[1064]152    //! \name Access functions
153    //!@{
[422]154
[1064]155    //! State output, e.g. for debugging.
156    friend std::ostream &operator<< ( std::ostream &os, const RV &rv );
[422]157
[1064]158    string to_string() const {
159        ostringstream o;
160        o << *this;
161        return o.str();
162    }
[737]163
[1064]164    //! total size of a random variable
165    int _dsize() const {
166        return dsize;
167    }
[271]168
[1064]169    //! access function
170    const ivec& _ids() const {
171        return ids;
172    }
[600]173
[1064]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;
[610]196
[1064]197    void set_time ( int at, int time0 ) {
198        times ( at ) = time0;
199    }
200    //!@}
[600]201
[1064]202    //! \name Algebra on Random Variables
203    //!@{
[600]204
[1064]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;
[600]217
[1064]218    //! Select only variables at indices ind
219    RV operator() ( const ivec &ind ) const {
220        return subselect ( ind );
221    }
[600]222
[1064]223    //! Select from data vector starting at di1 to di2
224    RV operator() ( int di1, int di2 ) const;
[600]225
[1064]226    //! Shift \c time by delta.
227    void t_plus ( int delta );
228    //!@}
[600]229
[1064]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    //!@}
[271]244
[1064]245    //!\name Relation to vectors
246    //!@{
[271]247
[1064]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    //!@}
[357]271
[1064]272    /*! \brief UI for class RV (description of data vectors)
[357]273
[1064]274    \code
275    class = 'RV';
276    names = {'a', 'b', 'c', ...};   // UNIQUE IDENTIFIER same names = same variable
[1066]277                                    // names are also used when storing results
[1064]278    --- optional ---
279    sizes = [1, 2, 3, ...];         // size of each name. default = ones()
[1066]280                                    // if size = -1, it is found out from previous instances of the same name
[1064]281    times = [-1, -2, 0, ...];       // time shifts with respect to current time, default = zeros()
282    \endcode
283    */
284    void from_setting ( const Setting &set );
[600]285
[1064]286    void to_setting ( Setting &set ) const;
[600]287
[1064]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();
[604]292
[270]293};
[600]294UIREGISTER ( RV );
295SHAREDPTR ( RV );
[32]296
[145]297//! Concat two random variables
[600]298RV concat ( const RV &rv1, const RV &rv2 );
[2]299
[959]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
[1064]307//! method. For the reason the second one is templated, it was necessary to declare this whole class.
[959]308template<class T> class log_level_intermediate : public log_level_base {
309protected:
[1064]310    //! boolean flags related indicating which details will be logged to a logger
311    bitset<32> values;
[959]312
[1064]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    }
[959]323public:
[1064]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    }
[959]333
[1064]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;
[959]339
[1064]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;
[959]348
[1064]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;
[959]352
[1064]353        return stream.str();
354    }
[959]355
[1064]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    }
[959]361
[1064]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    }
[959]377};
378//UIREGISTER IS FORBIDDEN FOR THIS CLASS,  AS IT SHOULD BE LOADED ONLY THROUGH THE SPECIALIZED UI::GET(...) METHOD
379
380
[907]381/*!
[676]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 {
[737]387protected:
[1064]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;
[907]396
[1064]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    }
[907]403
[1064]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;
[907]408
[1064]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;
[907]413
[1064]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;
[737]416public:
[1064]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;
[889]421
[1064]422    //!Default constructor
423    logger ( const string separator ) : entries ( 0 ), names ( 0 ), separator ( separator ) {}
[889]424
[1064]425    //!Destructor calls the finalize method
426    ~logger() {
427        finalize();
428    }
[737]429
[1064]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!");
[738]442
[1064]443        if ( rv._dsize() == 0 )
444            return;
[915]445
[1064]446        int id = entries.length();
447        string adjusted_name = log_level.store_id_and_give_name( log_level_enum, enum_subindex, id );
[737]448
[1064]449        names = concat ( names, prefix + separator + adjusted_name ); // diff
450        entries.set_length ( id + 1, true );
451        entries ( id ) = rv;
452    }
[907]453
[1064]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!");
[907]469
[1064]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    }
[737]476
[1064]477    //! Shifts storage position for another time step.
478    virtual void step() = 0;
[737]479
[1064]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() {};
[676]487};
488
[910]489//! This class stores a details that will be logged to a logger
[959]490template<class T> class log_level_template : public log_level_intermediate<T> {
[910]491public:
[945]492
[1064]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 );
[945]499
[1064]500        this->values.reset();
[945]501
[1064]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    }
[945]511
[1064]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="";
[945]522
[1064]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            }
[910]530
[1064]531        element = string_to_write;
532    }
[910]533
[1064]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    }
[910]563};
[945]564//UIREGISTER IS FORBIDDEN FOR THIS CLASS,  AS IT SHOULD BE LOADED ONLY THROUGH THE SPECIALIZED UI::GET(...) METHOD
[910]565
[945]566
[910]567/*!
568  \def LOG_LEVEL(classname,...)
[1064]569  \brief Macro for defining a log_level attribute with a specific set of enumerations related to a specific class
[910]570
571  This macro has to be called within a class declaration. Its argument \a classname has to correspond to that wrapping class.
[1063]572  This macro defines a log_level instance which can be modified either directly or by the means of #bdm::UI class.
[910]573
574  One of the main purposes of this macro is to allow variability in using enumerations. By relating them to their names through
[1064]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
[910]576  any applications which are using this library.
577
578  \todo Write a more detailed explanation including also examples
579
580  \ref ui
581*/
[959]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; }
[910]583
584
[85]585//! Class representing function \f$f(x)\f$ of variable \f$x\f$ represented by \c rv
[1064]586class fnc : public root {
[600]587protected:
[1064]588    //! Length of the output vector
589    int dimy;
590    //! Length of the input vector
591    int dimc;
[600]592public:
[1064]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    };
[2]599
[1064]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    }
[270]612};
[2]613
[675]614class epdf;
[7]615
[675]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.
[693]617class pdf : public root {
[675]618protected:
[1064]619    //!dimension of the condition
620    int dimc;
[766]621
[1064]622    //! random variable in condition
623    RV rvc;
[32]624
[1064]625    //! dimension of random variable
626    int dim;
[675]627
[1064]628    //! random variable
629    RV rv;
[675]630
631public:
[1064]632    //! \name Constructors
633    //! @{
[675]634
[1064]635    pdf() : dimc ( 0 ), rvc(), dim ( 0 ), rv() { }
[675]636
[1064]637    pdf ( const pdf &m ) : dimc ( m.dimc ), rvc ( m.rvc ), dim ( m.dim ), rv ( m.rv ) { }
[737]638
[1064]639    //!@}
[675]640
[1064]641    //! \name Matematical operations
642    //!@{
[675]643
[1064]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;
[675]646
[1064]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 );
[675]649
[1064]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;
[675]652
[1064]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    }
[675]661
[1064]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    }
[675]670
[1064]671    //! \name Access to attributes
672    //! @{
[675]673
[1064]674    const RV& _rv() const {
675        return rv;
676    }
677    const RV& _rvc() const {
678        return rvc;
679    }
[675]680
[1064]681    int dimension() const {
682        return dim;
683    }
684    int dimensionc() {
685        return dimc;
686    }
[675]687
[1064]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    }
[1068]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    //! @}
[1064]708    void from_setting ( const Setting &set );
[746]709
[1064]710    void to_setting ( Setting &set ) const;
711    //!@}
[675]712
[1064]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    }
[675]721
[1064]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    //!@}
[675]727};
[693]728SHAREDPTR ( pdf );
[675]729
[1066]730//! Abstract class representing probability density function with numerical statistics, e.g. posterior density.
[693]731class epdf : public pdf {
[1064]732    //! \var log_level_enums logmean
733    //! log mean value of the density when requested
[32]734
[1064]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
[600]743public:
[1064]744    /*! \name Constructors
745     Construction of each epdf should support two types of constructors:
746    \li empty constructor,
747    \li copy constructor,
[271]748
[1064]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()
[271]752
[1064]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 ) {};
[271]758
759
[1064]760    //!@}
[502]761
[1064]762    //! \name Matematical Operations
763    //!@{
[502]764
[1064]765    //! Returns a sample, \f$ x \f$ from density \f$ f_x()\f$
766    virtual vec sample() const = 0;
[502]767
[1064]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;
[502]770
[1064]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;
[271]774
[1064]775    //! Compute log-probability of multiple values argument \c val
776    virtual vec evallog_mat ( const mat &Val ) const;
[271]777
[1064]778    //! Compute log-probability of multiple values argument \c val
779    virtual vec evallog_mat ( const Array<vec> &Avec ) const;
[271]780
[1064]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;
[565]783
[1064]784    //! Return marginal density on the given RV, the remainig rvs are intergrated out
785    virtual shared_ptr<epdf> marginal ( const RV &rv ) const;
[271]786
[1064]787    virtual vec mean() const = 0;
[271]788
[1064]789    //! return expected variance (not covariance!)
790    virtual vec variance() const = 0;
[737]791
[1064]792    //! return expected covariance -- default is diag(variance)!!
793    virtual mat covariance() const {
794        return diag(variance());
795    };
[377]796
[1064]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    //!@}
[377]808
[1064]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    //! @{
[377]814
[1064]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    //! @{
[1066]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
[1064]831    //! \endcode
[1066]832    //! @}
[1064]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    }
[270]842};
[675]843SHAREDPTR ( epdf );
[32]844
[693]845//! pdf with internal epdf that is modified by function \c condition
[487]846template <class EPDF>
[693]847class pdf_internal: public pdf {
[600]848protected :
[1064]849    //! Internal epdf used for sampling
850    EPDF iepdf;
[600]851public:
[1064]852    //! constructor
853    pdf_internal() : pdf(), iepdf() {
854    }
[565]855
[1064]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;
[565]859
[1064]860    //!access function to iepdf
861    EPDF& e() {
862        return iepdf;
863    }
[488]864
[1064]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 );
[737]875
[1064]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    }
[487]884};
885
[270]886/*! \brief DataLink is a connection between two data vectors Up and Down
[2]887
[270]888Up can be longer than Down. Down must be fully present in Up (TODO optional)
889See chart:
890\dot
891digraph datalink {
[377]892  node [shape=record];
893  subgraph cluster0 {
894    label = "Up";
895      up [label="<1>|<2>|<3>|<4>|<5>"];
896    color = "white"
[270]897}
[377]898  subgraph cluster1{
899    label = "Down";
900    labelloc = b;
901      down [label="<1>|<2>|<3>"];
902    color = "white"
[270]903}
904    up:1 -> down:1;
905    up:3 -> down:2;
906    up:5 -> down:3;
907}
908\enddot
[263]909
[270]910*/
[600]911class datalink {
912protected:
[1064]913    //! Remember how long val should be
914    int downsize;
[424]915
[1064]916    //! Remember how long val of "Up" should be
917    int upsize;
[424]918
[1064]919    //! val-to-val link, indices of the upper val
920    ivec v2v_up;
[545]921
[600]922public:
[1064]923    //! Constructor
924    datalink() : downsize ( 0 ), upsize ( 0 ) { }
[424]925
[1064]926    //! Convenience constructor
927    datalink ( const RV &rv, const RV &rv_up ) {
928        set_connection ( rv, rv_up );
929    }
[271]930
[1064]931    //! set connection, rv must be fully present in rv_up
932    virtual void set_connection ( const RV &rv, const RV &rv_up );
[286]933
[1064]934    //! set connection using indices
935    virtual void set_connection ( int ds, int us, const ivec &upind );
[424]936
[1064]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() {}
[270]964};
[115]965
[598]966/*! Extension of datalink to fill only part of Down
967*/
[600]968class datalink_part : public datalink {
969protected:
[1064]970    //! indices of values in vector downsize
971    ivec v2v_down;
[600]972public:
[1064]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    }
[598]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*/
[600]984class datalink_buffered: public datalink_part {
985protected:
[1064]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;
[600]996public:
997
[1064]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    }
[600]1012
[1064]1013    void filldown ( const vec &val_up, vec &val_down ) {
1014        bdm_assert_debug ( val_down.length() >= downsize, "short val_down" );
[600]1015
[1064]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    }
[600]1019
[1064]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 );
[598]1024};
1025
[980]1026class vec_from_vec: public vec {
[1064]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    };
[980]1042};
1043
1044class vec_from_2vec: public vec {
[1064]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    };
[980]1061};
1062
[598]1063//! buffered datalink from 2 vectors to 1
[600]1064class datalink_2to1_buffered {
1065protected:
[1064]1066    //! link 1st vector to down
1067    datalink_buffered dl1;
1068    //! link 2nd vector to down
1069    datalink_buffered dl2;
[600]1070public:
[1064]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    }
[598]1087};
1088
[600]1089
1090
[424]1091//! Data link with a condition.
[600]1092class datalink_m2e: public datalink {
1093protected:
[1064]1094    //! Remember how long cond should be
1095    int condsize;
[424]1096
[1064]1097    //!upper_val-to-local_cond link, indices of the upper val
1098    ivec v2c_up;
[424]1099
[1064]1100    //!upper_val-to-local_cond link, indices of the local cond
1101    ivec v2c_lo;
[192]1102
[600]1103public:
[1064]1104    //! Constructor
1105    datalink_m2e() : condsize ( 0 ) { }
[545]1106
[1064]1107    //! Set connection between vectors
1108    void set_connection ( const RV &rv, const RV &rvc, const RV &rv_up );
[424]1109
[1064]1110    //!Construct condition
1111    vec get_cond ( const vec &val_up );
[545]1112
[1064]1113    //! Copy corresponding values to Up.condition
1114    void pushup_cond ( vec &val_up, const vec &val, const vec &cond );
[270]1115};
[424]1116
[693]1117//!DataLink is a connection between pdf and its superordinate (Up)
[192]1118//! This class links
[600]1119class datalink_m2m: public datalink_m2e {
1120protected:
[1064]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;
[424]1125
[600]1126public:
[1064]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 );
[1066]1134//         bdm_assert_debug ( c2c_lo.length() + v2c_lo.length() == condsize, "cond is not fully given" );
[1064]1135    }
[424]1136
[1064]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
[190]1150
[270]1151};
[190]1152
[267]1153
[693]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 );
[175]1156
[270]1157/*! \brief Abstract class for discrete-time sources of data.
[12]1158
[737]1159The class abstracts operations of:
1160\li  data aquisition,
1161\li  data-preprocessing, such as  scaling of data,
[603]1162\li  data resampling from the task of estimation and control.
[270]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).
[12]1164
[603]1165The DataSource has three main data interaction structures:
[1058]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
[270]1170*/
[32]1171
[600]1172class DS : public root {
[1064]1173    //! \var log_level_enums logdt
1174    //! log all outputs
[870]1175
[1064]1176    //! \var log_level_enums logut
1177    //! log all inputs
1178    LOG_LEVEL(DS,logdt,logut);
[907]1179
[600]1180protected:
[1064]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; //
[600]1189public:
[1064]1190    //! publicly acessible vector of observations
1191    vec dt;
1192    //! publicly writeble vector of inputs
1193    vec ut;
[565]1194
[1064]1195    //! default constructors
1196    DS() : dtsize ( 0 ), utsize ( 0 ), Drv(), Urv() {
1197        log_level[logdt] = true;
1198        log_level[logut] = true;
1199    };
[766]1200
[1064]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    };
[565]1210
[1064]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    };
[565]1216
[1064]1217    //! Accepts action variable and schedule it for application.
1218    virtual void write ( const vec &ut ) NOT_IMPLEMENTED_VOID;
[32]1219
[1064]1220    //! Accepts action variables at specific indices
1221    virtual void write ( const vec &ut, const ivec &indices ) NOT_IMPLEMENTED_VOID;
[32]1222
[1064]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;
[896]1225
[1064]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    }
[907]1238
[1064]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();
[270]1250};
[18]1251
[270]1252/*! \brief Bayesian Model of a system, i.e. all uncertainty is modeled by probabilities.
[32]1253
[283]1254This object represents exact or approximate evaluation of the Bayes rule:
1255\f[
[679]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})}
[283]1257\f]
[679]1258where:
[737]1259 * \f$ y_t \f$ is the variable
[283]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
[679]1265Alternatively, it can evaluate posterior density with rvc replaced by the given values, \f$ c_t \f$:
[283]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
[270]1270*/
[32]1271
[600]1272class BM : public root {
[1064]1273    //! \var log_level_enums logfull
1274    //! log full description of posterior in descriptive structure
[850]1275
[1064]1276    //! \var log_level_enums logevidence
1277    //! log value of eveidence in each step
[870]1278
[1064]1279    //! \var log_level_enums logbounds
1280    //! log lower and upper bounds of estimates
1281    LOG_LEVEL(BM,logfull,logevidence,logbounds);
1282
[600]1283protected:
[1064]1284    //! Random variable of the data (optional)
1285    RV yrv;
1286    //! size of the data record
1287    int dimy;
1288    //! Name of extension variable
1289    RV rvc;
1290    //! size of the conditioning vector
1291    int dimc;
[737]1292
[1064]1293    //!Logarithm of marginalized data likelihood.
1294    double ll;
1295    //!  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.
1296    bool evalll;
[679]1297
[600]1298public:
[1064]1299    //! \name Constructors
1300    //! @{
[271]1301
[1064]1302    BM() : yrv(), dimy ( 0 ), rvc(), dimc ( 0 ), ll ( 0 ), evalll ( true ) { };
[1066]1303    //    BM ( const BM &B ) :  yrv ( B.yrv ), dimy(B.dimy), rvc ( B.rvc ),dimc(B.dimc), ll ( B.ll ), evalll ( B.evalll ) {}
[1064]1304    //! \brief Copy function required in vectors, Arrays of BM etc. Have to be DELETED manually!
1305    //! Prototype: \code BM* _copy() const {return new BM(*this);} \endcode
1306    virtual BM* _copy() const NOT_IMPLEMENTED(NULL);
1307    //!@}
[18]1308
[1064]1309    //! \name Mathematical operations
1310    //!@{
[271]1311
[1064]1312    /*! \brief Incremental Bayes rule
1313    @param yt vector of input data
1314    */
1315    virtual void bayes ( const vec &yt, const vec &cond = empty_vec ) =0;
1316    //! Batch Bayes rule (columns of Dt are observations)
1317    virtual double bayes_batch ( const mat &Dt, const vec &cond = empty_vec );
1318    //! Batch Bayes rule (columns of Dt are observations, columns of Cond are conditions)
1319    virtual double bayes_batch ( const mat &Dt, const mat &Cond );
1320    //! Evaluates predictive log-likelihood of the given data record
1321    //! I.e. marginal likelihood of the data with the posterior integrated out.
1322    //! This function evaluates only \f$ y_t \f$, condition is assumed to be the last used in bayes().
1323    //! See bdm::BM::predictor for conditional version.
1324    virtual double logpred ( const vec &yt, const vec &cond ) const NOT_IMPLEMENTED(0.0);
[565]1325
[1064]1326    //! Matrix version of logpred
1327    vec logpred_mat ( const mat &Yt, const mat &Cond ) const {
1328        vec tmp ( Yt.cols() );
1329        for ( int i = 0; i < Yt.cols(); i++ ) {
1330            tmp ( i ) = logpred ( Yt.get_col ( i ), Cond.get_col(i) );
1331        }
1332        return tmp;
1333    }
[32]1334
[1064]1335    //!Constructs a predictive density \f$ f(d_{t+1} |d_{t}, \ldots d_{0}) \f$
1336    virtual epdf* epredictor(const vec &cond=vec()) const NOT_IMPLEMENTED(NULL);
[766]1337
[1064]1338    //!Constructs conditional density of 1-step ahead predictor \f$ f(d_{t+1} |d_{t+h-1}, \ldots d_{t}) \f$
1339    virtual pdf* predictor() const NOT_IMPLEMENTED(NULL);
[766]1340
[1064]1341    //!@}
[271]1342
[283]1343
[1064]1344    //! \name Access to attributes
1345    //!@{
1346    //! access function
1347    const RV& _rvc() const {
1348        return rvc;
1349    }
1350    //! access function
1351    int dimensionc() const {
1352        return dimc;
1353    }
1354    //! access function
1355    int dimensiony() const {
1356        return dimy;
1357    }
1358    //! access function
1359    int dimension() const {
1360        return posterior().dimension();
1361    }
1362    //! access function
1363    const RV& _rv() const {
1364        return posterior()._rv();
1365    }
1366    //! access function
1367    const RV& _yrv() const {
1368        return yrv;
1369    }
1370    //! access function
1371    void set_yrv ( const RV &rv ) {
1372        yrv = rv;
1373    }
1374    //! access function
1375    void set_rvc ( const RV &rv ) {
1376        rvc = rv;
1377    }
1378    //! access to rv of the posterior
1379    void set_rv ( const RV &rv ) {
1380        const_cast<epdf&> ( posterior() ).set_rv ( rv );
1381    }
1382    //! access function
1383    void set_dim ( int dim ) {
1384        const_cast<epdf&> ( posterior() ).set_dim ( dim );
1385    }
1386    //! return internal log-likelihood of the last data vector
1387    double _ll() const {
1388        return ll;
1389    }
1390    //! switch evaluation of log-likelihood on/off
1391    void set_evalll ( bool evl0 ) {
1392        evalll = evl0;
1393    }
1394    //! return posterior density
1395    virtual const epdf& posterior() const = 0;
[28]1396
[1064]1397    epdf& prior() {
1398        return const_cast<epdf&>(posterior());
1399    }
1400    //! set prior density -- same as posterior but writable
1401    virtual void set_prior(const epdf *pdf0) NOT_IMPLEMENTED_VOID;
[200]1402
[1064]1403    //!@}
[190]1404
[1064]1405    //! \name Logging of results
1406    //!@{
[738]1407
[1064]1408    //! Add all logged variables to a logger
1409    //! Log levels two digits: xy where
1410    //!  * y = 0/1 log-likelihood is to be logged
1411    //!  * x = level of the posterior (typically 0/1/2 for nothing/mean/bounds)
1412    virtual void log_register ( logger &L, const string &prefix = "" );
1413
1414    //! Save results to the given logger, details of what is stored is configured by \c LIDs and \c options
1415    virtual void log_write ( ) const;
1416
1417    //!@}
1418    //! \brief Read names of random variables from setting
1419    /*!
1420    reading structure:
1421    \TODO check if not remove... rv...
1422    \code
1423    yrv  = RV();               // names of modelled data
1424    rvc  = RV();               // names of data in condition
[989]1425    rv   = RV();               // names of parameters
[1064]1426    log_level = "logmean";     // identifiers of levels of detail to store to loggers
1427    \endcode
1428    */
1429    void from_setting ( const Setting &set ) {
1430        UI::get(yrv, set, "yrv", UI::optional );
1431        UI::get(rvc, set, "rvc", UI::optional );
1432        RV r;
1433        UI::get(r, set, "rv", UI::optional );
1434        set_rv ( r );
[573]1435
[1064]1436        UI::get ( log_level, set, "log_level", UI::optional );
1437    }
[746]1438
[1064]1439    void to_setting ( Setting &set ) const {
1440        root::to_setting( set );
1441        UI::save( &yrv, set, "yrv" );
1442        UI::save( &rvc, set, "rvc" );
1443        UI::save( &posterior()._rv(), set, "rv" );
1444        UI::save( log_level, set );
1445    }
1446
1447    //! process
1448    void validate()
1449    {
1450        if ( log_level[logbounds] ) {
1451            const_cast<epdf&> ( posterior() ).log_level[epdf::loglbound] = true;
1452        } else {
1453            const_cast<epdf&> ( posterior() ).log_level[epdf::logmean] = true;;
1454        }
1455    }
[768]1456};
[746]1457
[660]1458//! array of pointers to epdf
[529]1459typedef Array<shared_ptr<epdf> > epdf_array;
[693]1460//! array of pointers to pdf
1461typedef Array<shared_ptr<pdf> > pdf_array;
[529]1462
[488]1463template<class EPDF>
[693]1464vec pdf_internal<EPDF>::samplecond ( const vec &cond ) {
[1064]1465    condition ( cond );
1466    vec temp = iepdf.sample();
1467    return temp;
[488]1468}
[339]1469
[488]1470template<class EPDF>
[713]1471mat pdf_internal<EPDF>::samplecond_mat ( const vec &cond, int N ) {
[1064]1472    condition ( cond );
1473    mat temp ( dimension(), N );
1474    vec smp ( dimension() );
1475    for ( int i = 0; i < N; i++ ) {
1476        smp = iepdf.sample();
1477        temp.set_col ( i, smp );
1478    }
[488]1479
[1064]1480    return temp;
[488]1481}
1482
1483template<class EPDF>
[693]1484double pdf_internal<EPDF>::evallogcond ( const vec &yt, const vec &cond ) {
[1064]1485    double tmp;
1486    condition ( cond );
1487    tmp = iepdf.evallog ( yt );
1488    return tmp;
[488]1489}
1490
1491template<class EPDF>
[713]1492vec pdf_internal<EPDF>::evallogcond_mat ( const mat &Yt, const vec &cond ) {
[1064]1493    condition ( cond );
1494    return iepdf.evallog_mat ( Yt );
[488]1495}
1496
1497template<class EPDF>
[713]1498vec pdf_internal<EPDF>::evallogcond_mat ( const Array<vec> &Yt, const vec &cond ) {
[1064]1499    condition ( cond );
1500    return iepdf.evallog_mat ( Yt );
[488]1501}
1502
[254]1503}; //namespace
[384]1504#endif // BDMBASE_H
Note: See TracBrowser for help on using the browser.