![]() |
GURLS++
2.0.00
C++ Implementation of GURLS Matlab Toolbox
|
00001 /* 00002 * The GURLS Package in C++ 00003 * 00004 * Copyright (C) 2011-1013, IIT@MIT Lab 00005 * All rights reserved. 00006 * 00007 * author: M. Santoro 00008 * email: msantoro@mit.edu 00009 * website: http://cbcl.mit.edu/IIT@MIT/IIT@MIT.html 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions 00013 * are met: 00014 * 00015 * * Redistributions of source code must retain the above 00016 * copyright notice, this list of conditions and the following 00017 * disclaimer. 00018 * * Redistributions in binary form must reproduce the above 00019 * copyright notice, this list of conditions and the following 00020 * disclaimer in the documentation and/or other materials 00021 * provided with the distribution. 00022 * * Neither the name(s) of the copyright holders nor the names 00023 * of its contributors or of the Massacusetts Institute of 00024 * Technology or of the Italian Institute of Technology may be 00025 * used to endorse or promote products derived from this software 00026 * without specific prior written permission. 00027 * 00028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00029 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00030 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00031 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00032 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00033 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00034 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00035 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00036 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00037 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00038 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00039 * POSSIBILITY OF SUCH DAMAGE. 00040 */ 00041 00042 #include <string> 00043 #include <sstream> 00044 #include <iostream> 00045 #include <algorithm> 00046 #include <numeric> 00047 #include <vector> 00048 00049 #include "gurls++/options.h" 00050 #include "gurls++/optfunction.h" 00051 #include "gurls++/optlist.h" 00052 #ifdef _BGURLS 00053 #include "bgurls++/bigarray.h" 00054 #endif 00055 #include "gurls++/serialization.h" 00056 00057 #include <boost/algorithm/string/split.hpp> 00058 #include <boost/algorithm/string/classification.hpp> 00059 00060 using namespace std; 00061 00062 namespace gurls{ 00063 00064 void GurlsOptionsList::setName(std::string newname) 00065 { 00066 name = newname; 00067 removeOpt("Name"); 00068 (*table)["Name"] = new OptString(newname); 00069 } 00070 00071 GurlsOptionsList::GurlsOptionsList(std::string ExpName, bool usedefopt): GurlsOption(OptListOption), name(ExpName) 00072 { 00073 table = new std::map<std::string, GurlsOption* >(); 00074 00075 (*table)["Name"] = new OptString(ExpName); 00076 00077 if(usedefopt) 00078 { 00079 00080 // opt.combineclasses = @mean; % How to combine performance measure per class (mean/median/min/max?) 00081 (*table)["combineclasses"] = new OptFunction("mean"); 00082 00083 (*table)["name"] = new OptString(ExpName); 00084 (*table)["plotstr"] = new OptString(ExpName); 00085 00086 #ifdef USE_BINARY_ARCHIVES 00087 (*table)["savefile"] = new OptString(ExpName.append(".bin")); 00088 #else 00089 (*table)["savefile"] = new OptString(ExpName.append(".txt")); 00090 #endif 00091 00092 // ================================================== Algorithm options 00093 00094 // opt.kernel.type = 'rbf'; 00095 (*table)["singlelambda"] = new OptFunction("median"); 00096 (*table)["predbagmethod"] = new OptString("vote"); 00097 00098 // NOTE: lambda is searched between 00099 // [min(eig_r, opt.smallnumber), eig_1], 00100 // where r = rank, eig_1 = max eig val. 00101 (*table)["smallnumber"] = new OptNumber(1e-8); 00102 00103 // ================================================== Directory options 00104 (*table)["tmpdir"] = new OptString(ExpName); 00105 00106 // ===================================================== Output options 00107 (*table)["savekernel"] = new OptNumber(1); 00108 (*table)["saveanalysis"] = new OptNumber(1); 00109 // opt.hoperf = @perf_precrec; 00110 (*table)["ploteval"] = new OptString("acc"); 00111 // WARNING: this should be an array of strings... 00112 (*table)["perfeval"] = new OptString("acc"); 00113 00114 // ======================================================== Data option 00115 (*table)["nholdouts"] = new OptNumber(1); 00116 (*table)["hoproportion"] = new OptNumber(0.2); 00117 (*table)["hoperf"] = new OptString("macroavg"); 00118 // (*table)["nlambda"] = new OptNumber(100); 00119 (*table)["nsigma"] = new OptNumber(25); 00120 (*table)["nlambda"] = new OptNumber(20); 00121 // (*table)["nsigma"] = new OptNumber(10); 00122 (*table)["eig_percentage"] = new OptNumber(5); 00123 00124 00125 // ======================================================== Pegasos option 00126 (*table)["subsize"] = new OptNumber(50); 00127 (*table)["calibfile"] = new OptString("foo"); 00128 (*table)["epochs"] = new OptNumber(4); 00129 00130 // ============================================================== Quiet 00131 // Currenty either 0 or 1; levels of verbosity may be implemented later; 00132 (*table)["verbose"] = new OptNumber(1); 00133 00134 // ======================================================= Version info 00135 (*table)["version"] = new OptString("2.0"); 00136 00137 00138 GurlsOptionsList * randfeats = new GurlsOptionsList("randfeats"); 00139 randfeats->table->insert(pair<std::string,GurlsOption*>("D", new OptNumber(500))); 00140 randfeats->table->insert(pair<std::string,GurlsOption*>("samplesize", new OptNumber(100))); 00141 00142 (*table)["randfeats"] = randfeats; 00143 00144 } 00145 00146 } 00147 00148 GurlsOptionsList::GurlsOptionsList(const GurlsOptionsList &other): GurlsOption(OptListOption) 00149 { 00150 table = new ValueType(); 00151 00152 ValueType::const_iterator it, end; 00153 00154 for(it = other.table->begin(), end = other.table->end(); it != end; ++it) 00155 copyOpt(it->first, other); 00156 00157 name = getOptAsString("Name"); 00158 } 00159 00160 GurlsOptionsList::~GurlsOptionsList() 00161 { 00162 ValueType::iterator it, end; 00163 00164 for(it = table->begin(), end = table->end(); it != end; ++it) 00165 delete (it->second); 00166 00167 table->clear(); 00168 delete table; 00169 } 00170 00171 void GurlsOptionsList::printAll() 00172 { 00173 std::cout << *this; 00174 } 00175 00176 bool GurlsOptionsList::hasOpt(string key) const 00177 { 00178 //return table->count(key)>0; 00179 try 00180 { 00181 getOpt((key)); 00182 return true; 00183 } 00184 catch(gException&) 00185 { 00186 return false; 00187 } 00188 } 00189 00190 void GurlsOptionsList::removeOpt(string key, bool deleteMembers) 00191 { 00192 ValueType::iterator it = table->find(key); 00193 if(it != table->end()) 00194 { 00195 if (deleteMembers) 00196 delete it->second; 00197 00198 table->erase(it); 00199 } 00200 } 00201 00202 bool GurlsOptionsList::isA(OptTypes id) const 00203 { 00204 return (id == OptListOption); 00205 } 00206 00207 GurlsOptionsList *GurlsOptionsList::dynacast(GurlsOption *opt) 00208 { 00209 if (opt->isA(OptListOption) ) 00210 return static_cast<GurlsOptionsList*>(opt); 00211 00212 throw gException(gurls::Exception_Illegal_Dynamic_Cast); 00213 } 00214 00215 const GurlsOptionsList *GurlsOptionsList::dynacast(const GurlsOption *opt) 00216 { 00217 if (opt->isA(OptListOption) ) 00218 return static_cast<const GurlsOptionsList*>(opt); 00219 00220 throw gException(gurls::Exception_Illegal_Dynamic_Cast); 00221 } 00222 00223 int GurlsOptionsList::size() const 00224 { 00225 return table->size(); 00226 } 00227 00228 GurlsOption *GurlsOptionsList::operator [](int idx) 00229 { 00230 if ( idx >= this->size() ) 00231 throw gException(gurls::Exception_Index_Out_of_Bound); 00232 00233 ValueType::iterator itr = table->begin(); 00234 00235 for (int i = 0; i<idx; ++i, ++itr){} // Do nothing else then following the iterator 00236 00237 return itr->second; 00238 } 00239 00240 std::ostream& GurlsOptionsList::operator<<(std::ostream& os) const 00241 { 00242 return os << *this; 00243 } 00244 00245 string GurlsOptionsList::toString() 00246 { 00247 std::stringstream stream; 00248 stream << (*this); 00249 00250 return stream.str(); 00251 } 00252 00253 //template<typename T> 00254 //GurlsOption* copyOptMatrix(const GurlsOption* toCopy) 00255 //{ 00256 // const gMat2D<T> & mat = OptMatrix<gMat2D<T> >::dynacast(toCopy)->getValue(); 00257 00258 // gMat2D<T>* newMat = new gMat2D<T>(mat); 00259 // return new OptMatrix<gMat2D<T> >(*newMat); 00260 //} 00261 00262 template<class MatrixType> 00263 GurlsOption* copyOptMatrix(const GurlsOption* toCopy) 00264 { 00265 const MatrixType & mat = OptMatrix<MatrixType>::dynacast(toCopy)->getValue(); 00266 00267 MatrixType* newMat = new MatrixType(mat); 00268 return new OptMatrix<MatrixType >(*newMat); 00269 } 00270 00271 void GurlsOptionsList::copyOpt(string key, const GurlsOptionsList &from) 00272 { 00273 00274 const GurlsOption* toCopy = from.getOpt(key); 00275 00276 GurlsOption* newOpt = NULL; 00277 00278 switch(toCopy->getType()) 00279 { 00280 case StringOption: 00281 newOpt = new OptString(OptString::dynacast(toCopy)->getValue()); 00282 break; 00283 case NumberOption: 00284 newOpt = new OptNumber(OptNumber::dynacast(toCopy)->getValue()); 00285 break; 00286 case StringListOption: 00287 newOpt = new OptStringList(OptStringList::dynacast(toCopy)->getValue()); 00288 break; 00289 case NumberListOption: 00290 newOpt = new OptNumberList(OptNumberList::dynacast(toCopy)->getValue()); 00291 break; 00292 case FunctionOption: 00293 newOpt = new OptFunction(OptFunction::dynacast(toCopy)->getName()); 00294 break; 00295 case ProcessOption: 00296 newOpt = new OptProcess(*OptProcess::dynacast(toCopy)); 00297 break; 00298 case MatrixOption: 00299 case VectorOption: 00300 { 00301 const OptMatrixBase* base = dynamic_cast<const OptMatrixBase*>(toCopy); 00302 00303 if(base == NULL) 00304 throw gException(Exception_Illegal_Dynamic_Cast); 00305 00306 #ifdef _BGURLS 00307 if(base->hasBigArray()) 00308 { 00309 switch(base->getMatrixType()) 00310 { 00311 case OptMatrixBase::ULONG: 00312 newOpt = copyOptMatrix<BigArray<unsigned long> >(toCopy); 00313 break; 00314 case OptMatrixBase::FLOAT: 00315 newOpt = copyOptMatrix<BigArray<float> >(toCopy); 00316 break; 00317 case OptMatrixBase::DOUBLE: 00318 newOpt = copyOptMatrix<BigArray<double> >(toCopy); 00319 break; 00320 } 00321 } 00322 else 00323 #endif 00324 { 00325 switch(base->getMatrixType()) 00326 { 00327 case OptMatrixBase::ULONG: 00328 newOpt = copyOptMatrix<gMat2D<unsigned long> >(toCopy); 00329 break; 00330 case OptMatrixBase::FLOAT: 00331 newOpt = copyOptMatrix<gMat2D<float> >(toCopy); 00332 break; 00333 case OptMatrixBase::DOUBLE: 00334 newOpt = copyOptMatrix<gMat2D<double> >(toCopy); 00335 break; 00336 } 00337 } 00338 00339 } 00340 break; 00341 case OptListOption: 00342 { 00343 const GurlsOptionsList* toCopy_list = GurlsOptionsList::dynacast(toCopy); 00344 00345 newOpt = new GurlsOptionsList(*toCopy_list); 00346 } 00347 break; 00348 case OptArrayOption: 00349 newOpt = new OptArray(*OptArray::dynacast(toCopy)); 00350 break; 00351 case TaskSequenceOption: 00352 newOpt = new OptTaskSequence(OptTaskSequence::dynacast(toCopy)->getValue()); 00353 break; 00354 case TaskIDOption: 00355 case GenericOption: 00356 break; 00357 } 00358 00359 if(newOpt != NULL) 00360 addOpt(key, newOpt); 00361 } 00362 00366 GURLS_EXPORT std::ostream& operator<<(std::ostream& os, const GurlsOptionsList& opt) 00367 { 00368 std::map<std::string, GurlsOption* >::iterator it; 00369 00370 os << std::endl << "~~~~~~~ GurlsOptionList: " << opt.getName() << std::endl; 00371 00372 for (it = opt.table->begin(); it != opt.table->end(); ++it) 00373 os << "\t[ " << it->first << " ] = " << *(it->second) << endl; 00374 00375 os << "~~~~~~~"; 00376 return os; 00377 } 00378 00379 bool GurlsOptionsList::addOpt(std::string key, GurlsOption* value) 00380 { 00381 std::pair<ValueType::iterator, bool> res = table->insert( pair<std::string,GurlsOption*>(key, value) ); 00382 00383 if(!res.second) 00384 throw gException(Exception_Parameter_Already_Definied + " (" + key + ")"); 00385 00386 return true; 00387 } 00388 00389 bool GurlsOptionsList::addOpt(std::string key, std::wstring value) 00390 { 00391 std::string val = std::string(value.begin(), value.end()); 00392 return addOpt(key, val); 00393 } 00394 00395 bool GurlsOptionsList::addOpt(std::string key, std::string value) 00396 { 00397 OptString* v = new OptString(value); 00398 try 00399 { 00400 return addOpt(key, v); 00401 } 00402 catch (gException & ex) 00403 { 00404 delete v; 00405 throw ex; 00406 } 00407 } 00408 00409 GurlsOption* GurlsOptionsList::getOpt(std::string key) 00410 { 00411 if(key.empty()) 00412 throw gException(Exception_Parameter_Not_Definied_Yet + "( )"); 00413 00414 std::vector<std::string> names; 00415 boost::split(names, key, boost::is_any_of(".")); 00416 00417 GurlsOption* gout = this; 00418 ValueType *tab; 00419 00420 for(std::vector<std::string>::iterator n_it = names.begin(); n_it != names.end(); ++n_it) 00421 { 00422 tab = GurlsOptionsList::dynacast(gout)->table; 00423 00424 std::map<std::string, GurlsOption* >::iterator it = tab->find(*n_it); 00425 00426 if(it == tab->end()) 00427 throw gException(Exception_Parameter_Not_Definied_Yet + "( " + *n_it + " )"); 00428 00429 gout = it->second; 00430 } 00431 00432 return gout; 00433 } 00434 00435 const GurlsOption* GurlsOptionsList::getOpt(std::string key) const 00436 { 00437 if(key.empty()) 00438 throw gException(Exception_Parameter_Not_Definied_Yet + "( )"); 00439 00440 std::vector<std::string> names; 00441 boost::split(names, key, boost::is_any_of(".")); 00442 00443 const GurlsOption* gout = this; 00444 ValueType *tab; 00445 00446 for(std::vector<std::string>::iterator n_it = names.begin(); n_it != names.end(); ++n_it) 00447 { 00448 tab = GurlsOptionsList::dynacast(gout)->table; 00449 00450 std::map<std::string, GurlsOption* >::iterator it = tab->find(*n_it); 00451 00452 if(it == tab->end()) 00453 throw gException(Exception_Parameter_Not_Definied_Yet + "( " + *n_it + " )"); 00454 00455 gout = it->second; 00456 } 00457 00458 return gout; 00459 } 00460 00461 std::string GurlsOptionsList::getOptAsString(std::string key) const 00462 { 00463 return getOptValue<OptString>(key); 00464 } 00465 00466 string GurlsOptionsList::getName() const 00467 { 00468 return this->name; 00469 } 00470 00471 const GurlsOptionsList::ValueType &GurlsOptionsList::getValue() const 00472 { 00473 return *table; 00474 } 00475 00476 double GurlsOptionsList::getOptAsNumber(std::string key) const 00477 { 00478 return getOptValue<OptNumber>(key); 00479 } 00480 00481 void GurlsOptionsList::save(const std::string& fileName) const 00482 { 00483 #ifndef USE_BINARY_ARCHIVES 00484 std::ofstream outstream(fileName.c_str()); 00485 #else 00486 std::ofstream outstream(fileName.c_str(), ios_base::binary); 00487 #endif 00488 00489 if(!outstream.is_open()) 00490 throw gException("Could not open file " + fileName); 00491 00492 oarchive outar(outstream); 00493 outar << *this; 00494 00495 outstream.close(); 00496 } 00497 00498 void GurlsOptionsList::load(const std::string& fileName) 00499 { 00500 #ifndef USE_BINARY_ARCHIVES 00501 std::ifstream instream(fileName.c_str()); 00502 #else 00503 std::ifstream instream(fileName.c_str(), ios_base::binary); 00504 #endif 00505 00506 if(!instream.is_open()) 00507 throw gException("Could not open file " + fileName); 00508 00509 try 00510 { 00511 iarchive inar(instream); 00512 inar >> *this; 00513 } 00514 catch(boost::archive::archive_exception&) 00515 { 00516 instream.close(); 00517 throw gException("Invalid file format for " + fileName); 00518 } 00519 00520 instream.close(); 00521 } 00522 00523 00524 } 00525