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
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
101namespace 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:
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);
187 const std::string& intVarName(int i) const { return iv_names[i]; }
188 void addBoolVarName(const std::string& n);
189 const std::string& boolVarName(int i) const { return bv_names[i]; }
190#ifdef GECODE_HAS_FLOAT_VARS
191 void addFloatVarName(const std::string& n);
192 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);
196 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
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
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
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
341 int solutions(void) const { return _solutions.value(); }
342 bool allSolutions(void) const { return _allSolutions.value(); }
343 double threads(void) const { return _threads.value(); }
344 bool free(void) const { return _free.value(); }
345 unsigned int c_d(void) const { return _c_d.value(); }
346 unsigned int a_d(void) const { return _a_d.value(); }
347 unsigned long long int node(void) const { return _node.value(); }
348 unsigned long long int fail(void) const { return _fail.value(); }
349 double time(void) const { return _time.value(); }
350 int seed(void) const { return _seed.value(); }
351 double step(void) const { return _step.value(); }
352 const char* output(void) const { return _output.value(); }
353
354 Gecode::ScriptMode mode(void) const {
355 return static_cast<Gecode::ScriptMode>(_mode.value());
356 }
357
358 double decay(void) const { return _decay.value(); }
359 RestartMode restart(void) const {
360 return static_cast<RestartMode>(_restart.value());
361 }
362 void restart(RestartMode rm) {
363 _restart.value(rm);
364 }
365 double restart_base(void) const { return _r_base.value(); }
366 void restart_base(double d) { _r_base.value(d); }
367 unsigned int restart_scale(void) const { return _r_scale.value(); }
368 void restart_scale(int i) { _r_scale.value(i); }
369 bool nogoods(void) const { return _nogoods.value(); }
370 unsigned int nogoods_limit(void) const { return _nogoods_limit.value(); }
371 bool interrupt(void) const { return _interrupt.value(); }
372
373#ifdef GECODE_HAS_CPPROFILER
374
375 int profiler_id(void) const { return _profiler.execution_id(); }
376 unsigned int profiler_port(void) const { return _profiler.port(); }
377 bool profiler_info(void) const { return true; }
378
379#endif
380
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:
659 Error(const std::string& where, const std::string& what)
660 : msg(where+": "+what) {}
661 Error(const std::string& where, const std::string& what, AST::Array *const ann)
662 : msg(make_message(where, what, ann)) {}
663 const std::string& toString(void) const { return msg; }
664 private:
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 }
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