PLearn 0.1
|
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 :