Generated on Mon Aug 25 11:35:40 2008 for Gecode by doxygen 1.5.6

flatzinc.cc

Go to the documentation of this file.
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