gecode » serialization
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 00002 /* 00003 * Main authors: 00004 * Guido Tack <tack@gecode.org> 00005 * 00006 * Copyright: 00007 * Guido Tack, 2007 00008 * 00009 * Last modified: 00010 * $Date: 2008-02-14 15:40:16 +0100 (Thu, 14 Feb 2008) $ by $Author: tack $ 00011 * $Revision: 6163 $ 00012 * 00013 * This file is part of Gecode, the generic constraint 00014 * development environment: 00015 * http://www.gecode.org 00016 * 00017 * Permission is hereby granted, free of charge, to any person obtaining 00018 * a copy of this software and associated documentation files (the 00019 * "Software"), to deal in the Software without restriction, including 00020 * without limitation the rights to use, copy, modify, merge, publish, 00021 * distribute, sublicense, and/or sell copies of the Software, and to 00022 * permit persons to whom the Software is furnished to do so, subject to 00023 * the following conditions: 00024 * 00025 * The above copyright notice and this permission notice shall be 00026 * included in all copies or substantial portions of the Software. 00027 * 00028 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00029 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00030 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00031 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 00032 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 00033 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00034 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00035 * 00036 */ 00037 00038 #include "gecode/serialization.hh" 00039 #ifdef GECODE_HAS_INT_VARS 00040 #include "gecode/int.hh" 00041 #endif 00042 #ifdef GECODE_HAS_SET_VARS 00043 #include "gecode/set.hh" 00044 #endif 00045 00046 namespace Gecode { 00047 00048 namespace { 00049 #ifdef GECODE_HAS_INT_VARS 00050 void emitIntVar(std::ostream& os, int varNo, Reflection::VarSpec& vs) { 00051 using namespace std; 00052 os << "var "; 00053 Reflection::Arg* dom = vs.dom(); 00054 if (!dom->isIntArray()) 00055 throw Exception("Serialization", 00056 "Internal error: invalid domain specification for IntVar."); 00057 Reflection::IntArrayArg* a = dom->toIntArray(); 00058 if (a->size() == 2) { 00059 os << (*a)[0] << ".." << (*a)[1]; 00060 } else { 00061 os << "{"; 00062 for (int i=0; i<a->size(); i+=2) { 00063 for (int j=(*a)[i]; j<=(*a)[i+1]; j++) 00064 os << j << (i==a->size()-2 && j==(*a)[i+1] ? "" : ","); 00065 } 00066 os << "}"; 00067 } 00068 if (!vs.name().empty()) { 00069 os << ": " << vs.name() << ";" << endl; 00070 } 00071 else 00072 os << ": _v" << varNo << ";" << endl; 00073 } 00074 void emitBoolVar(std::ostream& os, int varNo, Reflection::VarSpec& vs) { 00075 using namespace std; 00076 os << "var "; 00077 Reflection::Arg* dom = vs.dom(); 00078 if (!dom->isInt()) 00079 throw Exception("Serialization", 00080 "Internal error: invalid domain specification for BoolVar."); 00081 switch (dom->toInt()) { 00082 case 0: os << "false..true"; break; 00083 case 1: os << "false"; break; 00084 case 2: os << "true"; break; 00085 default: 00086 throw Exception("Serialization", 00087 "Internal error: invalid domain specification for BoolVar."); 00088 } 00089 if (!vs.name().empty()) { 00090 os << ": " << vs.name() << ";" << endl; 00091 } 00092 else 00093 os << ": _v" << varNo << ";" << endl; 00094 } 00095 #endif 00096 #ifdef GECODE_HAS_SET_VARS 00097 void emitSetVar(std::ostream& os, int varNo, Reflection::VarSpec& vs) { 00098 using namespace std; 00099 os << "var set of "; 00100 Reflection::Arg* dom = vs.dom(); 00101 if (! (dom->isPair() && 00102 dom->first()->isPair() && dom->second()->isPair() && 00103 dom->first()->first()->isIntArray() && 00104 dom->second()->first()->isIntArray() && 00105 dom->first()->second()->isInt() && 00106 dom->second()->second()->isInt())) 00107 throw Exception("Serialization", 00108 "Internal error: invalid domain specification for SetVar."); 00109 00110 int lbCard = 0; 00111 int ubCard = 0; 00112 00113 // Output upper bound 00114 Reflection::IntArrayArg* a = dom->second()->first()->toIntArray(); 00115 if (a->size() == 2) { 00116 os << (*a)[0] << ".." << (*a)[1]; 00117 ubCard = (*a)[1] - (*a)[0]; 00118 } else { 00119 os << "{"; 00120 for (int i=0; i<a->size(); i+=2) { 00121 for (int j=(*a)[i]; j<(*a)[i+1]; j++) { 00122 os << j << (i==a->size()-2 && j==(*a)[i+1]-1 ? "" : ","); 00123 ubCard += (*a)[i+1] - (*a)[i]; 00124 } 00125 } 00126 os << "}"; 00127 } 00128 if (!vs.name().empty()) { 00129 os << ": " << vs.name() << ";" << endl; 00130 } 00131 else 00132 os << ": _v" << varNo << ";" << endl; 00133 00134 // Output additional constraints if lower bound is given and/or 00135 // cardinality is tighter than bounds 00136 00137 if (dom->first()->first()->toIntArray()->size() != 0) { 00138 os << "constraint subset("; 00139 a = dom->first()->first()->toIntArray(); 00140 if (a->size() == 2) { 00141 os << (*a)[0] << ".." << (*a)[1]; 00142 } else { 00143 os << "{"; 00144 for (int i=0; i<a->size(); i+=2) { 00145 for (int j=(*a)[i]; j<(*a)[i+1]; j++) 00146 os << j << (i==a->size()-2 && j==(*a)[i+1]-1 ? "" : ","); 00147 } 00148 os << "}"; 00149 } 00150 if (!vs.name().empty()) { 00151 os << "," << vs.name() << ");" << endl; 00152 } 00153 else 00154 os << ", _v" << varNo << ");" << endl; 00155 } 00156 00157 if (lbCard != dom->first()->second()->toInt() || 00158 ubCard != dom->second()->second()->toInt()) { 00159 os << "constraint cardinality("; 00160 if (!vs.name().empty()) 00161 os << vs.name() << ", "; 00162 else 00163 os << "_v" << varNo; 00164 os << ", " << lbCard << ", " << ubCard << ");" << endl; 00165 00166 } 00167 00168 } 00169 #endif 00170 00171 void emitVar(std::ostream& os, int v, Reflection::VarMap& vm) { 00172 using namespace std; 00173 Reflection::VarSpec& vs = vm.spec(v); 00174 if (vs.name().empty()) 00175 os << "_v" << v; 00176 else 00177 os << vs.name(); 00178 } 00179 00180 void emitVarArray(std::ostream& os, Reflection::ArrayArg* a, 00181 Reflection::VarMap& vm) { 00182 using namespace std; 00183 for (int i=0; i<a->size(); i++) 00184 emitVar(os, (*a)[i]->toVar(), vm); 00185 } 00186 00187 void emitArray(std::ostream& os, Reflection::ArrayArg* a, 00188 Reflection::VarMap& vm) { 00189 using namespace std; 00190 if ((*a)[0]->isInt()) { 00191 os << "["; 00192 for (int i=0; i<a->size(); i++) { 00193 os << (*a)[i]->toInt(); 00194 if (i<a->size()-1) 00195 os << ", "; 00196 } 00197 os << "]"; 00198 return; 00199 } 00200 00201 if ((*a)[0]->isVar()) { 00202 os << "["; 00203 for (int i=0; i<a->size(); i++) { 00204 emitVar(os, (*a)[i]->toVar(), vm); 00205 if (i<a->size()-1) 00206 os << ","; 00207 } 00208 os << "]"; 00209 return; 00210 } 00211 00212 if ((*a)[0]->isPair()) { 00213 Reflection::ArrayArg* aa = Reflection::Arg::newArray(a->size()); 00214 Reflection::ArrayArg* ab = Reflection::Arg::newArray(a->size()); 00215 for (int i=0; i<a->size(); i++) { 00216 (*aa)[i] = (*a)[i]->first(); 00217 (*ab)[i] = (*a)[i]->second(); 00218 } 00219 emitArray(os, aa, vm); 00220 os << ", "; 00221 emitArray(os, ab, vm); 00222 // Clear array, so that only the array is deleted 00223 for (int i=0; i<a->size(); i++) { 00224 (*aa)[i] = NULL; 00225 (*ab)[i] = NULL; 00226 } 00227 delete aa; 00228 delete ab; 00229 return; 00230 } 00231 00232 throw Exception("Serialization", "Specification not understood"); 00233 } 00234 00235 void emitArg(std::ostream& os, Reflection::Arg* arg, 00236 Reflection::VarMap& vm) { 00237 using namespace std; 00238 if (arg->isInt()) { 00239 os << arg->toInt(); 00240 return; 00241 } 00242 if (arg->isString()) { 00243 os << "\"" << arg->toString() << "\""; 00244 return; 00245 } 00246 if (arg->isVar()) { 00247 Reflection::VarSpec& s = vm.spec(arg->toVar()); 00248 if (s.name().empty()) 00249 os << "_v" << arg->toVar(); 00250 else 00251 os << s.name(); 00252 return; 00253 } 00254 if (arg->isIntArray()) { 00255 Reflection::IntArrayArg* a = arg->toIntArray(); 00256 os << "["; 00257 for (int i=0; i<a->size(); i++) { 00258 os << (*a)[i]; 00259 if (i<a->size()-1) 00260 os << ", "; 00261 } 00262 os << "]"; 00263 return; 00264 } 00265 if (arg->isArray()) { 00266 Reflection::ArrayArg* a = arg->toArray(); 00267 if (a->size() == 0) { 00268 os << "[]"; 00269 return; 00270 } 00271 emitArray(os, a, vm); 00272 return; 00273 } 00274 if (arg->isSharedReference()) { 00275 os << "_array" << arg->toSharedReference(); 00276 return; 00277 } 00278 assert(!arg->isSharedObject()); 00279 throw Exception("Serialization", "Specification not understood"); 00280 } 00281 00282 void emitSharedObject(std::ostream& os, int soCount, 00283 Reflection::VarMap& vm, 00284 Reflection::Arg* arg0) { 00285 using namespace std; 00286 Reflection::Arg* arg = arg0->toSharedObject(); 00287 if (arg->isIntArray()) { 00288 Reflection::IntArrayArg* a = arg->toIntArray(); 00289 os << "array[0.."<<a->size()-1<<"] of int: _array" << soCount << " = "; 00290 os << "["; 00291 for (int i=0; i<a->size(); i++) { 00292 os << (*a)[i]; 00293 if (i<a->size()-1) 00294 os << ", "; 00295 } 00296 os << "];" << std::endl; 00297 return; 00298 } 00299 if (arg->isArray()) { 00300 Reflection::ArrayArg* a = arg->toArray(); 00301 os << "array[0.."<<a->size()-1<<"] of int: _array" << soCount << " = "; 00302 if (a->size() == 0) { 00303 os << "[];" << std::endl; 00304 return; 00305 } 00306 emitArray(os, a, vm); 00307 os << ";" << std::endl; 00308 return; 00309 } 00310 return; 00311 } 00312 00313 void emitVarMap(std::ostream& os, int& varCount, 00314 Reflection::VarMapIter& vmi) { 00315 for (; vmi(); ++vmi, ++varCount) { 00316 Reflection::VarSpec& vs = vmi.spec(); 00317 if (false) { } 00318 #ifdef GECODE_HAS_INT_VARS 00319 else if (vs.vti() == Int::IntVarImp::vti) 00320 emitIntVar(os, varCount, vs); 00321 else if (vs.vti() == Int::BoolVarImp::vti) 00322 emitBoolVar(os, varCount, vs); 00323 #endif 00324 #ifdef GECODE_HAS_SET_VARS 00325 else if (vs.vti() == Set::SetVarImp::vti) 00326 emitSetVar(os, varCount, vs); 00327 #endif 00328 } 00329 } 00330 } 00331 00332 00333 void emitFlatzinc(Space* home, std::ostream& os) { 00334 using namespace std; 00335 Reflection::VarMap vm; 00336 home->getVars(vm, false); 00337 Reflection::VarMapIter vmi(vm); 00338 int varCount = 0; 00339 int soCount = 0; 00340 emitVarMap(os,varCount,vmi); 00341 for (Reflection::ActorSpecIter si(home, vm); si(); ++si) { 00342 Reflection::ActorSpec s = si.actor(); 00343 00344 emitVarMap(os,varCount,vmi); 00345 00346 int soBase = soCount; 00347 for (int i=0; i<s.noOfArgs(); i++) { 00348 if (s[i] && s[i]->isSharedObject()) 00349 emitSharedObject(os, soBase++, vm, s[i]); 00350 } 00351 00352 os << "constraint " << s.ati() << "("; 00353 00354 soBase = soCount; 00355 for (int i=0; i<s.noOfArgs(); i++) { 00356 if (s[i] == NULL) 00357 os << "[]"; 00358 else if (s[i]->isSharedObject()) 00359 os << "_array" << soBase++; 00360 else 00361 emitArg(os, s[i], vm); 00362 if (i<s.noOfArgs()-1) 00363 os << ", "; 00364 } 00365 os << ");" << endl; 00366 soCount = soBase; 00367 } 00368 } 00369 00370 } 00371 00372 // STATISTICS: serialization-any