PLearn 0.1
Option.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PLearn (A C++ Machine Learning Library)
00004 // Copyright (C) 1998 Pascal Vincent
00005 // Copyright (C) 1999-2002 Pascal Vincent and Yoshua Bengio
00006 // Copyright (C) 2002 Frederic Morin
00007 // Copyright (C) 2002-2005 University of Montreal
00008 
00009 // Redistribution and use in source and binary forms, with or without
00010 // modification, are permitted provided that the following conditions are met:
00011 // 
00012 //  1. Redistributions of source code must retain the above copyright
00013 //     notice, this list of conditions and the following disclaimer.
00014 // 
00015 //  2. Redistributions in binary form must reproduce the above copyright
00016 //     notice, this list of conditions and the following disclaimer in the
00017 //     documentation and/or other materials provided with the distribution.
00018 // 
00019 //  3. The name of the authors may not be used to endorse or promote
00020 //     products derived from this software without specific prior written
00021 //     permission.
00022 // 
00023 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00024 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00025 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00026 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00027 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00028 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 // 
00034 // This file is part of the PLearn library. For more information on the PLearn
00035 // library, go to the PLearn Web site at www.plearn.org
00036 
00037 
00038 
00039 /* *******************************************************      
00040  * $Id: Option.h 9788 2008-12-16 21:27:07Z nouiz $
00041  * This file is part of the PLearn library.
00042  ******************************************************* */
00043 
00044 
00047 #ifndef Option_INC
00048 #define Option_INC
00049 
00050 #include "OptionBase.h"
00051 #include <plearn/base/ObjectConversions.h>
00052 #include <plearn/base/diff.h>
00053 #include <plearn/base/lexical_cast.h>
00054 
00055 namespace PLearn {
00056 using std::string;
00057 
00059 template <class T> class TVec;
00060 template<class ObjectType, class OptionType> class Option;
00061 class PLearnDiff;
00062 
00063 template<class ObjectType, class OptionType>
00064 class DiffTemplate
00065 {
00066 public:
00067     static int diff(const string& refer, const string& other,
00068                     const Option<ObjectType, OptionType>* opt,
00069                     PLearnDiff* diffs)
00070     {
00071         /*
00072         pout << "Called defaut DiffTemplate<" << TypeTraits<ObjectType>::name()
00073             << " , " << TypeTraits<OptionType>::name() << ">::diff(...)" <<
00074             endl;
00075         */
00076         return PLearn::diff(refer, other, opt, diffs);
00077     }
00078 };
00079 
00080 //#####  Generic Option  ######################################################
00081   
00083 template<class ObjectType, class OptionType>
00084 class Option : public OptionBase
00085 {
00086     typedef OptionBase inherited;
00087   
00088 protected:
00089     OptionType ObjectType::*ptr;
00090 
00091 public:
00092 
00095     Option(const string& optionname, OptionType ObjectType::* member_ptr, 
00096            flag_t flags, const string& optiontype, const string& defaultval,
00097            const string& description, const OptionLevel& level)
00098         : inherited(optionname, flags, optiontype, defaultval, description, level),
00099           ptr(member_ptr)
00100     { }
00101 
00102     virtual void read(Object* o, PStream& in) const
00103     { (void)(in >> dynamic_cast<ObjectType*>(o)->*ptr); }
00104 
00105     virtual void write(const Object* o, PStream& out) const
00106     { (void)(out << dynamic_cast<ObjectType *>(const_cast<Object*>(o))->*ptr); }
00107 
00108     virtual Object* getAsObject(Object* o) const
00109     { return toObjectPtr(dynamic_cast<ObjectType*>(o)->*ptr); }
00110 
00111     virtual const Object* getAsObject(const Object* o) const
00112     { return toObjectPtr(dynamic_cast<const ObjectType*>(o)->*ptr); }
00113 
00114     virtual Object *getIndexedObject(Object *o, int i) const
00115     { return toIndexedObjectPtr(dynamic_cast<ObjectType*>(o)->*ptr, i); };
00116 
00117     virtual const Object* getIndexedObject(const Object *o, int i) const
00118     { return toIndexedObjectPtr(dynamic_cast<const ObjectType*>(o)->*ptr, i); };
00119 
00120     virtual void* getAsVoidPtr(Object* o) const
00121     { return &(dynamic_cast<ObjectType*>(o)->*ptr); }
00122     
00123     virtual const void* getAsVoidPtr(const Object* o) const
00124     { return &(dynamic_cast<const ObjectType*>(o)->*ptr); }
00125 
00126 #ifdef PL_PYTHON_VERSION 
00127     virtual PythonObjectWrapper getAsPythonObject(Object* o) const 
00128     { 
00129         return PythonObjectWrapper(*(OptionType*)getAsVoidPtr(o)); 
00130     }
00131 
00132     virtual PythonObjectWrapper getAsPythonObject(const Object* o) const 
00133     { 
00134         return PythonObjectWrapper(*(OptionType*)getAsVoidPtr(o)); 
00135     }
00136 
00137     virtual void setFromPythonObject(Object* o, const PythonObjectWrapper& v) const
00138     {
00139         dynamic_cast<ObjectType*>(o)->*ptr=
00140             ConvertFromPyObject<OptionType>::convert(v.getPyObject(), true);
00141     }
00142 
00143 #endif //def PL_PYTHON_VERSION 
00144 
00145     virtual string optionHolderClassName(const Object* o) const
00146     { return dynamic_cast<const ObjectType*>(o)->ObjectType::_classname_(); }
00147 
00148     virtual int diff(const string& refer, const string& other,
00149                      PLearnDiff* diffs) const
00150     {
00151         /*
00152         pout << "Calling Option<" << TypeTraits<ObjectType>::name()
00153             << "," << TypeTraits<OptionType>::name() << ">::diff" << endl;
00154         */
00155         // return PLearn::diff(refer, other, this, diffs);
00156         return DiffTemplate<ObjectType, OptionType>::diff(refer, other,
00157                                                           this, diffs);
00158     }
00159 
00162     virtual bool isAccessibleAsObject() const
00163     {
00164         static bool accessible = isConvertibleToObjectPtr(OptionType());
00165         return accessible;
00166     }
00167 
00168     virtual int indexableSize(const Object* o) const
00169     {
00170         const ObjectType* oto = dynamic_cast<const ObjectType*>(o);
00171         PLASSERT( oto );
00172         return indexableObjectSize(oto->*ptr);
00173     }
00174 
00176     OptionType ObjectType::* getPtr() const
00177     {
00178         return ptr;
00179     }
00180 };
00181 
00188 template<class OptionType>
00189 class StaticOption : public OptionBase
00190 {
00191     typedef OptionBase inherited;
00192   
00193 protected:
00194     OptionType* ptr;
00195 
00196 public:
00197 
00200     StaticOption(const string& optionname, OptionType* member_ptr, 
00201            flag_t flags, const string& optiontype, const string& defaultval,
00202            const string& description, const OptionLevel& level)
00203         : inherited(optionname, flags, optiontype, defaultval, description, level),
00204           ptr(member_ptr)
00205     { }
00206 
00207     virtual void read(Object* o, PStream& in) const
00208     { in >> *ptr; }
00209 
00210     virtual void write(const Object* o, PStream& out) const
00211     { out << *ptr; }
00212 
00213     virtual Object* getAsObject(Object* o) const
00214     { return toObjectPtr(*ptr); }
00215 
00216     virtual const Object* getAsObject(const Object* o) const
00217     { return toObjectPtr(*ptr); }
00218 
00219     virtual Object *getIndexedObject(Object *o, int i) const
00220     { return toIndexedObjectPtr(*ptr, i); };
00221 
00222     virtual const Object* getIndexedObject(const Object *o, int i) const
00223     { return toIndexedObjectPtr(*ptr, i); };
00224 
00225     virtual void* getAsVoidPtr(Object* o) const
00226     { return ptr; }
00227     
00228     virtual const void* getAsVoidPtr(const Object* o) const
00229     { return ptr; }
00230 
00231 
00233 #ifdef PL_PYTHON_VERSION 
00234     virtual PythonObjectWrapper getAsPythonObject(Object* o) const 
00235     { 
00236         return PythonObjectWrapper(*(OptionType*)getAsVoidPtr(o)); 
00237     }
00238 
00239     virtual PythonObjectWrapper getAsPythonObject(const Object* o) const 
00240     { 
00241         return PythonObjectWrapper(*(OptionType*)getAsVoidPtr(o)); 
00242     }
00243 
00244     virtual void setFromPythonObject(Object* o, const PythonObjectWrapper& v) const
00245     {
00246         *ptr=
00247             ConvertFromPyObject<OptionType>::convert(v.getPyObject(), true);
00248     }
00249 
00250 #endif //def PL_PYTHON_VERSION 
00251 
00252     virtual string optionHolderClassName(const Object* o) const
00253     { return "static"; }
00254 
00255     virtual int diff(const string& refer, const string& other,
00256                      PLearnDiff* diffs) const
00257     {
00258         /*
00259         pout << "Calling Option<" << TypeTraits<ObjectType>::name()
00260             << "," << TypeTraits<OptionType>::name() << ">::diff" << endl;
00261         */
00262         // return PLearn::diff(refer, other, this, diffs);       
00263         //return DiffTemplate<ObjectType, OptionType>::diff(refer, other,
00264         //                                                  this, diffs);
00265         // @todo: quick hack, fix this (maybe? Xavier?)
00266         return 0;
00267     }
00268 
00271     virtual bool isAccessibleAsObject() const
00272     {
00273         static bool accessible = isConvertibleToObjectPtr(OptionType());
00274         return accessible;
00275     }
00276 
00277     virtual int indexableSize(const Object* o) const
00278     {
00279         return indexableObjectSize(*ptr);
00280     }
00281 
00284     /*
00285     OptionType ObjectType::* getPtr() const
00286     {
00287         return ptr;
00288     }
00289     */
00290 };
00291 
00292 //#####  TVec-Specific Option  ################################################
00293 
00294 // This is a special version of Option designed for TVec<T>.
00295 // The only difference is that it supports indexed reads and writes.
00296 template<class ObjectType, class VecElementType>
00297 class TVecOption : public Option<ObjectType, TVec<VecElementType> >
00298 {
00299     typedef Option<ObjectType, TVec<VecElementType> > inherited;
00300   
00301 public:
00302     TVecOption(const string& optionname, TVec<VecElementType> ObjectType::* member_ptr, 
00303                OptionBase::flag_t flags, const string& optiontype, const string& defaultval,
00304                const string& description, const OptionBase::OptionLevel& level)
00305         : inherited(optionname, member_ptr, flags, optiontype, defaultval,
00306                     description, level)
00307     { }
00308 
00309     virtual void readIntoIndex(Object* o, PStream& in, const string& index)
00310     {
00311         int i = tolong(index);
00312         in >> (dynamic_cast<ObjectType*>(o)->*(this->ptr))[i];
00313     }
00314 
00315     virtual void writeAtIndex(const Object* o, PStream& out, const string& index) const
00316     {
00317         int i = tolong(index);
00318         out << (dynamic_cast<ObjectType*>(const_cast<Object*>(o))->*(this->ptr))[i];
00319     }
00320 
00321 };
00322 
00323 
00324 // This is a special version of Option designed for TVec<T>.
00325 // The only difference is that it supports indexed reads and writes.
00326 template<class VecElementType>
00327 class TVecStaticOption : public StaticOption<TVec<VecElementType> >
00328 {
00329     typedef StaticOption<TVec<VecElementType> > inherited;
00330   
00331 public:
00332     TVecStaticOption(const string& optionname, TVec<VecElementType> * member_ptr, 
00333                OptionBase::flag_t flags, const string& optiontype, const string& defaultval,
00334                const string& description, const OptionBase::OptionLevel& level)
00335         : inherited(optionname, member_ptr, flags, optiontype, defaultval,
00336                     description, level)
00337     { }
00338 
00339     virtual void readIntoIndex(Object* o, PStream& in, const string& index)
00340     {
00341         int i = tolong(index);
00342         in >> (*(this->ptr))[i];
00343     }
00344 
00345     virtual void writeAtIndex(const Object* o, PStream& out, const string& index) const
00346     {
00347         int i = tolong(index);
00348         out << (*(this->ptr))[i];
00349     }
00350 
00351 };
00352 
00353 //#####  declareOption and Friends  ###########################################
00354 
00369 template <class ObjectType, class OptionType>
00370 inline void declareOption(OptionList& ol,                      
00371                           const string& optionname,            
00372                           OptionType ObjectType::* member_ptr, 
00373                           OptionBase::flag_t flags,            
00374                           const string& description,           
00375                           const OptionBase::OptionLevel level= OptionBase::default_level, 
00376                           const string& defaultval="")         
00377 {
00378     ol.push_back(new Option<ObjectType, OptionType>(optionname, member_ptr, flags, 
00379                                                     TypeTraits<OptionType>::name(), 
00380                                                     defaultval, description, level));
00381 }
00382 
00383 
00384 // Overload for simple pointers
00385 template <class ObjectType, class OptionType>
00386 inline void declareOption(OptionList& ol,
00387                           const string& optionname,
00388                           OptionType* ObjectType::* member_ptr,
00389                           OptionBase::flag_t flags,
00390                           const string& description,
00391                           const OptionBase::OptionLevel level= OptionBase::default_level,
00392                           const string& defaultval="")
00393 {
00394     ol.push_back(new Option<ObjectType, OptionType *>(optionname, member_ptr, flags,
00395                                                       TypeTraits<OptionType *>::name(), 
00396                                                       defaultval, description, level));
00397 }
00398 
00403 template <class OptionType>
00404 inline void declareStaticOption(OptionList& ol,                      
00405                           const string& optionname,            
00406                           OptionType* ptr,                     
00407                           OptionBase::flag_t flags,            
00408                           const string& description,           
00409                           const OptionBase::OptionLevel level= OptionBase::default_level, 
00410                           const string& defaultval="")         
00411 {
00412     ol.push_back(new StaticOption<OptionType>(optionname, ptr, flags, 
00413                                                     TypeTraits<OptionType>::name(), 
00414                                                     defaultval, description, level));
00415 }
00416 
00417 // Overload for TVec<T>
00418 template <class VecElementType>//, class VecElementType>
00419 inline void declareStaticOption(OptionList& ol,                      
00420                           const string& optionname,            
00421                           TVec<VecElementType> * ptr,                     
00422                           OptionBase::flag_t flags,            
00423                           const string& description,           
00424                           const OptionBase::OptionLevel level= OptionBase::default_level, 
00425                           const string& defaultval="")         
00426 {
00427     ol.push_back(new TVecStaticOption<VecElementType>(
00428                      optionname, ptr, flags, 
00429                      TypeTraits< TVec<VecElementType> >::name(), 
00430                      defaultval, description, level));
00431 }
00432 
00433 
00434 
00435 // Overload for TVec<T>
00436 template <class ObjectType, class VecElementType>
00437 inline void declareOption(OptionList& ol,
00438                           const string& optionname,
00439                           TVec<VecElementType> ObjectType::* member_ptr,
00440                           OptionBase::flag_t flags,
00441                           const string& description,
00442                           const OptionBase::OptionLevel level= OptionBase::default_level,
00443                           const string& defaultval="")
00444 {
00445     ol.push_back(new TVecOption<ObjectType, VecElementType>(
00446                      optionname, member_ptr, flags,
00447                      TypeTraits< TVec<VecElementType> >::name(),
00448                      defaultval, description, level));
00449 }
00450 
00451 
00454 template<class ObjectType, class OptionType>
00455 inline void redeclareOption(OptionList& ol,                      
00456                             const string& optionname,            
00457                             OptionType ObjectType::* member_ptr, 
00458                             OptionBase::flag_t flags,            
00459                             const string& description,           
00460                             const OptionBase::OptionLevel level= OptionBase::default_level, 
00461                             const string& defaultval="")         
00462 {
00463     bool found = false;
00464     for (OptionList::iterator it = ol.begin(); !found && it != ol.end(); it++) {
00465         if ((*it)->optionname() == optionname) {
00466             // We found the option to redeclare.
00467             found = true;
00468             (*it) = new Option<ObjectType, OptionType>
00469                 (optionname, member_ptr, flags, TypeTraits<OptionType>::name(), defaultval, description, level);
00470         }
00471     }
00472     if (!found) {
00473         // We tried to redeclare an option that wasn't declared previously.
00474         PLERROR("Option::redeclareOption: trying to redeclare option '%s' that has "
00475                 "not been declared before", optionname.c_str());
00476     }
00477 }
00478 
00480 template<class ObjectType, class OptionType>
00481 inline void redeclareOption(OptionList& ol,                      
00482                             const string& optionname,            
00483                             OptionType* ObjectType::* member_ptr,
00484                             OptionBase::flag_t flags,            
00485                             const string& description,           
00486                             const OptionBase::OptionLevel level= OptionBase::default_level, 
00487                             const string& defaultval="")         
00488 {
00489     bool found = false;
00490     for (OptionList::iterator it = ol.begin(); !found && it != ol.end(); it++) {
00491         if ((*it)->optionname() == optionname) {
00492             // We found the option to redeclare.
00493             found = true;
00494             (*it) = new Option<ObjectType, OptionType*>
00495                 (optionname, member_ptr, flags, TypeTraits<OptionType*>::name(), defaultval, description, level);
00496         }
00497     }
00498     if (!found) {
00499         // We tried to redeclare an option that wasn't declared previously.
00500         PLERROR("Option::redeclareOption: trying to redeclare option '%s' that has "
00501                 "not been declared before", optionname.c_str());
00502     }
00503 }
00504 
00506 template<class ObjectType, class VecElementType>
00507 inline void redeclareOption(OptionList& ol,
00508                             const string& optionname,
00509                             TVec<VecElementType> ObjectType::* member_ptr,
00510                             OptionBase::flag_t flags,
00511                             const string& description,
00512                             const OptionBase::OptionLevel level= OptionBase::default_level,
00513                             const string& defaultval="")
00514 {
00515     bool found = false;
00516     for (OptionList::iterator it = ol.begin(); !found && it != ol.end(); it++) {
00517         if ((*it)->optionname() == optionname) {
00518             // We found the option to redeclare.
00519             found = true;
00520             (*it) = new TVecOption<ObjectType, VecElementType>
00521                 (optionname, member_ptr, flags,
00522                  TypeTraits< TVec<VecElementType> >::name(),
00523                  defaultval, description, level);
00524         }
00525     }
00526     if (!found) {
00527         // We tried to redeclare an option that wasn't declared previously.
00528         PLERROR("Option::redeclareOption: trying to redeclare option '%s' that has "
00529                 "not been declared before", optionname.c_str());
00530     }
00531 }
00532 
00533 } // end of namespace PLearn
00534 
00535 #endif //!<  Option_INC
00536 
00537 
00538 /*
00539   Local Variables:
00540   mode:c++
00541   c-basic-offset:4
00542   c-file-style:"stroustrup"
00543   c-file-offsets:((innamespace . 0)(inline-open . 0))
00544   indent-tabs-mode:nil
00545   fill-column:79
00546   End:
00547 */
00548 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines