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

Revision 914, 41.8 kB (checked in by smidl, 14 years ago)

linux compilation

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