1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 /* 3 * Main authors: 4 * Guido Tack <tack@gecode.org> 5 * 6 * Contributing authors: 7 * Gabriel Hjort Blindell <gabriel.hjort.blindell@gmail.com> 8 * 9 * Copyright: 10 * Guido Tack, 2007-2012 11 * Gabriel Hjort Blindell, 2012 12 * 13 * This file is part of Gecode, the generic constraint 14 * development environment: 15 * http://www.gecode.org 16 * 17 * Permission is hereby granted, free of charge, to any person obtaining 18 * a copy of this software and associated documentation files (the 19 * "Software"), to deal in the Software without restriction, including 20 * without limitation the rights to use, copy, modify, merge, publish, 21 * distribute, sublicense, and/or sell copies of the Software, and to 22 * permit persons to whom the Software is furnished to do so, subject to 23 * the following conditions: 24 * 25 * The above copyright notice and this permission notice shall be 26 * included in all copies or substantial portions of the Software. 27 * 28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35 * 36 */ 37 38 #ifndef GECODE_FLATZINC_HH 39 #define GECODE_FLATZINC_HH 40 41 #include <iostream> 42 43 #include <gecode/kernel.hh> 44 #include <gecode/int.hh> 45 #ifdef GECODE_HAS_SET_VARS 46 #include <gecode/set.hh> 47 #endif 48 #ifdef GECODE_HAS_FLOAT_VARS 49 #include <gecode/float.hh> 50 #endif 51 #include <map> 52 53 /* 54 * Support for DLLs under Windows 55 * 56 */ 57 58 #if !defined(GECODE_STATIC_LIBS) && \ 59 (defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)) 60 61 #ifdef GECODE_BUILD_FLATZINC 62 #define GECODE_FLATZINC_EXPORT __declspec( dllexport ) 63 #else 64 #define GECODE_FLATZINC_EXPORT __declspec( dllimport ) 65 #endif 66 67 #else 68 69 #ifdef GECODE_GCC_HAS_CLASS_VISIBILITY 70 71 #define GECODE_FLATZINC_EXPORT __attribute__ ((visibility("default"))) 72 73 #else 74 75 #define GECODE_FLATZINC_EXPORT 76 77 #endif 78 #endif 79 80 // Configure auto-linking 81 #ifndef GECODE_BUILD_FLATZINC 82 #define GECODE_LIBRARY_NAME "FlatZinc" 83 #include <gecode/support/auto-link.hpp> 84 #endif 85 86 #include <gecode/driver.hh> 87 88 #include <gecode/flatzinc/conexpr.hh> 89 #include <gecode/flatzinc/ast.hh> 90 #include <gecode/flatzinc/varspec.hh> 91 92 /** 93 * \namespace Gecode::FlatZinc 94 * \brief Interpreter for the %FlatZinc language 95 * 96 * The Gecode::FlatZinc namespace contains all functionality required 97 * to parse and solve constraint models written in the %FlatZinc language. 98 * 99 */ 100 101 namespace Gecode { namespace FlatZinc { 102 103 /** 104 * \brief Output support class for %FlatZinc interpreter 105 * 106 */ 107 class GECODE_FLATZINC_EXPORT Printer { 108 private: 109 /// Names of integer variables 110 std::vector<std::string> iv_names; 111 /// Names of Boolean variables 112 std::vector<std::string> bv_names; 113 #ifdef GECODE_HAS_FLOAT_VARS 114 /// Names of float variables 115 std::vector<std::string> fv_names; 116 #endif 117 #ifdef GECODE_HAS_SET_VARS 118 /// Names of set variables 119 std::vector<std::string> sv_names; 120 #endif 121 AST::Array* _output; 122 void printElem(std::ostream& out, 123 AST::Node* ai, 124 const Gecode::IntVarArray& iv, 125 const Gecode::BoolVarArray& bv 126 #ifdef GECODE_HAS_SET_VARS 127 , 128 const Gecode::SetVarArray& sv 129 #endif 130 #ifdef GECODE_HAS_FLOAT_VARS 131 , 132 const Gecode::FloatVarArray& fv 133 #endif 134 ) const; 135 void printElemDiff(std::ostream& out, 136 AST::Node* ai, 137 const Gecode::IntVarArray& iv1, 138 const Gecode::IntVarArray& iv2, 139 const Gecode::BoolVarArray& bv1, 140 const Gecode::BoolVarArray& bv2 141 #ifdef GECODE_HAS_SET_VARS 142 , 143 const Gecode::SetVarArray& sv1, 144 const Gecode::SetVarArray& sv2 145 #endif 146 #ifdef GECODE_HAS_FLOAT_VARS 147 , 148 const Gecode::FloatVarArray& fv1, 149 const Gecode::FloatVarArray& fv2 150 #endif 151 ) const; 152 public: Printer(void)153 Printer(void) : _output(nullptr) {} 154 void init(AST::Array* output); 155 156 void print(std::ostream& out, 157 const Gecode::IntVarArray& iv, 158 const Gecode::BoolVarArray& bv 159 #ifdef GECODE_HAS_SET_VARS 160 , 161 const Gecode::SetVarArray& sv 162 #endif 163 #ifdef GECODE_HAS_FLOAT_VARS 164 , 165 const Gecode::FloatVarArray& fv 166 #endif 167 ) const; 168 169 void printDiff(std::ostream& out, 170 const Gecode::IntVarArray& iv1, const Gecode::IntVarArray& iv2, 171 const Gecode::BoolVarArray& bv1, const Gecode::BoolVarArray& bv2 172 #ifdef GECODE_HAS_SET_VARS 173 , 174 const Gecode::SetVarArray& sv1, const Gecode::SetVarArray& sv2 175 #endif 176 #ifdef GECODE_HAS_FLOAT_VARS 177 , 178 const Gecode::FloatVarArray& fv1, 179 const Gecode::FloatVarArray& fv2 180 #endif 181 ) const; 182 183 184 ~Printer(void); 185 186 void addIntVarName(const std::string& n); intVarName(int i) const187 const std::string& intVarName(int i) const { return iv_names[i]; } 188 void addBoolVarName(const std::string& n); boolVarName(int i) const189 const std::string& boolVarName(int i) const { return bv_names[i]; } 190 #ifdef GECODE_HAS_FLOAT_VARS 191 void addFloatVarName(const std::string& n); floatVarName(int i) const192 const std::string& floatVarName(int i) const { return fv_names[i]; } 193 #endif 194 #ifdef GECODE_HAS_SET_VARS 195 void addSetVarName(const std::string& n); setVarName(int i) const196 const std::string& setVarName(int i) const { return sv_names[i]; } 197 #endif 198 199 void shrinkElement(AST::Node* node, 200 std::map<int,int>& iv, std::map<int,int>& bv, 201 std::map<int,int>& sv, std::map<int,int>& fv); 202 203 void shrinkArrays(Space& home, 204 int& optVar, bool optVarIsInt, 205 Gecode::IntVarArray& iv, 206 Gecode::BoolVarArray& bv 207 #ifdef GECODE_HAS_SET_VARS 208 , 209 Gecode::SetVarArray& sv 210 #endif 211 #ifdef GECODE_HAS_FLOAT_VARS 212 , 213 Gecode::FloatVarArray& fv 214 #endif 215 ); 216 217 private: 218 Printer(const Printer&); 219 Printer& operator=(const Printer&); 220 }; 221 222 /** 223 * \brief %Options for running %FlatZinc models 224 * 225 */ 226 class FlatZincOptions : public Gecode::BaseOptions { 227 protected: 228 /// \name Search options 229 //@{ 230 Gecode::Driver::IntOption _solutions; ///< How many solutions 231 Gecode::Driver::BoolOption _allSolutions; ///< Return all solutions 232 Gecode::Driver::DoubleOption _threads; ///< How many threads to use 233 Gecode::Driver::BoolOption _free; ///< Use free search 234 Gecode::Driver::DoubleOption _decay; ///< Decay option 235 Gecode::Driver::UnsignedIntOption _c_d; ///< Copy recomputation distance 236 Gecode::Driver::UnsignedIntOption _a_d; ///< Adaptive recomputation distance 237 Gecode::Driver::UnsignedLongLongIntOption _node; ///< Cutoff for number of nodes 238 Gecode::Driver::UnsignedLongLongIntOption _fail; ///< Cutoff for number of failures 239 Gecode::Driver::DoubleOption _time; ///< Cutoff for time 240 Gecode::Driver::DoubleOption _time_limit; ///< Cutoff for time (for compatibility with flatzinc command line) 241 Gecode::Driver::IntOption _seed; ///< Random seed 242 Gecode::Driver::StringOption _restart; ///< Restart method option 243 Gecode::Driver::DoubleOption _r_base; ///< Restart base 244 Gecode::Driver::UnsignedIntOption _r_scale; ///< Restart scale factor 245 Gecode::Driver::BoolOption _nogoods; ///< Whether to use no-goods 246 Gecode::Driver::UnsignedIntOption _nogoods_limit; ///< Depth limit for extracting no-goods 247 Gecode::Driver::BoolOption _interrupt; ///< Whether to catch SIGINT 248 Gecode::Driver::DoubleOption _step; ///< Step option 249 //@} 250 251 /// \name Execution options 252 //@{ 253 Gecode::Driver::StringOption _mode; ///< Script mode to run 254 Gecode::Driver::BoolOption _stat; ///< Emit statistics 255 Gecode::Driver::StringValueOption _output; ///< Output file 256 257 #ifdef GECODE_HAS_CPPROFILER 258 Gecode::Driver::ProfilerOption _profiler; ///< Use this execution id for the CP-profiler 259 #endif 260 261 //@} 262 public: 263 /// Constructor FlatZincOptions(const char * s)264 FlatZincOptions(const char* s) 265 : Gecode::BaseOptions(s), 266 _solutions("n","number of solutions (0 = all, -1 = one/best)",-1), 267 _allSolutions("a", "return all solutions (equal to -n 0)"), 268 _threads("p","number of threads (0 = #processing units)", 269 Gecode::Search::Config::threads), 270 _free("f", "free search, no need to follow search-specification"), 271 _decay("decay","decay factor",0.99), 272 _c_d("c-d","recomputation commit distance",Gecode::Search::Config::c_d), 273 _a_d("a-d","recomputation adaption distance",Gecode::Search::Config::a_d), 274 _node("node","node cutoff (0 = none, solution mode)"), 275 _fail("fail","failure cutoff (0 = none, solution mode)"), 276 _time("time","time (in ms) cutoff (0 = none, solution mode)"), 277 _time_limit("t","time (in ms) cutoff (0 = none, solution mode)"), 278 _seed("r","random seed",0), 279 _restart("restart","restart sequence type",RM_NONE), 280 _r_base("restart-base","base for geometric restart sequence",1.5), 281 _r_scale("restart-scale","scale factor for restart sequence",250), 282 _nogoods("nogoods","whether to use no-goods from restarts",false), 283 _nogoods_limit("nogoods-limit","depth limit for no-good extraction", 284 Search::Config::nogoods_limit), 285 _interrupt("interrupt","whether to catch Ctrl-C (true) or not (false)", 286 true), 287 _step("step","step distance for float optimization",0.0), 288 _mode("mode","how to execute script",Gecode::SM_SOLUTION), 289 _stat("s","emit statistics"), 290 _output("o","file to send output to") 291 292 #ifdef GECODE_HAS_CPPROFILER 293 , 294 _profiler("cp-profiler", "use this execution id and port (comma separated) with CP-profiler") 295 #endif 296 { 297 _mode.add(Gecode::SM_SOLUTION, "solution"); 298 _mode.add(Gecode::SM_STAT, "stat"); 299 _mode.add(Gecode::SM_GIST, "gist"); 300 _restart.add(RM_NONE,"none"); 301 _restart.add(RM_CONSTANT,"constant"); 302 _restart.add(RM_LINEAR,"linear"); 303 _restart.add(RM_LUBY,"luby"); 304 _restart.add(RM_GEOMETRIC,"geometric"); 305 306 add(_solutions); add(_threads); add(_c_d); add(_a_d); 307 add(_allSolutions); 308 add(_free); 309 add(_decay); 310 add(_node); add(_fail); add(_time); add(_time_limit); add(_interrupt); 311 add(_seed); 312 add(_step); 313 add(_restart); add(_r_base); add(_r_scale); 314 add(_nogoods); add(_nogoods_limit); 315 add(_mode); add(_stat); 316 add(_output); 317 #ifdef GECODE_HAS_CPPROFILER 318 add(_profiler); 319 #endif 320 } 321 parse(int & argc,char * argv[])322 void parse(int& argc, char* argv[]) { 323 Gecode::BaseOptions::parse(argc,argv); 324 if (_allSolutions.value() && _solutions.value()==-1) { 325 _solutions.value(0); 326 } 327 if (_time_limit.value()) { 328 _time.value(_time_limit.value()); 329 } 330 if (_stat.value()) 331 _mode.value(Gecode::SM_STAT); 332 } 333 help(void)334 virtual void help(void) { 335 std::cerr << "Gecode FlatZinc interpreter" << std::endl 336 << " - Supported FlatZinc version: " << GECODE_FLATZINC_VERSION 337 << std::endl << std::endl; 338 Gecode::BaseOptions::help(); 339 } 340 solutions(void) const341 int solutions(void) const { return _solutions.value(); } allSolutions(void) const342 bool allSolutions(void) const { return _allSolutions.value(); } threads(void) const343 double threads(void) const { return _threads.value(); } free(void) const344 bool free(void) const { return _free.value(); } c_d(void) const345 unsigned int c_d(void) const { return _c_d.value(); } a_d(void) const346 unsigned int a_d(void) const { return _a_d.value(); } node(void) const347 unsigned long long int node(void) const { return _node.value(); } fail(void) const348 unsigned long long int fail(void) const { return _fail.value(); } time(void) const349 double time(void) const { return _time.value(); } seed(void) const350 int seed(void) const { return _seed.value(); } step(void) const351 double step(void) const { return _step.value(); } output(void) const352 const char* output(void) const { return _output.value(); } 353 mode(void) const354 Gecode::ScriptMode mode(void) const { 355 return static_cast<Gecode::ScriptMode>(_mode.value()); 356 } 357 decay(void) const358 double decay(void) const { return _decay.value(); } restart(void) const359 RestartMode restart(void) const { 360 return static_cast<RestartMode>(_restart.value()); 361 } restart(RestartMode rm)362 void restart(RestartMode rm) { 363 _restart.value(rm); 364 } restart_base(void) const365 double restart_base(void) const { return _r_base.value(); } restart_base(double d)366 void restart_base(double d) { _r_base.value(d); } restart_scale(void) const367 unsigned int restart_scale(void) const { return _r_scale.value(); } restart_scale(int i)368 void restart_scale(int i) { _r_scale.value(i); } nogoods(void) const369 bool nogoods(void) const { return _nogoods.value(); } nogoods_limit(void) const370 unsigned int nogoods_limit(void) const { return _nogoods_limit.value(); } interrupt(void) const371 bool interrupt(void) const { return _interrupt.value(); } 372 373 #ifdef GECODE_HAS_CPPROFILER 374 profiler_id(void) const375 int profiler_id(void) const { return _profiler.execution_id(); } profiler_port(void) const376 unsigned int profiler_port(void) const { return _profiler.port(); } profiler_info(void) const377 bool profiler_info(void) const { return true; } 378 379 #endif 380 allSolutions(bool b)381 void allSolutions(bool b) { _allSolutions.value(b); } 382 }; 383 384 class BranchInformation : public SharedHandle { 385 public: 386 /// Constructor 387 BranchInformation(void); 388 /// Copy constructor 389 BranchInformation(const BranchInformation& bi); 390 /// Initialise for use 391 void init(void); 392 /// Add new brancher information 393 void add(BrancherGroup bg, 394 const std::string& rel0, 395 const std::string& rel1, 396 const std::vector<std::string>& n); 397 /// Output branch information 398 void print(const Brancher& b, 399 unsigned int a, int i, int n, std::ostream& o) const; 400 #ifdef GECODE_HAS_FLOAT_VARS 401 /// Output branch information 402 void print(const Brancher& b, 403 unsigned int a, int i, const FloatNumBranch& nl, 404 std::ostream& o) const; 405 #endif 406 }; 407 408 /// Uninitialized default random number generator 409 GECODE_FLATZINC_EXPORT 410 extern Rnd defrnd; 411 412 class FlatZincSpaceInitData; 413 414 /** 415 * \brief A space that can be initialized with a %FlatZinc model 416 * 417 */ 418 class GECODE_FLATZINC_EXPORT FlatZincSpace : public Space { 419 public: 420 enum Meth { 421 SAT, //< Solve as satisfaction problem 422 MIN, //< Solve as minimization problem 423 MAX //< Solve as maximization problem 424 }; 425 protected: 426 /// Initialisation data (only used for posting constraints) 427 FlatZincSpaceInitData* _initData; 428 /// Number of integer variables 429 int intVarCount; 430 /// Number of Boolean variables 431 int boolVarCount; 432 /// Number of float variables 433 int floatVarCount; 434 /// Number of set variables 435 int setVarCount; 436 437 /// Index of the variable to optimize 438 int _optVar; 439 /// Whether variable to optimize is integer (or float) 440 bool _optVarIsInt; 441 442 /// Whether to solve as satisfaction or optimization problem 443 Meth _method; 444 445 /// Percentage of variables to keep in LNS (or 0 for no LNS) 446 unsigned int _lns; 447 448 /// Initial solution to start the LNS (or nullptr for no LNS) 449 IntSharedArray _lnsInitialSolution; 450 451 /// Random number generator 452 Rnd _random; 453 454 /// Annotations on the solve item 455 AST::Array* _solveAnnotations; 456 457 /// Copy constructor 458 FlatZincSpace(FlatZincSpace&); 459 private: 460 /// Run the search engine 461 template<template<class> class Engine> 462 void 463 runEngine(std::ostream& out, const Printer& p, 464 const FlatZincOptions& opt, Gecode::Support::Timer& t_total); 465 /// Run the meta search engine 466 template<template<class> class Engine, 467 template<class, template<class> class> class Meta> 468 void 469 runMeta(std::ostream& out, const Printer& p, 470 const FlatZincOptions& opt, Gecode::Support::Timer& t_total); 471 void 472 branchWithPlugin(AST::Node* ann); 473 public: 474 /// The integer variables 475 Gecode::IntVarArray iv; 476 /// The introduced integer variables 477 Gecode::IntVarArray iv_aux; 478 479 /// The integer variables used in LNS 480 Gecode::IntVarArray iv_lns; 481 482 /// Indicates whether an integer variable is introduced by mzn2fzn 483 std::vector<bool> iv_introduced; 484 /// Indicates whether an integer variable aliases a Boolean variable 485 int* iv_boolalias; 486 /// The Boolean variables 487 Gecode::BoolVarArray bv; 488 /// The introduced Boolean variables 489 Gecode::BoolVarArray bv_aux; 490 /// Indicates whether a Boolean variable is introduced by mzn2fzn 491 std::vector<bool> bv_introduced; 492 #ifdef GECODE_HAS_SET_VARS 493 /// The set variables 494 Gecode::SetVarArray sv; 495 /// The introduced set variables 496 Gecode::SetVarArray sv_aux; 497 /// Indicates whether a set variable is introduced by mzn2fzn 498 std::vector<bool> sv_introduced; 499 #endif 500 #ifdef GECODE_HAS_FLOAT_VARS 501 /// The float variables 502 Gecode::FloatVarArray fv; 503 /// The introduced float variables 504 Gecode::FloatVarArray fv_aux; 505 /// Indicates whether a float variable is introduced by mzn2fzn 506 std::vector<bool> fv_introduced; 507 /// Step by which a next solution has to have lower cost 508 Gecode::FloatNum step; 509 #endif 510 /// Whether the introduced variables still need to be copied 511 bool needAuxVars; 512 /// Construct empty space 513 FlatZincSpace(Rnd& random = defrnd); 514 515 /// Destructor 516 ~FlatZincSpace(void); 517 518 /// Initialize space with given number of variables 519 void init(int intVars, int boolVars, int setVars, int floatVars); 520 521 /// Create new integer variable from specification 522 void newIntVar(IntVarSpec* vs); 523 /// Link integer variable \a iv to Boolean variable \a bv 524 void aliasBool2Int(int iv, int bv); 525 /// Return linked Boolean variable for integer variable \a iv 526 int aliasBool2Int(int iv); 527 /// Create new Boolean variable from specification 528 void newBoolVar(BoolVarSpec* vs); 529 /// Create new set variable from specification 530 void newSetVar(SetVarSpec* vs); 531 /// Create new float variable from specification 532 void newFloatVar(FloatVarSpec* vs); 533 534 /// Post a constraint specified by \a ce 535 void postConstraints(std::vector<ConExpr*>& ces); 536 537 /// Post the solve item 538 void solve(AST::Array* annotation); 539 /// Post that integer variable \a var should be minimized 540 void minimize(int var, bool isInt, AST::Array* annotation); 541 /// Post that integer variable \a var should be maximized 542 void maximize(int var, bool isInt, AST::Array* annotation); 543 544 /// Run the search 545 void run(std::ostream& out, const Printer& p, 546 const FlatZincOptions& opt, Gecode::Support::Timer& t_total); 547 548 /// Produce output on \a out using \a p 549 void print(std::ostream& out, const Printer& p) const; 550 #ifdef GECODE_HAS_CPPROFILER 551 /// Get string representing the domains of variables (for cpprofiler) 552 std::string getDomains(const Printer& p) const; 553 #endif 554 /// Compare this space with space \a s and print the differences on 555 /// \a out 556 void compare(const Space& s, std::ostream& out) const; 557 /// Compare this space with space \a s and print the differences on 558 /// \a out using \a p 559 void compare(const FlatZincSpace& s, std::ostream& out, 560 const Printer& p) const; 561 562 /** 563 * \brief Remove all variables not needed for output 564 * 565 * After calling this function, no new constraints can be posted through 566 * FlatZinc variable references, and the createBranchers method must 567 * not be called again. 568 * 569 */ 570 void shrinkArrays(Printer& p); 571 572 /// Return whether to solve a satisfaction or optimization problem 573 Meth method(void) const; 574 575 /// Return index of variable used for optimization 576 int optVar(void) const; 577 /// Return whether variable used for optimization is integer (or float) 578 bool optVarIsInt(void) const; 579 580 /** 581 * \brief Create branchers corresponding to the solve item annotations 582 * 583 * If \a ignoreUnknown is true, unknown solve item annotations will be 584 * ignored, otherwise a warning is written to \a err. 585 * 586 * The seed for random branchers is given by the \a seed parameter. 587 * 588 */ 589 void createBranchers(Printer& p, AST::Node* ann, 590 FlatZincOptions& opt, bool ignoreUnknown, 591 std::ostream& err = std::cerr); 592 593 /// Return the solve item annotations 594 AST::Array* solveAnnotations(void) const; 595 596 /// Information for printing branches 597 BranchInformation branchInfo; 598 599 /// Implement optimization 600 virtual void constrain(const Space& s); 601 /// Copy function 602 virtual Gecode::Space* copy(void); 603 /// Slave function for restarts 604 virtual bool slave(const MetaInfo& mi); 605 606 /// \name AST to variable and value conversion 607 //@{ 608 /// Convert \a arg (array of integers) to IntArgs 609 IntArgs arg2intargs(AST::Node* arg, int offset = 0); 610 /// Convert \a arg (array of integers) to IntSharedArray 611 IntSharedArray arg2intsharedarray(AST::Node* arg, int offset = 0); 612 /// Convert \a arg (array of Booleans) to IntArgs 613 IntArgs arg2boolargs(AST::Node* arg, int offset = 0); 614 /// Convert \a arg (array of integers) to IntSharedArray 615 IntSharedArray arg2boolsharedarray(AST::Node* arg, int offset = 0); 616 /// Convert \a n to IntSet 617 IntSet arg2intset(AST::Node* n); 618 /// Convert \a arg to IntSetArgs 619 IntSetArgs arg2intsetargs(AST::Node* arg, int offset = 0); 620 /// Convert \a arg to IntVarArgs 621 IntVarArgs arg2intvarargs(AST::Node* arg, int offset = 0); 622 /// Convert \a arg to BoolVarArgs 623 BoolVarArgs arg2boolvarargs(AST::Node* arg, int offset = 0, int siv=-1); 624 /// Convert \a n to BoolVar 625 BoolVar arg2BoolVar(AST::Node* n); 626 /// Convert \a n to IntVar 627 IntVar arg2IntVar(AST::Node* n); 628 /// Convert \a a to TupleSet 629 TupleSet arg2tupleset(const IntArgs& a, int noOfVars); 630 /// Check if \a b is array of Booleans (or has a single integer) 631 bool isBoolArray(AST::Node* b, int& singleInt); 632 #ifdef GECODE_HAS_SET_VARS 633 /// Convert \a n to SetVar 634 SetVar arg2SetVar(AST::Node* n); 635 /// Convert \a n to SetVarArgs 636 SetVarArgs arg2setvarargs(AST::Node* arg, int offset = 0, int doffset = 0, 637 const IntSet& od=IntSet::empty); 638 #endif 639 #ifdef GECODE_HAS_FLOAT_VARS 640 /// Convert \a n to FloatValArgs 641 FloatValArgs arg2floatargs(AST::Node* arg, int offset = 0); 642 /// Convert \a n to FloatVar 643 FloatVar arg2FloatVar(AST::Node* n); 644 /// Convert \a n to FloatVarArgs 645 FloatVarArgs arg2floatvarargs(AST::Node* arg, int offset = 0); 646 #endif 647 /// Convert \a ann to integer propagation level 648 IntPropLevel ann2ipl(AST::Node* ann); 649 /// Share DFA \a a if possible 650 DFA getSharedDFA(DFA& a); 651 //@} 652 }; 653 654 /// %Exception class for %FlatZinc errors 655 class GECODE_VTABLE_EXPORT Error { 656 private: 657 const std::string msg; 658 public: Error(const std::string & where,const std::string & what)659 Error(const std::string& where, const std::string& what) 660 : msg(where+": "+what) {} Error(const std::string & where,const std::string & what,AST::Array * const ann)661 Error(const std::string& where, const std::string& what, AST::Array *const ann) 662 : msg(make_message(where, what, ann)) {} toString(void) const663 const std::string& toString(void) const { return msg; } 664 private: make_message(const std::string & where,const std::string & what,AST::Array * const ann)665 static std::string make_message(const std::string &where, const std::string &what, AST::Array *const ann) { 666 std::ostringstream result; 667 result << where << ": " << what; 668 669 std::vector<std::string> names = get_constraint_names(ann); 670 if (names.size() > 1) { 671 result << " in constraints "; 672 for (unsigned int i = 0; i < names.size(); ++i) { 673 result << '\"' << names[i] << '\"'; 674 if (i < names.size() - 1) { 675 result << ","; 676 } 677 result << " "; 678 } 679 } else if (names.size() == 1) { 680 result << " in constraint " << '\"' << names[0] << '\"'; 681 } 682 683 return result.str(); 684 } get_constraint_names(AST::Array * const ann)685 static std::vector<std::string> get_constraint_names(AST::Array *const ann) { 686 std::vector<std::string> result; 687 if (ann) { 688 for (const auto & i : ann->a) { 689 if (i->isArray()) { 690 auto nested_result = get_constraint_names(i->getArray()); 691 result.insert(result.end(), nested_result.begin(), nested_result.end()); 692 } else if (i->isCall("mzn_constraint_name")) { 693 result.emplace_back(i->getCall()->args->getString()); 694 } 695 } 696 } 697 return result; 698 } 699 }; 700 701 /** 702 * \brief Parse FlatZinc file \a fileName into \a fzs and return it. 703 * 704 * Creates a new empty FlatZincSpace if \a fzs is nullptr. 705 */ 706 GECODE_FLATZINC_EXPORT 707 FlatZincSpace* parse(const std::string& fileName, 708 Printer& p, std::ostream& err = std::cerr, 709 FlatZincSpace* fzs=nullptr, Rnd& rnd=defrnd); 710 711 /** 712 * \brief Parse FlatZinc from \a is into \a fzs and return it. 713 * 714 * Creates a new empty FlatZincSpace if \a fzs is nullptr. 715 */ 716 GECODE_FLATZINC_EXPORT 717 FlatZincSpace* parse(std::istream& is, 718 Printer& p, std::ostream& err = std::cerr, 719 FlatZincSpace* fzs=nullptr, Rnd& rnd=defrnd); 720 721 }} 722 723 #endif 724 725 // STATISTICS: flatzinc-any 726