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