pelib  2.0.0
include/pelib/AmplOutputSet.hpp
Go to the documentation of this file.
00001 /*
00002  Copyright 2015 Nicolas Melot
00003 
00004  This file is part of Pelib.
00005 
00006  Pelib is free software: you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation, either version 3 of the License, or
00009  (at your option) any later version.
00010 
00011  Pelib is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with Pelib. If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 
00021 #include <set>
00022 
00023 #include <pelib/AmplOutputData.hpp>
00024 #include <pelib/Set.hpp>
00025 #include <pelib/Scalar.hpp>
00026 #include <pelib/CastException.hpp>
00027 
00028 #ifndef PELIB_AMPLOUTPUTSET
00029 #define PELIB_AMPLOUTPUTSET
00030 
00031 namespace pelib
00032 {
00033         /*** AMPL Output format parser and output class for pelib::Set class instances ***/
00034         template <class Value, class Key = size_t>
00035         class AmplOutputSet: public AmplOutputData
00036         {
00037                 /*** Internal format of data collection handled ***/
00038                 typedef std::set<Value, std::less<Value>, std::allocator<Value> > SetType;
00039                 
00040                 public:
00044                         AmplOutputSet(bool strict = true)
00045                         {
00046                                 this->strict = strict;
00047                         }
00048                         
00050                         virtual
00051                         AmplOutputSet*
00052                         clone() const
00053                         {
00054                                 return new AmplOutputSet();
00055                         }
00056 
00058                         virtual
00059                         std::string
00060                         getDetailedPattern()
00061                         {
00062                                 return "set\\s*([^\\s\\n\\[\\]]+)\\s*(?:\\[([^\\s\\n]+)\\])?\\s*:=(.+)";
00063                         }
00064 
00066                         virtual
00067                         std::string
00068                         getGlobalPattern()
00069                         {
00070                                 return "set\\s*[^\\s\\n\\[\\]]+\\s*(?:\\[[^\\s\\n]+\\])?\\s*:=.+";
00071                         }
00072 
00076                         virtual
00077                         AlgebraData*
00078                         parse(std::istream &in)
00079                         {
00080                                 SetType values;
00081                                 
00082                                 std::string str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
00083                                 boost::cmatch match; // = AlgebraDataParser::match(getDetailedPattern(), str);
00084                                 if(!boost::regex_match(str.c_str(), match, boost::regex(getDetailedPattern())))
00085                                 {
00086                                         throw ParseException(std::string("String \"").append(str).append("\" doesn't match regex \"").append(getDetailedPattern()).append("\". "));
00087                                 }
00088                                 
00089                                 boost::regex param_set("\\s*([^\\s]+)");
00090                                 std::string keystr = match[2];
00091                                 std::string remain = match[3];
00092                                 const int subs[] = {1};
00093                                 boost::sregex_token_iterator iter = make_regex_token_iterator(remain, param_set, subs, boost::regex_constants::match_default);
00094                                 boost::sregex_token_iterator end;
00095 
00096                                 int integer_values = 0, total_values = 0;
00097                                 for(; iter != end; ++iter )
00098                                 {
00099                                         Value value;
00100                                         
00101                                         try
00102                                         {
00103                                                 value = AlgebraDataParser::convert<Value>(*iter, strict);
00104                                         }
00105                                         catch(NoDecimalFloatException &e)
00106                                         {
00107                                                 std::stringstream ss;
00108                                                 ss << e.getValue();
00109                                                 ss >> value;
00110                                                 integer_values++;
00111                                         }
00112 
00113                                         values.insert(value);
00114                                         total_values++;
00115                                 }
00116 
00117                                 // If all values could have been parsed as integer, then this is obviously an integer vector rather to a float one
00118                                 if(integer_values == total_values)
00119                                 {
00120                                         //throw NoDecimalFloatException(std::string("Set only composed of integer-parsable values."), 0);
00121                                         throw ParseException(std::string("Set only composed of integer-parsable values."));
00122                                 }
00123 
00124                                 if(keystr.compare(std::string()) == 0)
00125                                 {
00126                                         return new Set<Value>(match[1], values);
00127                                 }
00128                                 else
00129                                 {
00130                                         Key key;
00131 
00132                                         try
00133                                         {
00134                                                 key = AlgebraDataParser::convert<Key>(keystr, strict);
00135                                         }
00136                                         catch(NoDecimalFloatException &e)
00137                                         {
00138                                                 std::stringstream ss;
00139                                                 ss << e.getValue();
00140                                                 ss >> key;
00141                                         }
00142 
00143                                         return new Set<Value, Key>(match[1], key, values);
00144                                 }
00145                         }
00146 
00151                         virtual
00152                         void
00153                         dump(std::ostream &o, const AlgebraData *data) const
00154                         {                               
00155                                 const Set<Value, Key> *set = dynamic_cast<const Set<Value>*>(data);
00156                                 if(set == NULL) throw CastException("parameter \"data\" was not of type \"Set<Value>\".");                              
00157                                 
00158                                 for(typename Set<Value, Key>::SetOfSetsType::const_iterator i = set->getSubsets().begin(); i != set->getSubsets().end(); i++)
00159                                 {
00160                                         if(set->isOneSet())
00161                                         {
00162                                                 o << "set " << set->getName() << " :=";
00163                                         }
00164                                         else
00165                                         {
00166                                                 o << "set " << set->getName() << "[" << i->first << "] :=";
00167                                         }
00168                                         
00169                                         SetType values = i->second;
00170                                         for(typename std::set<Value>::const_iterator iter = values.begin(); iter != values.end(); iter++)
00171                                         {
00172                                                 o << " " << *iter;
00173                                         }
00174 
00175                                         o << ";" << std::endl;
00176                                 }
00177                         }
00178 
00179                 protected:
00181                         bool strict;
00182                 private:        
00183         };
00184 }
00185 
00186 #endif