GURLS++  2.0.00
C++ Implementation of GURLS Matlab Toolbox
optlist.cpp
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends