/*! \file \brief Bayesian Models (bm) that use Bayes rule to learn from observations \author Vaclav Smidl. ----------------------------------- BDM++ - C++ library for Bayesian Decision Making under Uncertainty Using IT++ for numerical operations ----------------------------------- */ #ifndef root_H #define root_H #include #include #include "itpp_ext.h" #include "bdmerror.h" #ifdef MEX #include "base/libconfig/lib/libconfig.h++" // TODO DODELAT A NAHRADIT #include "base/libconfig_mex.h" #else #include "base/libconfig/lib/libconfig.h++" #endif using namespace libconfig; using namespace itpp; using namespace std; namespace bdm { //! auxiliary function for debugging void UI_DBG (const Setting &S, const string &spc, ostream &out ); //! level of details that will be logged to a logger // DULEZITE TODO - zde musi respektovat aktualne ulozene hodnoty, tj. nacist je, pak pridat // ty co se maji v tomto kroku ulozit a pak vse ulozit.. protoze to delame kompozici a ne dedenim DODELAT // ALE HOUBY, TAKHLE TO NEJDE, musime nechat jako samostatny objekt, kazda uroven tedy zvlast, // jednoznacne jmeno atd.. // //! information about connection to a logger template class logged_options { private: friend class UI; //! boolean flags related indicating which details will be logged to a logger bitset<32> values; const Array &names() const { return T::option_names(); } public: bool any() const { return values.any(); } bool operator [] (const enum T::possible_options &option ) const { return values[option]; } bitset<32>::reference operator [] (const enum T::possible_options &option ) { return values[option]; } }; // MUZEME INTERNE POUZIVAT ENUMY, A KLIDNE MENIT JEJICH PORADI, DIKY TOMUHLE MAKRU SE VZDY NAMAPUJI NA TY SPRAVNE STRINGY #define LOG_LEVEL(CLASSNAME,...) private: friend class logged_options; static const Array &option_names() { static const Array option_names( "{"#__VA_ARGS__" }" ); return option_names; }; public: enum possible_options { __VA_ARGS__ }; logged_options log_level; //forward declaration class logger; //! information about connection to a logger class log_record { public: //!remember which logger is registered logger &L; //! vector of log IDs - one element for each entry ivec ids; //!default constructor log_record ( logger &L0 ) : L ( L0 ), ids ( 0 ) {} }; //! Root class of BDM objects class root { private: //! It is necessary to allow calling of from_setting and to_setting within the UI class ++ i log_options friend class UI; // TODO okomentovat static const Array &option_names() { static const Array option_names; return option_names; }; protected: //! record of connections to the logger log_record* logrec; /*! \brief Read instance properties according the data stored in the Setting structure. It has to be called only through UI class, therefore it is protected At the begining of this method, it is obligatory to call the corresponding base::from_setting method. Sometimes, there can be an exception from this rule. If so, the programmer is encouraged to describe the reasons for this exception in the documentation in detail. Then, all the configuration components should be read through the UI mechanism. Those with UI::SettingPresence set to optional shoud have their defaults fulfilled within the body of this method. For instance, declaring a class \c trunk derived from our #root class, the implementation of the from_setting method should look like this \code public trunk : public root { anytype xxx, yyy; virtual void from_setting ( const Setting &set ) { root::from_setting( set ); UI::get ( xxx, set, "xxx", UI::compulsory ); if ( !UI::get ( yyy, set, "yyy", UI::optional ) ) { ... // here, it is necessary to set the default of attribute yyy } ... // another stuff related to trunk class } ... // other members of this class }; \endcode */ virtual void from_setting ( const Setting &set ) { } /*! \brief Save all the instance properties into the Setting structure. It has to be called only through UI class, therefore it is protected The only obligatory rule concerning the body of this method is to call the corresponding base::to_setting method first. Sometimes, there can be an exception from this rule. If so, the programmer is encouraged to describe the reasons for this exception in the documentation in detail. For instance, declaring a class \c trunk derived from our #root class, the implementation of the to_setting method should look like this \code public trunk : public root { anytype xxx; virtual void to_setting ( const Setting &set ) { root::to_setting( set ); UI::save ( xxx, set, "xxx" ); ... // another stuff related directly to trunk class } ... // other members of this class }; \endcode */ virtual void to_setting ( Setting &set ) const { } public: // TODO okomentovat enum possible_options { }; //!default constructor root() : logrec ( NULL ) {}; //! make sure this is a virtual object virtual ~root() { if ( logrec ) delete logrec; } //! Returns basic textual info about the current instance virtual string to_string() const { Config C; Setting &set=C.getRoot(); this->to_setting(set); ostringstream os; UI_DBG(set, "", os); return os.str(); } //! Register itself in a logger, i.e. allocate space for data from this class //! The level of details (parameter \c level ) is individual for each class. virtual void log_register ( logger &L, const string &prefix ) { logrec = new log_record ( L ); } //! Write current information into the given logger virtual void log_write() const { } /*! \brief This method checks that all internal structures has been set up correctly. It is called automatically after the call of the #from_setting method by the mechanism of the UI class. However, it can be called in any other situation to assure the correctness of an instance. The only obligatory rule concerning the body of this method is to call the corresponding base::validate method first. Sometimes, there can be an exception from this rule. If so, the programmer is encouraged to describe the reasons for this exception in the documentation in detail. Then, only those checks which are not implemented in the base method are implemented here. For instance, declaring a class \c trunk derived from our #root class, the implementation of the method validate should look like this \code public trunk : public root { virtual void validate ( ) { root::validate( ); ... // checks related directly to trunk class } ... // other members of this class }; \endcode */ virtual void validate() { } //! Virtual method providing deep copy of instances virtual root* _copy() const NOT_IMPLEMENTED(NULL); }; }; //namespace #endif // root_H