pelib
2.0.0
|
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 <sstream> 00022 00023 #include <pelib/AmplInputData.hpp> 00024 #include <pelib/Matrix.hpp> 00025 #include <pelib/CastException.hpp> 00026 00027 #ifndef PELIB_AMPLINPUTMATRIX 00028 #define PELIB_AMPLINPUTMATRIX 00029 00030 namespace pelib 00031 { 00033 template <class Col, class Row, class Value> 00034 class AmplInputMatrix: public AmplInputData 00035 { 00036 typedef std::map<Col, Value> RowType; 00037 typedef std::map<Row, RowType> MatrixType; 00038 00039 public: 00043 AmplInputMatrix(bool strict = true) 00044 { 00045 this->strict = strict; 00046 } 00047 00050 virtual 00051 AmplInputMatrix* 00052 clone() const 00053 { 00054 return new AmplInputMatrix(); 00055 } 00056 00058 virtual 00059 std::string 00060 getDetailedPattern() 00061 { 00062 return "param\\s+([^\\s\\n:]+):\\s*(.*)\\s*:=(.+)"; 00063 } 00064 00066 virtual 00067 std::string 00068 getGlobalPattern() 00069 { 00070 return "param\\s+[^\\s\\n:]+:\\s*.*\\s*:=.+"; 00071 } 00072 00077 virtual 00078 AlgebraData* 00079 parse(std::istream &in) 00080 { 00081 MatrixType values; 00082 00083 std::string str((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>()); 00084 boost::cmatch match; // = AlgebraDataParser::match(getDetailedPattern(), str); 00085 if(!boost::regex_match(str.c_str(), match, boost::regex(getDetailedPattern()))) 00086 { 00087 throw ParseException(std::string("String \"").append(str).append("\" doesn't match regex \"").append(getDetailedPattern()).append("\". ")); 00088 } 00089 std::string indexes = match[2]; 00090 std::string remain = match[3]; 00091 00092 // Extract all indexes 00093 boost::regex isolated_value("\\s*([^\\s]+)\\s*"); 00094 boost::sregex_token_iterator iter = make_regex_token_iterator(indexes, isolated_value, 1, boost::regex_constants::match_default); 00095 boost::sregex_token_iterator end; 00096 00097 // Put them in a vector 00098 std::vector<Col> cols; 00099 for(; iter != end; ++iter) 00100 { 00101 try 00102 { 00103 cols.push_back(AlgebraDataParser::convert<Col>(*iter, strict)); 00104 } catch(NoDecimalFloatException &e) 00105 { 00106 std::ostringstream ss; 00107 ss << e.getValue(); 00108 throw ParseException(std::string("Asked a decimal conversion, but \"").append(ss.str()).append("\" is integer.")); 00109 } 00110 } 00111 int s = cols.size(); 00112 00113 // Parse the rest of the matrix; catch the row index every s reads 00114 iter = make_regex_token_iterator(remain, isolated_value, 1, boost::regex_constants::match_default); 00115 00116 //int progress = 0; 00117 Row row; 00118 Col col; 00119 Value val; 00120 00121 int integer_values = 0, total_values = 0; 00122 while(iter != end) 00123 { 00124 std::map<Col, Value> vector; 00125 00126 try 00127 { 00128 row = AlgebraDataParser::convert<Row>(*iter, strict); 00129 } catch(NoDecimalFloatException &e) 00130 { 00131 std::ostringstream ss; 00132 ss << e.getValue(); 00133 throw ParseException(std::string("Asked a decimal conversion, but \"").append(ss.str()).append("\" is integer.")); 00134 } 00135 00136 iter++; 00137 for(int i = 0; i < s; i++) 00138 { 00139 try 00140 { 00141 val = AlgebraDataParser::convert<Value>(*iter, strict); 00142 } catch(NoDecimalFloatException &e) 00143 { 00144 float float_value = e.getValue(); 00145 std::stringstream ss; 00146 00147 ss << float_value; 00148 ss >> val; 00149 //val = Value(float_value); 00150 integer_values++; 00151 } 00152 00153 col = cols[i]; 00154 vector.insert(std::pair<Col, Value>(col, val)); 00155 00156 iter++; 00157 total_values++; 00158 } 00159 00160 values.insert(std::pair<Row, RowType>(row, vector)); 00161 } 00162 00163 // If all values could have been parsed as integer, then this is obviously an integer vector rather to a float one 00164 if(integer_values == total_values) 00165 { 00166 //throw NoDecimalFloatException(std::string("Matrix only composed of integer-parsable values."), 0); 00167 throw ParseException(std::string("Matrix only composed of integer-parsable values.")); 00168 } 00169 00170 return new Matrix<Col, Row, Value>(match[1], values); 00171 } 00172 00177 virtual 00178 void 00179 dump(std::ostream &o, const AlgebraData *data) const 00180 { 00181 const Matrix<Col, Row, Value> *matrix = dynamic_cast<const Matrix<Col, Row, Value>*>(data); 00182 if(matrix == NULL) throw CastException("parameter \"data\" was not of type \"Matrix<Col, Row, Value>\"."); 00183 MatrixType values = matrix->getValues(); 00184 00185 o << "param " << matrix->getName() << ":" << std::endl; 00186 typename std::map<Row, std::map<Col, Value> >::const_iterator row_iter = values.begin(); 00187 00188 if(row_iter != matrix->getValues().end()) 00189 { 00190 for(typename std::map<Col, Value>::const_iterator col_iter = row_iter->second.begin(); col_iter != row_iter->second.end(); col_iter++) 00191 { 00192 o << col_iter->first << " "; 00193 } 00194 o << ":=" << std::endl; 00195 00196 for(row_iter = values.begin(); row_iter != values.end(); row_iter++) 00197 { 00198 o << row_iter->first << " "; 00199 for(typename std::map<Col, Value>::const_iterator col_iter = row_iter->second.begin(); col_iter != row_iter->second.end(); col_iter++) 00200 { 00201 o << col_iter->second << " "; 00202 } 00203 o << std::endl; 00204 } 00205 } 00206 00207 o << ";" << std::endl; 00208 } 00209 00210 protected: 00212 bool strict; 00213 private: 00214 }; 00215 } 00216 00217 #endif