this repo has no description
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#include <array> 92#include <memory> 93 94/** 95 * \namespace Gecode::FlatZinc 96 * \brief Interpreter for the %FlatZinc language 97 * 98 * The Gecode::FlatZinc namespace contains all functionality required 99 * to parse and solve constraint models written in the %FlatZinc language. 100 * 101 */ 102 103namespace Gecode { namespace FlatZinc { 104 105 /** 106 * \brief Output support class for %FlatZinc interpreter 107 * 108 */ 109 class GECODE_FLATZINC_EXPORT Printer { 110 private: 111 /// Names of integer variables 112 std::vector<std::string> iv_names; 113 /// Names of Boolean variables 114 std::vector<std::string> bv_names; 115#ifdef GECODE_HAS_FLOAT_VARS 116 /// Names of float variables 117 std::vector<std::string> fv_names; 118#endif 119#ifdef GECODE_HAS_SET_VARS 120 /// Names of set variables 121 std::vector<std::string> sv_names; 122#endif 123 AST::Array* _output; 124 void printElem(std::ostream& out, 125 AST::Node* ai, 126 const Gecode::IntVarArray& iv, 127 const Gecode::BoolVarArray& bv 128#ifdef GECODE_HAS_SET_VARS 129 , 130 const Gecode::SetVarArray& sv 131#endif 132#ifdef GECODE_HAS_FLOAT_VARS 133 , 134 const Gecode::FloatVarArray& fv 135#endif 136 ) const; 137 void printElemDiff(std::ostream& out, 138 AST::Node* ai, 139 const Gecode::IntVarArray& iv1, 140 const Gecode::IntVarArray& iv2, 141 const Gecode::BoolVarArray& bv1, 142 const Gecode::BoolVarArray& bv2 143#ifdef GECODE_HAS_SET_VARS 144 , 145 const Gecode::SetVarArray& sv1, 146 const Gecode::SetVarArray& sv2 147#endif 148#ifdef GECODE_HAS_FLOAT_VARS 149 , 150 const Gecode::FloatVarArray& fv1, 151 const Gecode::FloatVarArray& fv2 152#endif 153 ) const; 154 public: 155 Printer(void) : _output(nullptr) {} 156 void init(AST::Array* output); 157 158 void print(std::ostream& out, 159 const Gecode::IntVarArray& iv, 160 const Gecode::BoolVarArray& bv 161#ifdef GECODE_HAS_SET_VARS 162 , 163 const Gecode::SetVarArray& sv 164#endif 165#ifdef GECODE_HAS_FLOAT_VARS 166 , 167 const Gecode::FloatVarArray& fv 168#endif 169 ) const; 170 171 void printDiff(std::ostream& out, 172 const Gecode::IntVarArray& iv1, const Gecode::IntVarArray& iv2, 173 const Gecode::BoolVarArray& bv1, const Gecode::BoolVarArray& bv2 174#ifdef GECODE_HAS_SET_VARS 175 , 176 const Gecode::SetVarArray& sv1, const Gecode::SetVarArray& sv2 177#endif 178#ifdef GECODE_HAS_FLOAT_VARS 179 , 180 const Gecode::FloatVarArray& fv1, 181 const Gecode::FloatVarArray& fv2 182#endif 183 ) const; 184 185 186 ~Printer(void); 187 188 void addIntVarName(const std::string& n); 189 const std::string& intVarName(int i) const { return iv_names[i]; } 190 void addBoolVarName(const std::string& n); 191 const std::string& boolVarName(int i) const { return bv_names[i]; } 192#ifdef GECODE_HAS_FLOAT_VARS 193 void addFloatVarName(const std::string& n); 194 const std::string& floatVarName(int i) const { return fv_names[i]; } 195#endif 196#ifdef GECODE_HAS_SET_VARS 197 void addSetVarName(const std::string& n); 198 const std::string& setVarName(int i) const { return sv_names[i]; } 199#endif 200 201 void shrinkElement(AST::Node* node, 202 std::map<int,int>& iv, std::map<int,int>& bv, 203 std::map<int,int>& sv, std::map<int,int>& fv); 204 205 void shrinkArrays(Space& home, 206 int& optVar, bool optVarIsInt, 207 Gecode::IntVarArray& iv, 208 Gecode::BoolVarArray& bv 209#ifdef GECODE_HAS_SET_VARS 210 , 211 Gecode::SetVarArray& sv 212#endif 213#ifdef GECODE_HAS_FLOAT_VARS 214 , 215 Gecode::FloatVarArray& fv 216#endif 217 ); 218 219 private: 220 Printer(const Printer&); 221 Printer& operator=(const Printer&); 222 }; 223 224 /** 225 * \brief %Options for running %FlatZinc models 226 * 227 */ 228 class FlatZincOptions : public Gecode::BaseOptions { 229 protected: 230 /// \name Search options 231 //@{ 232 Gecode::Driver::IntOption _solutions; ///< How many solutions 233 Gecode::Driver::BoolOption _allSolutions; ///< Return all solutions 234 Gecode::Driver::DoubleOption _threads; ///< How many threads to use 235 Gecode::Driver::BoolOption _free; ///< Use free search 236 Gecode::Driver::DoubleOption _decay; ///< Decay option 237 Gecode::Driver::UnsignedIntOption _c_d; ///< Copy recomputation distance 238 Gecode::Driver::UnsignedIntOption _a_d; ///< Adaptive recomputation distance 239 Gecode::Driver::UnsignedLongLongIntOption _node; ///< Cutoff for number of nodes 240 Gecode::Driver::UnsignedLongLongIntOption _fail; ///< Cutoff for number of failures 241 Gecode::Driver::DoubleOption _time; ///< Cutoff for time 242 Gecode::Driver::DoubleOption _time_limit; ///< Cutoff for time (for compatibility with flatzinc command line) 243 Gecode::Driver::IntOption _seed; ///< Random seed 244 Gecode::Driver::StringOption _restart; ///< Restart method option 245 Gecode::Driver::DoubleOption _r_base; ///< Restart base 246 Gecode::Driver::UnsignedIntOption _r_scale; ///< Restart scale factor 247 Gecode::Driver::BoolOption _nogoods; ///< Whether to use no-goods 248 Gecode::Driver::UnsignedIntOption _nogoods_limit; ///< Depth limit for extracting no-goods 249 Gecode::Driver::BoolOption _interrupt; ///< Whether to catch SIGINT 250 Gecode::Driver::DoubleOption _step; ///< Step option 251 //@} 252 253 /// \name Execution options 254 //@{ 255 Gecode::Driver::StringOption _mode; ///< Script mode to run 256 Gecode::Driver::BoolOption _stat; ///< Emit statistics 257 Gecode::Driver::StringValueOption _output; ///< Output file 258 259#ifdef GECODE_HAS_CPPROFILER 260 Gecode::Driver::ProfilerOption _profiler; ///< Use this execution id for the CP-profiler 261#endif 262 263 //@} 264 public: 265 /// Constructor 266 FlatZincOptions(const char* s) 267 : Gecode::BaseOptions(s), 268 _solutions("n","number of solutions (0 = all, -1 = one/best)",-1), 269 _allSolutions("a", "return all solutions (equal to -n 0)"), 270 _threads("p","number of threads (0 = #processing units)", 271 Gecode::Search::Config::threads), 272 _free("f", "free search, no need to follow search-specification"), 273 _decay("decay","decay factor",0.99), 274 _c_d("c-d","recomputation commit distance",Gecode::Search::Config::c_d), 275 _a_d("a-d","recomputation adaption distance",Gecode::Search::Config::a_d), 276 _node("node","node cutoff (0 = none, solution mode)"), 277 _fail("fail","failure cutoff (0 = none, solution mode)"), 278 _time("time","time (in ms) cutoff (0 = none, solution mode)"), 279 _time_limit("t","time (in ms) cutoff (0 = none, solution mode)"), 280 _seed("r","random seed",0), 281 _restart("restart","restart sequence type",RM_NONE), 282 _r_base("restart-base","base for geometric restart sequence",1.5), 283 _r_scale("restart-scale","scale factor for restart sequence",250), 284 _nogoods("nogoods","whether to use no-goods from restarts",false), 285 _nogoods_limit("nogoods-limit","depth limit for no-good extraction", 286 Search::Config::nogoods_limit), 287 _interrupt("interrupt","whether to catch Ctrl-C (true) or not (false)", 288 true), 289 _step("step","step distance for float optimization",0.0), 290 _mode("mode","how to execute script",Gecode::SM_SOLUTION), 291 _stat("s","emit statistics"), 292 _output("o","file to send output to") 293 294#ifdef GECODE_HAS_CPPROFILER 295 , 296 _profiler("cp-profiler", "use this execution id and port (comma separated) with CP-profiler") 297#endif 298 { 299 _mode.add(Gecode::SM_SOLUTION, "solution"); 300 _mode.add(Gecode::SM_STAT, "stat"); 301 _mode.add(Gecode::SM_GIST, "gist"); 302 _restart.add(RM_NONE,"none"); 303 _restart.add(RM_CONSTANT,"constant"); 304 _restart.add(RM_LINEAR,"linear"); 305 _restart.add(RM_LUBY,"luby"); 306 _restart.add(RM_GEOMETRIC,"geometric"); 307 308 add(_solutions); add(_threads); add(_c_d); add(_a_d); 309 add(_allSolutions); 310 add(_free); 311 add(_decay); 312 add(_node); add(_fail); add(_time); add(_time_limit); add(_interrupt); 313 add(_seed); 314 add(_step); 315 add(_restart); add(_r_base); add(_r_scale); 316 add(_nogoods); add(_nogoods_limit); 317 add(_mode); add(_stat); 318 add(_output); 319#ifdef GECODE_HAS_CPPROFILER 320 add(_profiler); 321#endif 322 } 323 324 void parse(int& argc, char* argv[]) { 325 Gecode::BaseOptions::parse(argc,argv); 326 if (_allSolutions.value() && _solutions.value()==-1) { 327 _solutions.value(0); 328 } 329 if (_time_limit.value()) { 330 _time.value(_time_limit.value()); 331 } 332 if (_stat.value()) 333 _mode.value(Gecode::SM_STAT); 334 } 335 336 virtual void help(void) { 337 std::cerr << "Gecode FlatZinc interpreter" << std::endl 338 << " - Supported FlatZinc version: " << GECODE_FLATZINC_VERSION 339 << std::endl << std::endl; 340 Gecode::BaseOptions::help(); 341 } 342 343 int solutions(void) const { return _solutions.value(); } 344 bool allSolutions(void) const { return _allSolutions.value(); } 345 double threads(void) const { return _threads.value(); } 346 bool free(void) const { return _free.value(); } 347 unsigned int c_d(void) const { return _c_d.value(); } 348 unsigned int a_d(void) const { return _a_d.value(); } 349 unsigned long long int node(void) const { return _node.value(); } 350 unsigned long long int fail(void) const { return _fail.value(); } 351 double time(void) const { return _time.value(); } 352 int seed(void) const { return _seed.value(); } 353 double step(void) const { return _step.value(); } 354 const char* output(void) const { return _output.value(); } 355 356 Gecode::ScriptMode mode(void) const { 357 return static_cast<Gecode::ScriptMode>(_mode.value()); 358 } 359 360 double decay(void) const { return _decay.value(); } 361 RestartMode restart(void) const { 362 return static_cast<RestartMode>(_restart.value()); 363 } 364 void restart(RestartMode rm) { 365 _restart.value(rm); 366 } 367 double restart_base(void) const { return _r_base.value(); } 368 void restart_base(double d) { _r_base.value(d); } 369 unsigned int restart_scale(void) const { return _r_scale.value(); } 370 void restart_scale(int i) { _r_scale.value(i); } 371 bool nogoods(void) const { return _nogoods.value(); } 372 unsigned int nogoods_limit(void) const { return _nogoods_limit.value(); } 373 bool interrupt(void) const { return _interrupt.value(); } 374 375#ifdef GECODE_HAS_CPPROFILER 376 377 int profiler_id(void) const { return _profiler.execution_id(); } 378 unsigned int profiler_port(void) const { return _profiler.port(); } 379 bool profiler_info(void) const { return true; } 380 381#endif 382 383 void allSolutions(bool b) { _allSolutions.value(b); } 384 }; 385 386 class BranchInformation : public SharedHandle { 387 public: 388 /// Constructor 389 BranchInformation(void); 390 /// Copy constructor 391 BranchInformation(const BranchInformation& bi); 392 /// Initialise for use 393 void init(void); 394 /// Add new brancher information 395 void add(BrancherGroup bg, 396 const std::string& rel0, 397 const std::string& rel1, 398 const std::vector<std::string>& n); 399 /// Output branch information 400 void print(const Brancher& b, 401 unsigned int a, int i, int n, std::ostream& o) const; 402#ifdef GECODE_HAS_FLOAT_VARS 403 /// Output branch information 404 void print(const Brancher& b, 405 unsigned int a, int i, const FloatNumBranch& nl, 406 std::ostream& o) const; 407#endif 408 }; 409 410 /// Uninitialized default random number generator 411 GECODE_FLATZINC_EXPORT 412 extern Rnd defrnd; 413 414 class FlatZincSpaceInitData; 415 416 /** 417 * \brief A space that can be initialized with a %FlatZinc model 418 * 419 */ 420 class GECODE_FLATZINC_EXPORT FlatZincSpace : public Space { 421 public: 422 static long long copies; 423 enum Meth { 424 SAT, //< Solve as satisfaction problem 425 MIN, //< Solve as minimization problem 426 MAX //< Solve as maximization problem 427 }; 428 protected: 429 /// Initialisation data (only used for posting constraints) 430 FlatZincSpaceInitData* _initData; 431 /// Number of integer variables 432 int intVarCount; 433 /// Number of Boolean variables 434 int boolVarCount; 435 /// Number of float variables 436 int floatVarCount; 437 /// Number of set variables 438 int setVarCount; 439 440 /// Index of the variable to optimize 441 int _optVar; 442 /// Whether variable to optimize is integer (or float) 443 bool _optVarIsInt; 444 445 /// Whether to solve as satisfaction or optimization problem 446 Meth _method; 447 448 /// Percentage of variables to keep in LNS (or 0 for no LNS) 449 unsigned int _lns; 450 451 /// Initial solution to start the LNS (or nullptr for no LNS) 452 IntSharedArray _lnsInitialSolution; 453 454 /// Random number generator 455 Rnd _random; 456 457 /// Annotations on the solve item 458 AST::Array* _solveAnnotations; 459 460 /// Copy constructor 461 FlatZincSpace(FlatZincSpace&); 462 private: 463 /// Run the search engine 464 template<template<class> class Engine> 465 void 466 runEngine(std::ostream& out, const Printer& p, 467 const FlatZincOptions& opt, Gecode::Support::Timer& t_total); 468 /// Run the meta search engine 469 template<template<class> class Engine, 470 template<class, template<class> class> class Meta> 471 void 472 runMeta(std::ostream& out, const Printer& p, 473 const FlatZincOptions& opt, Gecode::Support::Timer& t_total); 474 void 475 branchWithPlugin(AST::Node* ann); 476 public: 477 /// The integer variables 478 Gecode::IntVarArray iv; 479 /// The introduced integer variables 480 Gecode::IntVarArray iv_aux; 481 482 /// The integer variables used in LNS 483 Gecode::IntVarArray iv_lns; 484 485 /// Status() variable 486 Gecode::IntVarArray restart_status; 487 /// int_uniform arguments 488 Gecode::IntVarArray int_uniform_var; 489 int* int_uniform_lb; 490 int* int_uniform_ub; 491 /// int_sol arguments 492 Gecode::IntVarArray int_sol_var; 493 Gecode::IntVarArray int_sol_orig; 494 /// int_lastval arguments 495 Gecode::IntVarArray int_lastval_var; 496 std::shared_ptr<int>* int_lastval_val; 497 498 /// record fixed integers 499 static std::ifstream record; 500 Gecode::IntVarArray main_vars; 501 static std::vector<std::vector<int>> vrecord; 502 static size_t record_i; 503 504 505 /// Indicates whether an integer variable is introduced by mzn2fzn 506 std::vector<bool> iv_introduced; 507 /// Indicates whether an integer variable aliases a Boolean variable 508 int* iv_boolalias; 509 /// The Boolean variables 510 Gecode::BoolVarArray bv; 511 /// The introduced Boolean variables 512 Gecode::BoolVarArray bv_aux; 513 /// Indicates whether a Boolean variable is introduced by mzn2fzn 514 std::vector<bool> bv_introduced; 515#ifdef GECODE_HAS_SET_VARS 516 /// The set variables 517 Gecode::SetVarArray sv; 518 /// The introduced set variables 519 Gecode::SetVarArray sv_aux; 520 /// Indicates whether a set variable is introduced by mzn2fzn 521 std::vector<bool> sv_introduced; 522#endif 523#ifdef GECODE_HAS_FLOAT_VARS 524 /// The float variables 525 Gecode::FloatVarArray fv; 526 /// The introduced float variables 527 Gecode::FloatVarArray fv_aux; 528 /// Indicates whether a float variable is introduced by mzn2fzn 529 std::vector<bool> fv_introduced; 530 /// Step by which a next solution has to have lower cost 531 Gecode::FloatNum step; 532#endif 533 /// Whether the introduced variables still need to be copied 534 bool needAuxVars; 535 /// Construct empty space 536 FlatZincSpace(Rnd& random = defrnd); 537 538 /// Destructor 539 ~FlatZincSpace(void); 540 541 /// Initialize space with given number of variables 542 void init(int intVars, int boolVars, int setVars, int floatVars); 543 544 /// Create new integer variable from specification 545 void newIntVar(IntVarSpec* vs); 546 /// Link integer variable \a iv to Boolean variable \a bv 547 void aliasBool2Int(int iv, int bv); 548 /// Return linked Boolean variable for integer variable \a iv 549 int aliasBool2Int(int iv); 550 /// Create new Boolean variable from specification 551 void newBoolVar(BoolVarSpec* vs); 552 /// Create new set variable from specification 553 void newSetVar(SetVarSpec* vs); 554 /// Create new float variable from specification 555 void newFloatVar(FloatVarSpec* vs); 556 557 /// Post a constraint specified by \a ce 558 void postConstraints(std::vector<ConExpr*>& ces); 559 560 /// Post the solve item 561 void solve(AST::Array* annotation); 562 /// Post that integer variable \a var should be minimized 563 void minimize(int var, bool isInt, AST::Array* annotation); 564 /// Post that integer variable \a var should be maximized 565 void maximize(int var, bool isInt, AST::Array* annotation); 566 567 /// Run the search 568 void run(std::ostream& out, const Printer& p, 569 const FlatZincOptions& opt, Gecode::Support::Timer& t_total); 570 571 /// Produce output on \a out using \a p 572 void print(std::ostream& out, const Printer& p) const; 573#ifdef GECODE_HAS_CPPROFILER 574 /// Get string representing the domains of variables (for cpprofiler) 575 std::string getDomains(const Printer& p) const; 576#endif 577 /// Compare this space with space \a s and print the differences on 578 /// \a out 579 void compare(const Space& s, std::ostream& out) const; 580 /// Compare this space with space \a s and print the differences on 581 /// \a out using \a p 582 void compare(const FlatZincSpace& s, std::ostream& out, 583 const Printer& p) const; 584 585 /** 586 * \brief Remove all variables not needed for output 587 * 588 * After calling this function, no new constraints can be posted through 589 * FlatZinc variable references, and the createBranchers method must 590 * not be called again. 591 * 592 */ 593 void shrinkArrays(Printer& p); 594 595 /// Return whether to solve a satisfaction or optimization problem 596 Meth method(void) const; 597 598 /// Return index of variable used for optimization 599 int optVar(void) const; 600 /// Return whether variable used for optimization is integer (or float) 601 bool optVarIsInt(void) const; 602 603 /** 604 * \brief Create branchers corresponding to the solve item annotations 605 * 606 * If \a ignoreUnknown is true, unknown solve item annotations will be 607 * ignored, otherwise a warning is written to \a err. 608 * 609 * The seed for random branchers is given by the \a seed parameter. 610 * 611 */ 612 void createBranchers(Printer& p, AST::Node* ann, 613 FlatZincOptions& opt, bool ignoreUnknown, 614 std::ostream& err = std::cerr); 615 616 /// Return the solve item annotations 617 AST::Array* solveAnnotations(void) const; 618 619 /// Information for printing branches 620 BranchInformation branchInfo; 621 622 /// Implement optimization 623 virtual void constrain(const Space& s); 624 /// Copy function 625 virtual Gecode::Space* copy(void); 626 /// Slave function for restarts 627 virtual bool slave(const MetaInfo& mi); 628 629 /// \name AST to variable and value conversion 630 //@{ 631 /// Convert \a arg (array of integers) to IntArgs 632 IntArgs arg2intargs(AST::Node* arg, int offset = 0); 633 /// Convert \a arg (array of integers) to IntSharedArray 634 IntSharedArray arg2intsharedarray(AST::Node* arg, int offset = 0); 635 /// Convert \a arg (array of Booleans) to IntArgs 636 IntArgs arg2boolargs(AST::Node* arg, int offset = 0); 637 /// Convert \a arg (array of integers) to IntSharedArray 638 IntSharedArray arg2boolsharedarray(AST::Node* arg, int offset = 0); 639 /// Convert \a n to IntSet 640 IntSet arg2intset(AST::Node* n); 641 /// Convert \a arg to IntSetArgs 642 IntSetArgs arg2intsetargs(AST::Node* arg, int offset = 0); 643 /// Convert \a arg to IntVarArgs 644 IntVarArgs arg2intvarargs(AST::Node* arg, int offset = 0); 645 /// Convert \a arg to BoolVarArgs 646 BoolVarArgs arg2boolvarargs(AST::Node* arg, int offset = 0, int siv=-1); 647 /// Convert \a n to BoolVar 648 BoolVar arg2BoolVar(AST::Node* n); 649 /// Convert \a n to IntVar 650 IntVar arg2IntVar(AST::Node* n); 651 /// Convert \a a to TupleSet 652 TupleSet arg2tupleset(const IntArgs& a, int noOfVars); 653 /// Check if \a b is array of Booleans (or has a single integer) 654 bool isBoolArray(AST::Node* b, int& singleInt); 655#ifdef GECODE_HAS_SET_VARS 656 /// Convert \a n to SetVar 657 SetVar arg2SetVar(AST::Node* n); 658 /// Convert \a n to SetVarArgs 659 SetVarArgs arg2setvarargs(AST::Node* arg, int offset = 0, int doffset = 0, 660 const IntSet& od=IntSet::empty); 661#endif 662#ifdef GECODE_HAS_FLOAT_VARS 663 /// Convert \a n to FloatValArgs 664 FloatValArgs arg2floatargs(AST::Node* arg, int offset = 0); 665 /// Convert \a n to FloatVar 666 FloatVar arg2FloatVar(AST::Node* n); 667 /// Convert \a n to FloatVarArgs 668 FloatVarArgs arg2floatvarargs(AST::Node* arg, int offset = 0); 669#endif 670 /// Convert \a ann to integer propagation level 671 IntPropLevel ann2ipl(AST::Node* ann); 672 /// Share DFA \a a if possible 673 DFA getSharedDFA(DFA& a); 674 //@} 675 }; 676 677 /// %Exception class for %FlatZinc errors 678 class GECODE_VTABLE_EXPORT Error { 679 private: 680 const std::string msg; 681 public: 682 Error(const std::string& where, const std::string& what) 683 : msg(where+": "+what) {} 684 Error(const std::string& where, const std::string& what, AST::Array *const ann) 685 : msg(make_message(where, what, ann)) {} 686 const std::string& toString(void) const { return msg; } 687 private: 688 static std::string make_message(const std::string &where, const std::string &what, AST::Array *const ann) { 689 std::ostringstream result; 690 result << where << ": " << what; 691 692 std::vector<std::string> names = get_constraint_names(ann); 693 if (names.size() > 1) { 694 result << " in constraints "; 695 for (unsigned int i = 0; i < names.size(); ++i) { 696 result << '\"' << names[i] << '\"'; 697 if (i < names.size() - 1) { 698 result << ","; 699 } 700 result << " "; 701 } 702 } else if (names.size() == 1) { 703 result << " in constraint " << '\"' << names[0] << '\"'; 704 } 705 706 return result.str(); 707 } 708 static std::vector<std::string> get_constraint_names(AST::Array *const ann) { 709 std::vector<std::string> result; 710 if (ann) { 711 for (const auto & i : ann->a) { 712 if (i->isArray()) { 713 auto nested_result = get_constraint_names(i->getArray()); 714 result.insert(result.end(), nested_result.begin(), nested_result.end()); 715 } else if (i->isCall("mzn_constraint_name")) { 716 result.emplace_back(i->getCall()->args->getString()); 717 } 718 } 719 } 720 return result; 721 } 722 }; 723 724 /** 725 * \brief Parse FlatZinc file \a fileName into \a fzs and return it. 726 * 727 * Creates a new empty FlatZincSpace if \a fzs is nullptr. 728 */ 729 GECODE_FLATZINC_EXPORT 730 FlatZincSpace* parse(const std::string& fileName, 731 Printer& p, std::ostream& err = std::cerr, 732 FlatZincSpace* fzs=nullptr, Rnd& rnd=defrnd); 733 734 /** 735 * \brief Parse FlatZinc from \a is into \a fzs and return it. 736 * 737 * Creates a new empty FlatZincSpace if \a fzs is nullptr. 738 */ 739 GECODE_FLATZINC_EXPORT 740 FlatZincSpace* parse(std::istream& is, 741 Printer& p, std::ostream& err = std::cerr, 742 FlatZincSpace* fzs=nullptr, Rnd& rnd=defrnd); 743 744}} 745 746#endif 747 748// STATISTICS: flatzinc-any