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#include <gecode/flatzinc.hh> 39#include <gecode/flatzinc/registry.hh> 40#include <gecode/flatzinc/plugin.hh> 41#include <gecode/flatzinc/branch.hh> 42 43#include <gecode/search.hh> 44 45#include <vector> 46#include <string> 47#include <sstream> 48#include <limits> 49#include <unordered_set> 50 51 52namespace std { 53 54 /// Hashing for tuple sets 55 template<> struct hash<Gecode::TupleSet> { 56 /// Return hash key for \a x 57 forceinline size_t 58 operator()(const Gecode::TupleSet& x) const { 59 return x.hash(); 60 } 61 }; 62 63 /// Hashing for tuple sets 64 template<> struct hash<Gecode::SharedArray<int> > { 65 /// Return hash key for \a x 66 forceinline size_t 67 operator()(const Gecode::SharedArray<int>& x) const { 68 size_t seed = static_cast<size_t>(x.size()); 69 for (int i=x.size(); i--; ) 70 Gecode::cmb_hash(seed, x[i]); 71 return seed; 72 } 73 }; 74 75 /// Hashing for DFAs 76 template<> struct hash<Gecode::DFA> { 77 /// Return hash key for \a d 78 forceinline size_t operator()(const Gecode::DFA& d) const { 79 return d.hash(); 80 } 81 }; 82 83} 84 85namespace Gecode { namespace FlatZinc { 86 87 // Default random number generator 88 Rnd defrnd(0); 89 90 /** 91 * \brief Branching on the introduced variables 92 * 93 * This brancher makes sure that when a solution is found for the model 94 * variables, all introduced variables are either assigned, or the solution 95 * can be extended to a solution of the introduced variables. 96 * 97 * The advantage over simply branching over the introduced variables is that 98 * only one such extension will be searched for, instead of enumerating all 99 * possible (equivalent) extensions. 100 * 101 */ 102 class AuxVarBrancher : public Brancher { 103 protected: 104 /// Flag whether brancher is done 105 bool done; 106 /// Construct brancher 107 AuxVarBrancher(Home home, TieBreak<IntVarBranch> int_varsel0, 108 IntValBranch int_valsel0, 109 TieBreak<BoolVarBranch> bool_varsel0, 110 BoolValBranch bool_valsel0 111#ifdef GECODE_HAS_SET_VARS 112 , 113 SetVarBranch set_varsel0, 114 SetValBranch set_valsel0 115#endif 116#ifdef GECODE_HAS_FLOAT_VARS 117 , 118 TieBreak<FloatVarBranch> float_varsel0, 119 FloatValBranch float_valsel0 120#endif 121 ) 122 : Brancher(home), done(false), 123 int_varsel(int_varsel0), int_valsel(int_valsel0), 124 bool_varsel(bool_varsel0), bool_valsel(bool_valsel0) 125#ifdef GECODE_HAS_SET_VARS 126 , set_varsel(set_varsel0), set_valsel(set_valsel0) 127#endif 128#ifdef GECODE_HAS_FLOAT_VARS 129 , float_varsel(float_varsel0), float_valsel(float_valsel0) 130#endif 131 {} 132 /// Copy constructor 133 AuxVarBrancher(Space& home, AuxVarBrancher& b) 134 : Brancher(home, b), done(b.done) {} 135 136 /// %Choice that only signals failure or success 137 class Choice : public Gecode::Choice { 138 public: 139 /// Whether brancher should fail 140 bool fail; 141 /// Initialize choice for brancher \a b 142 Choice(const Brancher& b, bool fail0) 143 : Gecode::Choice(b,1), fail(fail0) {} 144 /// Report size occupied 145 virtual size_t size(void) const { 146 return sizeof(Choice); 147 } 148 /// Archive into \a e 149 virtual void archive(Archive& e) const { 150 Gecode::Choice::archive(e); 151 e.put(fail); 152 } 153 }; 154 155 TieBreak<IntVarBranch> int_varsel; 156 IntValBranch int_valsel; 157 TieBreak<BoolVarBranch> bool_varsel; 158 BoolValBranch bool_valsel; 159#ifdef GECODE_HAS_SET_VARS 160 SetVarBranch set_varsel; 161 SetValBranch set_valsel; 162#endif 163#ifdef GECODE_HAS_FLOAT_VARS 164 TieBreak<FloatVarBranch> float_varsel; 165 FloatValBranch float_valsel; 166#endif 167 168 public: 169 /// Check status of brancher, return true if alternatives left. 170 virtual bool status(const Space& _home) const { 171 if (done) return false; 172 const FlatZincSpace& home = static_cast<const FlatZincSpace&>(_home); 173 for (int i=0; i<home.iv_aux.size(); i++) 174 if (!home.iv_aux[i].assigned()) return true; 175 for (int i=0; i<home.bv_aux.size(); i++) 176 if (!home.bv_aux[i].assigned()) return true; 177#ifdef GECODE_HAS_SET_VARS 178 for (int i=0; i<home.sv_aux.size(); i++) 179 if (!home.sv_aux[i].assigned()) return true; 180#endif 181#ifdef GECODE_HAS_FLOAT_VARS 182 for (int i=0; i<home.fv_aux.size(); i++) 183 if (!home.fv_aux[i].assigned()) return true; 184#endif 185 // No non-assigned variables left 186 return false; 187 } 188 /// Return choice 189 virtual Choice* choice(Space& home) { 190 done = true; 191 FlatZincSpace& fzs = static_cast<FlatZincSpace&>(*home.clone()); 192 fzs.needAuxVars = false; 193 branch(fzs,fzs.iv_aux,int_varsel,int_valsel); 194 branch(fzs,fzs.bv_aux,bool_varsel,bool_valsel); 195#ifdef GECODE_HAS_SET_VARS 196 branch(fzs,fzs.sv_aux,set_varsel,set_valsel); 197#endif 198#ifdef GECODE_HAS_FLOAT_VARS 199 branch(fzs,fzs.fv_aux,float_varsel,float_valsel); 200#endif 201 Search::Options opt; opt.clone = false; 202 FlatZincSpace* sol = dfs(&fzs, opt); 203 if (sol) { 204 delete sol; 205 return new Choice(*this,false); 206 } else { 207 return new Choice(*this,true); 208 } 209 } 210 /// Return choice 211 virtual Choice* choice(const Space&, Archive& e) { 212 bool fail; e >> fail; 213 return new Choice(*this, fail); 214 } 215 /// Perform commit for choice \a c 216 virtual ExecStatus commit(Space&, const Gecode::Choice& c, unsigned int) { 217 return static_cast<const Choice&>(c).fail ? ES_FAILED : ES_OK; 218 } 219 /// Print explanation 220 virtual void print(const Space&, const Gecode::Choice& c, 221 unsigned int, 222 std::ostream& o) const { 223 o << "FlatZinc(" 224 << (static_cast<const Choice&>(c).fail ? "fail" : "ok") 225 << ")"; 226 } 227 /// Copy brancher 228 virtual Actor* copy(Space& home) { 229 return new (home) AuxVarBrancher(home, *this); 230 } 231 /// Post brancher 232 static void post(Home home, 233 TieBreak<IntVarBranch> int_varsel, 234 IntValBranch int_valsel, 235 TieBreak<BoolVarBranch> bool_varsel, 236 BoolValBranch bool_valsel 237#ifdef GECODE_HAS_SET_VARS 238 , 239 SetVarBranch set_varsel, 240 SetValBranch set_valsel 241#endif 242#ifdef GECODE_HAS_FLOAT_VARS 243 , 244 TieBreak<FloatVarBranch> float_varsel, 245 FloatValBranch float_valsel 246#endif 247 ) { 248 (void) new (home) AuxVarBrancher(home, int_varsel, int_valsel, 249 bool_varsel, bool_valsel 250#ifdef GECODE_HAS_SET_VARS 251 , set_varsel, set_valsel 252#endif 253#ifdef GECODE_HAS_FLOAT_VARS 254 , float_varsel, float_valsel 255#endif 256 ); 257 } 258 /// Delete brancher and return its size 259 virtual size_t dispose(Space&) { 260 return sizeof(*this); 261 } 262 }; 263 264 class BranchInformationO : public SharedHandle::Object { 265 private: 266 struct BI { 267 std::string r0; 268 std::string r1; 269 std::vector<std::string> n; 270 BI(void) : r0(""), r1(""), n(0) {} 271 BI(const std::string& r00, const std::string& r10, 272 const std::vector<std::string>& n0) 273 : r0(r00), r1(r10), n(n0) {} 274 }; 275 std::vector<BI> v; 276 BranchInformationO(std::vector<BI> v0) : v(v0) {} 277 public: 278 BranchInformationO(void) {} 279 virtual ~BranchInformationO(void) {} 280 virtual SharedHandle::Object* copy(void) const { 281 return new BranchInformationO(v); 282 } 283 /// Add new brancher information 284 void add(BrancherGroup bg, 285 const std::string& rel0, 286 const std::string& rel1, 287 const std::vector<std::string>& n) { 288 v.resize(std::max(static_cast<unsigned int>(v.size()),bg.id()+1)); 289 v[bg.id()] = BI(rel0,rel1,n); 290 } 291 /// Output branch information 292 void print(const Brancher& b, 293 unsigned int a, int i, int n, std::ostream& o) const { 294 const BI& bi = v[b.group().id()]; 295 o << bi.n[i] << " " << (a==0 ? bi.r0 : bi.r1) << " " << n; 296 } 297#ifdef GECODE_HAS_FLOAT_VARS 298 void print(const Brancher& b, 299 unsigned int a, int i, const FloatNumBranch& nl, 300 std::ostream& o) const { 301 const BI& bi = v[b.group().id()]; 302 o << bi.n[i] << " " 303 << (((a == 0) == nl.l) ? "<=" : ">=") << nl.n; 304 } 305#endif 306 }; 307 308 BranchInformation::BranchInformation(void) 309 : SharedHandle(nullptr) {} 310 311 BranchInformation::BranchInformation(const BranchInformation& bi) 312 : SharedHandle(bi) {} 313 314 void 315 BranchInformation::init(void) { 316 assert(object() == nullptr); 317 object(new BranchInformationO()); 318 } 319 320 void 321 BranchInformation::add(BrancherGroup bg, 322 const std::string& rel0, 323 const std::string& rel1, 324 const std::vector<std::string>& n) { 325 static_cast<BranchInformationO*>(object())->add(bg,rel0,rel1,n); 326 } 327 void 328 BranchInformation::print(const Brancher& b, unsigned int a, int i, 329 int n, std::ostream& o) const { 330 static_cast<const BranchInformationO*>(object())->print(b,a,i,n,o); 331 } 332#ifdef GECODE_HAS_FLOAT_VARS 333 void 334 BranchInformation::print(const Brancher& b, unsigned int a, int i, 335 const FloatNumBranch& nl, std::ostream& o) const { 336 static_cast<const BranchInformationO*>(object())->print(b,a,i,nl,o); 337 } 338#endif 339 template<class Var> 340 void varValPrint(const Space &home, const Brancher& b, 341 unsigned int a, 342 Var, int i, const int& n, 343 std::ostream& o) { 344 static_cast<const FlatZincSpace&>(home).branchInfo.print(b,a,i,n,o); 345 } 346 347#ifdef GECODE_HAS_FLOAT_VARS 348 void varValPrintF(const Space &home, const Brancher& b, 349 unsigned int a, 350 FloatVar, int i, const FloatNumBranch& nl, 351 std::ostream& o) { 352 static_cast<const FlatZincSpace&>(home).branchInfo.print(b,a,i,nl,o); 353 } 354#endif 355 356 IntSet vs2is(IntVarSpec* vs) { 357 if (vs->assigned) { 358 return IntSet(vs->i,vs->i); 359 } 360 if (vs->domain()) { 361 AST::SetLit* sl = vs->domain.some(); 362 if (sl->interval) { 363 return IntSet(sl->min, sl->max); 364 } else { 365 int* newdom = heap.alloc<int>(static_cast<unsigned long int>(sl->s.size())); 366 for (int i=sl->s.size(); i--;) 367 newdom[i] = sl->s[i]; 368 IntSet ret(newdom, sl->s.size()); 369 heap.free(newdom, static_cast<unsigned long int>(sl->s.size())); 370 return ret; 371 } 372 } 373 return IntSet(Int::Limits::min, Int::Limits::max); 374 } 375 376 int vs2bsl(BoolVarSpec* bs) { 377 if (bs->assigned) { 378 return bs->i; 379 } 380 if (bs->domain()) { 381 AST::SetLit* sl = bs->domain.some(); 382 assert(sl->interval); 383 return std::min(1, std::max(0, sl->min)); 384 } 385 return 0; 386 } 387 388 int vs2bsh(BoolVarSpec* bs) { 389 if (bs->assigned) { 390 return bs->i; 391 } 392 if (bs->domain()) { 393 AST::SetLit* sl = bs->domain.some(); 394 assert(sl->interval); 395 return std::max(0, std::min(1, sl->max)); 396 } 397 return 1; 398 } 399 400 TieBreak<IntVarBranch> ann2ivarsel(AST::Node* ann, Rnd rnd, double decay) { 401 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 402 if (s->id == "input_order") 403 return TieBreak<IntVarBranch>(INT_VAR_NONE()); 404 if (s->id == "first_fail") 405 return TieBreak<IntVarBranch>(INT_VAR_SIZE_MIN()); 406 if (s->id == "anti_first_fail") 407 return TieBreak<IntVarBranch>(INT_VAR_SIZE_MAX()); 408 if (s->id == "smallest") 409 return TieBreak<IntVarBranch>(INT_VAR_MIN_MIN()); 410 if (s->id == "largest") 411 return TieBreak<IntVarBranch>(INT_VAR_MAX_MAX()); 412 if (s->id == "occurrence") 413 return TieBreak<IntVarBranch>(INT_VAR_DEGREE_MAX()); 414 if (s->id == "max_regret") 415 return TieBreak<IntVarBranch>(INT_VAR_REGRET_MIN_MAX()); 416 if (s->id == "most_constrained") 417 return TieBreak<IntVarBranch>(INT_VAR_SIZE_MIN(), 418 INT_VAR_DEGREE_MAX()); 419 if (s->id == "random") { 420 return TieBreak<IntVarBranch>(INT_VAR_RND(rnd)); 421 } 422 if (s->id == "dom_w_deg") { 423 return TieBreak<IntVarBranch>(INT_VAR_AFC_SIZE_MAX(decay)); 424 } 425 if (s->id == "afc_min") 426 return TieBreak<IntVarBranch>(INT_VAR_AFC_MIN(decay)); 427 if (s->id == "afc_max") 428 return TieBreak<IntVarBranch>(INT_VAR_AFC_MAX(decay)); 429 if (s->id == "afc_size_min") 430 return TieBreak<IntVarBranch>(INT_VAR_AFC_SIZE_MIN(decay)); 431 if (s->id == "afc_size_max") { 432 return TieBreak<IntVarBranch>(INT_VAR_AFC_SIZE_MAX(decay)); 433 } 434 if (s->id == "action_min") 435 return TieBreak<IntVarBranch>(INT_VAR_ACTION_MIN(decay)); 436 if (s->id == "action_max") 437 return TieBreak<IntVarBranch>(INT_VAR_ACTION_MAX(decay)); 438 if (s->id == "action_size_min") 439 return TieBreak<IntVarBranch>(INT_VAR_ACTION_SIZE_MIN(decay)); 440 if (s->id == "action_size_max") 441 return TieBreak<IntVarBranch>(INT_VAR_ACTION_SIZE_MAX(decay)); 442 } 443 std::cerr << "Warning, ignored search annotation: "; 444 ann->print(std::cerr); 445 std::cerr << std::endl; 446 return TieBreak<IntVarBranch>(INT_VAR_NONE()); 447 } 448 449 IntValBranch ann2ivalsel(AST::Node* ann, std::string& r0, std::string& r1, 450 Rnd rnd) { 451 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 452 if (s->id == "indomain_min") { 453 r0 = "="; r1 = "!="; 454 return INT_VAL_MIN(); 455 } 456 if (s->id == "indomain_max") { 457 r0 = "="; r1 = "!="; 458 return INT_VAL_MAX(); 459 } 460 if (s->id == "indomain_median") { 461 r0 = "="; r1 = "!="; 462 return INT_VAL_MED(); 463 } 464 if (s->id == "indomain_split") { 465 r0 = "<="; r1 = ">"; 466 return INT_VAL_SPLIT_MIN(); 467 } 468 if (s->id == "indomain_reverse_split") { 469 r0 = ">"; r1 = "<="; 470 return INT_VAL_SPLIT_MAX(); 471 } 472 if (s->id == "indomain_random") { 473 r0 = "="; r1 = "!="; 474 return INT_VAL_RND(rnd); 475 } 476 if (s->id == "indomain") { 477 r0 = "="; r1 = "="; 478 return INT_VALUES_MIN(); 479 } 480 if (s->id == "indomain_middle") { 481 std::cerr << "Warning, replacing unsupported annotation " 482 << "indomain_middle with indomain_median" << std::endl; 483 r0 = "="; r1 = "!="; 484 return INT_VAL_MED(); 485 } 486 if (s->id == "indomain_interval") { 487 std::cerr << "Warning, replacing unsupported annotation " 488 << "indomain_interval with indomain_split" << std::endl; 489 r0 = "<="; r1 = ">"; 490 return INT_VAL_SPLIT_MIN(); 491 } 492 } 493 std::cerr << "Warning, ignored search annotation: "; 494 ann->print(std::cerr); 495 std::cerr << std::endl; 496 r0 = "="; r1 = "!="; 497 return INT_VAL_MIN(); 498 } 499 500 IntAssign ann2asnivalsel(AST::Node* ann, Rnd rnd) { 501 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 502 if (s->id == "indomain_min") 503 return INT_ASSIGN_MIN(); 504 if (s->id == "indomain_max") 505 return INT_ASSIGN_MAX(); 506 if (s->id == "indomain_median") 507 return INT_ASSIGN_MED(); 508 if (s->id == "indomain_random") { 509 return INT_ASSIGN_RND(rnd); 510 } 511 } 512 std::cerr << "Warning, ignored search annotation: "; 513 ann->print(std::cerr); 514 std::cerr << std::endl; 515 return INT_ASSIGN_MIN(); 516 } 517 518 TieBreak<BoolVarBranch> ann2bvarsel(AST::Node* ann, Rnd rnd, double decay) { 519 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 520 if ((s->id == "input_order") || 521 (s->id == "first_fail") || 522 (s->id == "anti_first_fail") || 523 (s->id == "smallest") || 524 (s->id == "largest") || 525 (s->id == "max_regret")) 526 return TieBreak<BoolVarBranch>(BOOL_VAR_NONE()); 527 if ((s->id == "occurrence") || 528 (s->id == "most_constrained")) 529 return TieBreak<BoolVarBranch>(BOOL_VAR_DEGREE_MAX()); 530 if (s->id == "random") 531 return TieBreak<BoolVarBranch>(BOOL_VAR_RND(rnd)); 532 if ((s->id == "afc_min") || 533 (s->id == "afc_size_min")) 534 return TieBreak<BoolVarBranch>(BOOL_VAR_AFC_MIN(decay)); 535 if ((s->id == "afc_max") || 536 (s->id == "afc_size_max") || 537 (s->id == "dom_w_deg")) 538 return TieBreak<BoolVarBranch>(BOOL_VAR_AFC_MAX(decay)); 539 if ((s->id == "action_min") && 540 (s->id == "action_size_min")) 541 return TieBreak<BoolVarBranch>(BOOL_VAR_ACTION_MIN(decay)); 542 if ((s->id == "action_max") || 543 (s->id == "action_size_max")) 544 return TieBreak<BoolVarBranch>(BOOL_VAR_ACTION_MAX(decay)); 545 } 546 std::cerr << "Warning, ignored search annotation: "; 547 ann->print(std::cerr); 548 std::cerr << std::endl; 549 return TieBreak<BoolVarBranch>(BOOL_VAR_NONE()); 550 } 551 552 BoolValBranch ann2bvalsel(AST::Node* ann, std::string& r0, std::string& r1, 553 Rnd rnd) { 554 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 555 if (s->id == "indomain_min") { 556 r0 = "="; r1 = "!="; 557 return BOOL_VAL_MIN(); 558 } 559 if (s->id == "indomain_max") { 560 r0 = "="; r1 = "!="; 561 return BOOL_VAL_MAX(); 562 } 563 if (s->id == "indomain_median") { 564 r0 = "="; r1 = "!="; 565 return BOOL_VAL_MIN(); 566 } 567 if (s->id == "indomain_split") { 568 r0 = "<="; r1 = ">"; 569 return BOOL_VAL_MIN(); 570 } 571 if (s->id == "indomain_reverse_split") { 572 r0 = ">"; r1 = "<="; 573 return BOOL_VAL_MAX(); 574 } 575 if (s->id == "indomain_random") { 576 r0 = "="; r1 = "!="; 577 return BOOL_VAL_RND(rnd); 578 } 579 if (s->id == "indomain") { 580 r0 = "="; r1 = "="; 581 return BOOL_VAL_MIN(); 582 } 583 if (s->id == "indomain_middle") { 584 std::cerr << "Warning, replacing unsupported annotation " 585 << "indomain_middle with indomain_median" << std::endl; 586 r0 = "="; r1 = "!="; 587 return BOOL_VAL_MIN(); 588 } 589 if (s->id == "indomain_interval") { 590 std::cerr << "Warning, replacing unsupported annotation " 591 << "indomain_interval with indomain_split" << std::endl; 592 r0 = "<="; r1 = ">"; 593 return BOOL_VAL_MIN(); 594 } 595 } 596 std::cerr << "Warning, ignored search annotation: "; 597 ann->print(std::cerr); 598 std::cerr << std::endl; 599 r0 = "="; r1 = "!="; 600 return BOOL_VAL_MIN(); 601 } 602 603 BoolAssign ann2asnbvalsel(AST::Node* ann, Rnd rnd) { 604 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 605 if ((s->id == "indomain_min") || 606 (s->id == "indomain_median")) 607 return BOOL_ASSIGN_MIN(); 608 if (s->id == "indomain_max") 609 return BOOL_ASSIGN_MAX(); 610 if (s->id == "indomain_random") { 611 return BOOL_ASSIGN_RND(rnd); 612 } 613 } 614 std::cerr << "Warning, ignored search annotation: "; 615 ann->print(std::cerr); 616 std::cerr << std::endl; 617 return BOOL_ASSIGN_MIN(); 618 } 619 620#ifdef GECODE_HAS_SET_VARS 621 SetVarBranch ann2svarsel(AST::Node* ann, Rnd rnd, double decay) { 622 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 623 if (s->id == "input_order") 624 return SET_VAR_NONE(); 625 if (s->id == "first_fail") 626 return SET_VAR_SIZE_MIN(); 627 if (s->id == "anti_first_fail") 628 return SET_VAR_SIZE_MAX(); 629 if (s->id == "smallest") 630 return SET_VAR_MIN_MIN(); 631 if (s->id == "largest") 632 return SET_VAR_MAX_MAX(); 633 if (s->id == "afc_min") 634 return SET_VAR_AFC_MIN(decay); 635 if (s->id == "afc_max") 636 return SET_VAR_AFC_MAX(decay); 637 if (s->id == "afc_size_min") 638 return SET_VAR_AFC_SIZE_MIN(decay); 639 if (s->id == "afc_size_max") 640 return SET_VAR_AFC_SIZE_MAX(decay); 641 if (s->id == "action_min") 642 return SET_VAR_ACTION_MIN(decay); 643 if (s->id == "action_max") 644 return SET_VAR_ACTION_MAX(decay); 645 if (s->id == "action_size_min") 646 return SET_VAR_ACTION_SIZE_MIN(decay); 647 if (s->id == "action_size_max") 648 return SET_VAR_ACTION_SIZE_MAX(decay); 649 if (s->id == "random") { 650 return SET_VAR_RND(rnd); 651 } 652 } 653 std::cerr << "Warning, ignored search annotation: "; 654 ann->print(std::cerr); 655 std::cerr << std::endl; 656 return SET_VAR_NONE(); 657 } 658 659 SetValBranch ann2svalsel(AST::Node* ann, std::string r0, std::string r1, 660 Rnd rnd) { 661 (void) rnd; 662 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 663 if (s->id == "indomain_min") { 664 r0 = "in"; r1 = "not in"; 665 return SET_VAL_MIN_INC(); 666 } 667 if (s->id == "indomain_max") { 668 r0 = "in"; r1 = "not in"; 669 return SET_VAL_MAX_INC(); 670 } 671 if (s->id == "outdomain_min") { 672 r1 = "in"; r0 = "not in"; 673 return SET_VAL_MIN_EXC(); 674 } 675 if (s->id == "outdomain_max") { 676 r1 = "in"; r0 = "not in"; 677 return SET_VAL_MAX_EXC(); 678 } 679 } 680 std::cerr << "Warning, ignored search annotation: "; 681 ann->print(std::cerr); 682 std::cerr << std::endl; 683 r0 = "in"; r1 = "not in"; 684 return SET_VAL_MIN_INC(); 685 } 686#endif 687 688#ifdef GECODE_HAS_FLOAT_VARS 689 TieBreak<FloatVarBranch> ann2fvarsel(AST::Node* ann, Rnd rnd, 690 double decay) { 691 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 692 if (s->id == "input_order") 693 return TieBreak<FloatVarBranch>(FLOAT_VAR_NONE()); 694 if (s->id == "first_fail") 695 return TieBreak<FloatVarBranch>(FLOAT_VAR_SIZE_MIN()); 696 if (s->id == "anti_first_fail") 697 return TieBreak<FloatVarBranch>(FLOAT_VAR_SIZE_MAX()); 698 if (s->id == "smallest") 699 return TieBreak<FloatVarBranch>(FLOAT_VAR_MIN_MIN()); 700 if (s->id == "largest") 701 return TieBreak<FloatVarBranch>(FLOAT_VAR_MAX_MAX()); 702 if (s->id == "occurrence") 703 return TieBreak<FloatVarBranch>(FLOAT_VAR_DEGREE_MAX()); 704 if (s->id == "most_constrained") 705 return TieBreak<FloatVarBranch>(FLOAT_VAR_SIZE_MIN(), 706 FLOAT_VAR_DEGREE_MAX()); 707 if (s->id == "random") { 708 return TieBreak<FloatVarBranch>(FLOAT_VAR_RND(rnd)); 709 } 710 if (s->id == "afc_min") 711 return TieBreak<FloatVarBranch>(FLOAT_VAR_AFC_MIN(decay)); 712 if (s->id == "afc_max") 713 return TieBreak<FloatVarBranch>(FLOAT_VAR_AFC_MAX(decay)); 714 if (s->id == "afc_size_min") 715 return TieBreak<FloatVarBranch>(FLOAT_VAR_AFC_SIZE_MIN(decay)); 716 if (s->id == "afc_size_max") 717 return TieBreak<FloatVarBranch>(FLOAT_VAR_AFC_SIZE_MAX(decay)); 718 if (s->id == "action_min") 719 return TieBreak<FloatVarBranch>(FLOAT_VAR_ACTION_MIN(decay)); 720 if (s->id == "action_max") 721 return TieBreak<FloatVarBranch>(FLOAT_VAR_ACTION_MAX(decay)); 722 if (s->id == "action_size_min") 723 return TieBreak<FloatVarBranch>(FLOAT_VAR_ACTION_SIZE_MIN(decay)); 724 if (s->id == "action_size_max") 725 return TieBreak<FloatVarBranch>(FLOAT_VAR_ACTION_SIZE_MAX(decay)); 726 } 727 std::cerr << "Warning, ignored search annotation: "; 728 ann->print(std::cerr); 729 std::cerr << std::endl; 730 return TieBreak<FloatVarBranch>(FLOAT_VAR_NONE()); 731 } 732 733 FloatValBranch ann2fvalsel(AST::Node* ann, std::string r0, std::string r1) { 734 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) { 735 if (s->id == "indomain_split") { 736 r0 = "<="; r1 = ">"; 737 return FLOAT_VAL_SPLIT_MIN(); 738 } 739 if (s->id == "indomain_reverse_split") { 740 r1 = "<="; r0 = ">"; 741 return FLOAT_VAL_SPLIT_MAX(); 742 } 743 } 744 std::cerr << "Warning, ignored search annotation: "; 745 ann->print(std::cerr); 746 std::cerr << std::endl; 747 r0 = "<="; r1 = ">"; 748 return FLOAT_VAL_SPLIT_MIN(); 749 } 750 751#endif 752 753 class FlatZincSpaceInitData { 754 public: 755 /// Hash table of tuple sets 756 typedef std::unordered_set<TupleSet> TupleSetSet; 757 /// Hash table of tuple sets 758 TupleSetSet tupleSetSet; 759 760 /// Hash table of shared integer arrays 761 typedef std::unordered_set<SharedArray<int> > IntSharedArraySet; 762 /// Hash table of shared integer arrays 763 IntSharedArraySet intSharedArraySet; 764 765 /// Hash table of DFAs 766 typedef std::unordered_set<DFA> DFASet; 767 /// Hash table of DFAs 768 DFASet dfaSet; 769 770 /// Initialize 771 FlatZincSpaceInitData(void) {} 772 }; 773 774 FlatZincSpace::FlatZincSpace(FlatZincSpace& f) 775 : Space(f), 776 _initData(nullptr), _random(f._random), 777 _solveAnnotations(nullptr), iv_boolalias(nullptr), 778#ifdef GECODE_HAS_FLOAT_VARS 779 step(f.step), 780#endif 781 needAuxVars(f.needAuxVars) { 782 _optVar = f._optVar; 783 _optVarIsInt = f._optVarIsInt; 784 _method = f._method; 785 _lns = f._lns; 786 _lnsInitialSolution = f._lnsInitialSolution; 787 branchInfo = f.branchInfo; 788 iv.update(*this, f.iv); 789 iv_lns.update(*this, f.iv_lns); 790 intVarCount = f.intVarCount; 791 792 if (needAuxVars) { 793 IntVarArgs iva; 794 for (int i=0; i<f.iv_aux.size(); i++) { 795 if (!f.iv_aux[i].assigned()) { 796 iva << IntVar(); 797 iva[iva.size()-1].update(*this, f.iv_aux[i]); 798 } 799 } 800 iv_aux = IntVarArray(*this, iva); 801 } 802 803 bv.update(*this, f.bv); 804 boolVarCount = f.boolVarCount; 805 if (needAuxVars) { 806 BoolVarArgs bva; 807 for (int i=0; i<f.bv_aux.size(); i++) { 808 if (!f.bv_aux[i].assigned()) { 809 bva << BoolVar(); 810 bva[bva.size()-1].update(*this, f.bv_aux[i]); 811 } 812 } 813 bv_aux = BoolVarArray(*this, bva); 814 } 815 816#ifdef GECODE_HAS_SET_VARS 817 sv.update(*this, f.sv); 818 setVarCount = f.setVarCount; 819 if (needAuxVars) { 820 SetVarArgs sva; 821 for (int i=0; i<f.sv_aux.size(); i++) { 822 if (!f.sv_aux[i].assigned()) { 823 sva << SetVar(); 824 sva[sva.size()-1].update(*this, f.sv_aux[i]); 825 } 826 } 827 sv_aux = SetVarArray(*this, sva); 828 } 829#endif 830#ifdef GECODE_HAS_FLOAT_VARS 831 fv.update(*this, f.fv); 832 floatVarCount = f.floatVarCount; 833 if (needAuxVars) { 834 FloatVarArgs fva; 835 for (int i=0; i<f.fv_aux.size(); i++) { 836 if (!f.fv_aux[i].assigned()) { 837 fva << FloatVar(); 838 fva[fva.size()-1].update(*this, f.fv_aux[i]); 839 } 840 } 841 fv_aux = FloatVarArray(*this, fva); 842 } 843#endif 844 } 845 846 FlatZincSpace::FlatZincSpace(Rnd& random) 847 : _initData(new FlatZincSpaceInitData), 848 intVarCount(-1), boolVarCount(-1), floatVarCount(-1), setVarCount(-1), 849 _optVar(-1), _optVarIsInt(true), _lns(0), _lnsInitialSolution(0), 850 _random(random), 851 _solveAnnotations(nullptr), needAuxVars(true) { 852 branchInfo.init(); 853 } 854 855 void 856 FlatZincSpace::init(int intVars, int boolVars, 857 int setVars, int floatVars) { 858 (void) setVars; 859 (void) floatVars; 860 861 intVarCount = 0; 862 iv = IntVarArray(*this, intVars); 863 iv_introduced = std::vector<bool>(2*intVars); 864 iv_boolalias = alloc<int>(intVars+(intVars==0?1:0)); 865 boolVarCount = 0; 866 bv = BoolVarArray(*this, boolVars); 867 bv_introduced = std::vector<bool>(2*boolVars); 868#ifdef GECODE_HAS_SET_VARS 869 setVarCount = 0; 870 sv = SetVarArray(*this, setVars); 871 sv_introduced = std::vector<bool>(2*setVars); 872#endif 873#ifdef GECODE_HAS_FLOAT_VARS 874 floatVarCount = 0; 875 fv = FloatVarArray(*this, floatVars); 876 fv_introduced = std::vector<bool>(2*floatVars); 877#endif 878 } 879 880 void 881 FlatZincSpace::newIntVar(IntVarSpec* vs) { 882 if (vs->alias) { 883 iv[intVarCount++] = iv[vs->i]; 884 } else { 885 IntSet dom(vs2is(vs)); 886 if (dom.size()==0) { 887 fail(); 888 return; 889 } else { 890 iv[intVarCount++] = IntVar(*this, dom); 891 } 892 } 893 iv_introduced[2*(intVarCount-1)] = vs->introduced; 894 iv_introduced[2*(intVarCount-1)+1] = vs->funcDep; 895 iv_boolalias[intVarCount-1] = -1; 896 } 897 898 void 899 FlatZincSpace::aliasBool2Int(int iv, int bv) { 900 iv_boolalias[iv] = bv; 901 } 902 int 903 FlatZincSpace::aliasBool2Int(int iv) { 904 return iv_boolalias[iv]; 905 } 906 907 void 908 FlatZincSpace::newBoolVar(BoolVarSpec* vs) { 909 if (vs->alias) { 910 bv[boolVarCount++] = bv[vs->i]; 911 } else { 912 bv[boolVarCount++] = BoolVar(*this, vs2bsl(vs), vs2bsh(vs)); 913 } 914 bv_introduced[2*(boolVarCount-1)] = vs->introduced; 915 bv_introduced[2*(boolVarCount-1)+1] = vs->funcDep; 916 } 917 918#ifdef GECODE_HAS_SET_VARS 919 void 920 FlatZincSpace::newSetVar(SetVarSpec* vs) { 921 if (vs->alias) { 922 sv[setVarCount++] = sv[vs->i]; 923 } else if (vs->assigned) { 924 assert(vs->upperBound()); 925 AST::SetLit* vsv = vs->upperBound.some(); 926 if (vsv->interval) { 927 IntSet d(vsv->min, vsv->max); 928 sv[setVarCount++] = SetVar(*this, d, d); 929 } else { 930 int* is = heap.alloc<int>(static_cast<unsigned long int>(vsv->s.size())); 931 for (int i=vsv->s.size(); i--; ) 932 is[i] = vsv->s[i]; 933 IntSet d(is, vsv->s.size()); 934 heap.free(is,static_cast<unsigned long int>(vsv->s.size())); 935 sv[setVarCount++] = SetVar(*this, d, d); 936 } 937 } else if (vs->upperBound()) { 938 AST::SetLit* vsv = vs->upperBound.some(); 939 if (vsv->interval) { 940 IntSet d(vsv->min, vsv->max); 941 sv[setVarCount++] = SetVar(*this, IntSet::empty, d); 942 } else { 943 int* is = heap.alloc<int>(static_cast<unsigned long int>(vsv->s.size())); 944 for (int i=vsv->s.size(); i--; ) 945 is[i] = vsv->s[i]; 946 IntSet d(is, vsv->s.size()); 947 heap.free(is,static_cast<unsigned long int>(vsv->s.size())); 948 sv[setVarCount++] = SetVar(*this, IntSet::empty, d); 949 } 950 } else { 951 sv[setVarCount++] = SetVar(*this, IntSet::empty, 952 IntSet(Set::Limits::min, 953 Set::Limits::max)); 954 } 955 sv_introduced[2*(setVarCount-1)] = vs->introduced; 956 sv_introduced[2*(setVarCount-1)+1] = vs->funcDep; 957 } 958#else 959 void 960 FlatZincSpace::newSetVar(SetVarSpec*) { 961 throw FlatZinc::Error("Gecode", "set variables not supported"); 962 } 963#endif 964 965#ifdef GECODE_HAS_FLOAT_VARS 966 void 967 FlatZincSpace::newFloatVar(FloatVarSpec* vs) { 968 if (vs->alias) { 969 fv[floatVarCount++] = fv[vs->i]; 970 } else { 971 double dmin, dmax; 972 if (vs->domain()) { 973 dmin = vs->domain.some().first; 974 dmax = vs->domain.some().second; 975 if (dmin > dmax) { 976 fail(); 977 return; 978 } 979 } else { 980 dmin = Float::Limits::min; 981 dmax = Float::Limits::max; 982 } 983 fv[floatVarCount++] = FloatVar(*this, dmin, dmax); 984 } 985 fv_introduced[2*(floatVarCount-1)] = vs->introduced; 986 fv_introduced[2*(floatVarCount-1)+1] = vs->funcDep; 987 } 988#else 989 void 990 FlatZincSpace::newFloatVar(FloatVarSpec*) { 991 throw FlatZinc::Error("Gecode", "float variables not supported"); 992 } 993#endif 994 995 namespace { 996 struct ConExprOrder { 997 bool operator() (ConExpr* ce0, ConExpr* ce1) { 998 return ce0->args->a.size() < ce1->args->a.size(); 999 } 1000 }; 1001 } 1002 1003 void 1004 FlatZincSpace::postConstraints(std::vector<ConExpr*>& ces) { 1005 ConExprOrder ceo; 1006 std::sort(ces.begin(), ces.end(), ceo); 1007 1008 for (unsigned int i=0; i<ces.size(); i++) { 1009 const ConExpr& ce = *ces[i]; 1010 try { 1011 registry().post(*this, ce); 1012 } catch (Gecode::Exception& e) { 1013 throw FlatZinc::Error("Gecode", e.what(), ce.ann); 1014 } catch (AST::TypeError& e) { 1015 throw FlatZinc::Error("Type error", e.what(), ce.ann); 1016 } 1017 delete ces[i]; 1018 ces[i] = nullptr; 1019 } 1020 } 1021 1022 void flattenAnnotations(AST::Array* ann, std::vector<AST::Node*>& out) { 1023 for (unsigned int i=0; i<ann->a.size(); i++) { 1024 if (ann->a[i]->isCall("seq_search")) { 1025 AST::Call* c = ann->a[i]->getCall(); 1026 if (c->args->isArray()) 1027 flattenAnnotations(c->args->getArray(), out); 1028 else 1029 out.push_back(c->args); 1030 } else { 1031 out.push_back(ann->a[i]); 1032 } 1033 } 1034 } 1035 1036 void 1037 FlatZincSpace::createBranchers(Printer&p, AST::Node* ann, FlatZincOptions& opt, 1038 bool ignoreUnknown, 1039 std::ostream& err) { 1040 int seed = opt.seed(); 1041 double decay = opt.decay(); 1042 Rnd rnd(static_cast<unsigned int>(seed)); 1043 TieBreak<IntVarBranch> def_int_varsel = INT_VAR_AFC_SIZE_MAX(0.99); 1044 IntBoolVarBranch def_intbool_varsel = INTBOOL_VAR_AFC_SIZE_MAX(0.99); 1045 IntValBranch def_int_valsel = INT_VAL_MIN(); 1046 std::string def_int_rel_left = "="; 1047 std::string def_int_rel_right = "!="; 1048 TieBreak<BoolVarBranch> def_bool_varsel = BOOL_VAR_AFC_MAX(0.99); 1049 BoolValBranch def_bool_valsel = BOOL_VAL_MIN(); 1050 std::string def_bool_rel_left = "="; 1051 std::string def_bool_rel_right = "!="; 1052#ifdef GECODE_HAS_SET_VARS 1053 SetVarBranch def_set_varsel = SET_VAR_AFC_SIZE_MAX(0.99); 1054 SetValBranch def_set_valsel = SET_VAL_MIN_INC(); 1055 std::string def_set_rel_left = "in"; 1056 std::string def_set_rel_right = "not in"; 1057#endif 1058#ifdef GECODE_HAS_FLOAT_VARS 1059 TieBreak<FloatVarBranch> def_float_varsel = FLOAT_VAR_SIZE_MIN(); 1060 FloatValBranch def_float_valsel = FLOAT_VAL_SPLIT_MIN(); 1061 std::string def_float_rel_left = "<="; 1062 std::string def_float_rel_right = ">"; 1063#endif 1064 1065 std::vector<bool> iv_searched(iv.size()); 1066 for (unsigned int i=iv.size(); i--;) 1067 iv_searched[i] = false; 1068 std::vector<bool> bv_searched(bv.size()); 1069 for (unsigned int i=bv.size(); i--;) 1070 bv_searched[i] = false; 1071#ifdef GECODE_HAS_SET_VARS 1072 std::vector<bool> sv_searched(sv.size()); 1073 for (unsigned int i=sv.size(); i--;) 1074 sv_searched[i] = false; 1075#endif 1076#ifdef GECODE_HAS_FLOAT_VARS 1077 std::vector<bool> fv_searched(fv.size()); 1078 for (unsigned int i=fv.size(); i--;) 1079 fv_searched[i] = false; 1080#endif 1081 1082 _lns = 0; 1083 if (ann) { 1084 std::vector<AST::Node*> flatAnn; 1085 if (ann->isArray()) { 1086 flattenAnnotations(ann->getArray() , flatAnn); 1087 } else { 1088 flatAnn.push_back(ann); 1089 } 1090 1091 for (unsigned int i=0; i<flatAnn.size(); i++) { 1092 if (flatAnn[i]->isCall("restart_geometric")) { 1093 AST::Call* call = flatAnn[i]->getCall("restart_geometric"); 1094 opt.restart(RM_GEOMETRIC); 1095 AST::Array* args = call->getArgs(2); 1096 opt.restart_base(args->a[0]->getFloat()); 1097 opt.restart_scale(args->a[1]->getInt()); 1098 } else if (flatAnn[i]->isCall("restart_luby")) { 1099 AST::Call* call = flatAnn[i]->getCall("restart_luby"); 1100 opt.restart(RM_LUBY); 1101 opt.restart_scale(call->args->getInt()); 1102 } else if (flatAnn[i]->isCall("restart_linear")) { 1103 AST::Call* call = flatAnn[i]->getCall("restart_linear"); 1104 opt.restart(RM_LINEAR); 1105 opt.restart_scale(call->args->getInt()); 1106 } else if (flatAnn[i]->isCall("restart_constant")) { 1107 AST::Call* call = flatAnn[i]->getCall("restart_constant"); 1108 opt.restart(RM_CONSTANT); 1109 opt.restart_scale(call->args->getInt()); 1110 } else if (flatAnn[i]->isCall("restart_none")) { 1111 opt.restart(RM_NONE); 1112 } else if (flatAnn[i]->isCall("relax_and_reconstruct")) { 1113 if (_lns != 0) 1114 throw FlatZinc::Error("FlatZinc", 1115 "Only one relax_and_reconstruct annotation allowed"); 1116 AST::Call *call = flatAnn[i]->getCall("relax_and_reconstruct"); 1117 AST::Array* args; 1118 if (call->args->getArray()->a.size()==2) { 1119 args = call->getArgs(2); 1120 } else { 1121 args = call->getArgs(3); 1122 } 1123 _lns = args->a[1]->getInt(); 1124 AST::Array *vars = args->a[0]->getArray(); 1125 int k=vars->a.size(); 1126 for (int i=vars->a.size(); i--;) 1127 if (vars->a[i]->isInt()) 1128 k--; 1129 iv_lns = IntVarArray(*this, k); 1130 k = 0; 1131 for (unsigned int i=0; i<vars->a.size(); i++) { 1132 if (vars->a[i]->isInt()) 1133 continue; 1134 iv_lns[k++] = iv[vars->a[i]->getIntVar()]; 1135 } 1136 if (args->a.size()==3) { 1137 AST::Array *initial = args->a[2]->getArray(); 1138 _lnsInitialSolution = IntSharedArray(initial->a.size()); 1139 for (unsigned int i=initial->a.size(); i--;) 1140 _lnsInitialSolution[i] = initial->a[i]->getInt(); 1141 } 1142 } else if (flatAnn[i]->isCall("gecode_search")) { 1143 AST::Call* c = flatAnn[i]->getCall(); 1144 branchWithPlugin(c->args); 1145 } else if (flatAnn[i]->isCall("int_search")) { 1146 AST::Call *call = flatAnn[i]->getCall("int_search"); 1147 AST::Array *args = call->getArgs(4); 1148 AST::Array *vars = args->a[0]->getArray(); 1149 int k=vars->a.size(); 1150 for (int i=vars->a.size(); i--;) 1151 if (vars->a[i]->isInt()) 1152 k--; 1153 IntVarArgs va(k); 1154 std::vector<std::string> names; 1155 k=0; 1156 for (unsigned int i=0; i<vars->a.size(); i++) { 1157 if (vars->a[i]->isInt()) 1158 continue; 1159 va[k++] = iv[vars->a[i]->getIntVar()]; 1160 iv_searched[vars->a[i]->getIntVar()] = true; 1161 names.push_back(vars->a[i]->getVarName()); 1162 } 1163 std::string r0, r1; 1164 { 1165 BrancherGroup bg; 1166 branch(bg(*this), va, 1167 ann2ivarsel(args->a[1],rnd,decay), 1168 ann2ivalsel(args->a[2],r0,r1,rnd), 1169 nullptr, 1170 &varValPrint<IntVar>); 1171 branchInfo.add(bg,r0,r1,names); 1172 } 1173 } else if (flatAnn[i]->isCall("int_assign")) { 1174 AST::Call *call = flatAnn[i]->getCall("int_assign"); 1175 AST::Array *args = call->getArgs(2); 1176 AST::Array *vars = args->a[0]->getArray(); 1177 int k=vars->a.size(); 1178 for (int i=vars->a.size(); i--;) 1179 if (vars->a[i]->isInt()) 1180 k--; 1181 IntVarArgs va(k); 1182 k=0; 1183 for (unsigned int i=0; i<vars->a.size(); i++) { 1184 if (vars->a[i]->isInt()) 1185 continue; 1186 va[k++] = iv[vars->a[i]->getIntVar()]; 1187 iv_searched[vars->a[i]->getIntVar()] = true; 1188 } 1189 assign(*this, va, ann2asnivalsel(args->a[1],rnd), nullptr, 1190 &varValPrint<IntVar>); 1191 } else if (flatAnn[i]->isCall("bool_search")) { 1192 AST::Call *call = flatAnn[i]->getCall("bool_search"); 1193 AST::Array *args = call->getArgs(4); 1194 AST::Array *vars = args->a[0]->getArray(); 1195 int k=vars->a.size(); 1196 for (int i=vars->a.size(); i--;) 1197 if (vars->a[i]->isBool()) 1198 k--; 1199 BoolVarArgs va(k); 1200 k=0; 1201 std::vector<std::string> names; 1202 for (unsigned int i=0; i<vars->a.size(); i++) { 1203 if (vars->a[i]->isBool()) 1204 continue; 1205 va[k++] = bv[vars->a[i]->getBoolVar()]; 1206 bv_searched[vars->a[i]->getBoolVar()] = true; 1207 names.push_back(vars->a[i]->getVarName()); 1208 } 1209 1210 std::string r0, r1; 1211 { 1212 BrancherGroup bg; 1213 branch(bg(*this), va, 1214 ann2bvarsel(args->a[1],rnd,decay), 1215 ann2bvalsel(args->a[2],r0,r1,rnd), 1216 nullptr, 1217 &varValPrint<BoolVar>); 1218 branchInfo.add(bg,r0,r1,names); 1219 } 1220 } else if (flatAnn[i]->isCall("int_default_search")) { 1221 AST::Call *call = flatAnn[i]->getCall("int_default_search"); 1222 AST::Array *args = call->getArgs(2); 1223 def_int_varsel = ann2ivarsel(args->a[0],rnd,decay); 1224 def_int_valsel = ann2ivalsel(args->a[1], 1225 def_int_rel_left,def_int_rel_right,rnd); 1226 } else if (flatAnn[i]->isCall("bool_default_search")) { 1227 AST::Call *call = flatAnn[i]->getCall("bool_default_search"); 1228 AST::Array *args = call->getArgs(2); 1229 def_bool_varsel = ann2bvarsel(args->a[0],rnd,decay); 1230 def_bool_valsel = ann2bvalsel(args->a[1], 1231 def_bool_rel_left,def_bool_rel_right, 1232 rnd); 1233 } else if (flatAnn[i]->isCall("set_search")) { 1234#ifdef GECODE_HAS_SET_VARS 1235 AST::Call *call = flatAnn[i]->getCall("set_search"); 1236 AST::Array *args = call->getArgs(4); 1237 AST::Array *vars = args->a[0]->getArray(); 1238 int k=vars->a.size(); 1239 for (int i=vars->a.size(); i--;) 1240 if (vars->a[i]->isSet()) 1241 k--; 1242 SetVarArgs va(k); 1243 k=0; 1244 std::vector<std::string> names; 1245 for (unsigned int i=0; i<vars->a.size(); i++) { 1246 if (vars->a[i]->isSet()) 1247 continue; 1248 va[k++] = sv[vars->a[i]->getSetVar()]; 1249 sv_searched[vars->a[i]->getSetVar()] = true; 1250 names.push_back(vars->a[i]->getVarName()); 1251 } 1252 std::string r0, r1; 1253 { 1254 BrancherGroup bg; 1255 branch(bg(*this), va, 1256 ann2svarsel(args->a[1],rnd,decay), 1257 ann2svalsel(args->a[2],r0,r1,rnd), 1258 nullptr, 1259 &varValPrint<SetVar>); 1260 branchInfo.add(bg,r0,r1,names); 1261 } 1262#else 1263 if (!ignoreUnknown) { 1264 err << "Warning, ignored search annotation: "; 1265 flatAnn[i]->print(err); 1266 err << std::endl; 1267 } 1268#endif 1269 } else if (flatAnn[i]->isCall("set_default_search")) { 1270#ifdef GECODE_HAS_SET_VARS 1271 AST::Call *call = flatAnn[i]->getCall("set_default_search"); 1272 AST::Array *args = call->getArgs(2); 1273 def_set_varsel = ann2svarsel(args->a[0],rnd,decay); 1274 def_set_valsel = ann2svalsel(args->a[1], 1275 def_set_rel_left,def_set_rel_right,rnd); 1276#else 1277 if (!ignoreUnknown) { 1278 err << "Warning, ignored search annotation: "; 1279 flatAnn[i]->print(err); 1280 err << std::endl; 1281 } 1282#endif 1283 } else if (flatAnn[i]->isCall("float_default_search")) { 1284#ifdef GECODE_HAS_FLOAT_VARS 1285 AST::Call *call = flatAnn[i]->getCall("float_default_search"); 1286 AST::Array *args = call->getArgs(2); 1287 def_float_varsel = ann2fvarsel(args->a[0],rnd,decay); 1288 def_float_valsel = ann2fvalsel(args->a[1], 1289 def_float_rel_left,def_float_rel_right); 1290#else 1291 if (!ignoreUnknown) { 1292 err << "Warning, ignored search annotation: "; 1293 flatAnn[i]->print(err); 1294 err << std::endl; 1295 } 1296#endif 1297 } else if (flatAnn[i]->isCall("float_search")) { 1298#ifdef GECODE_HAS_FLOAT_VARS 1299 AST::Call *call = flatAnn[i]->getCall("float_search"); 1300 AST::Array *args = call->getArgs(5); 1301 AST::Array *vars = args->a[0]->getArray(); 1302 int k=vars->a.size(); 1303 for (int i=vars->a.size(); i--;) 1304 if (vars->a[i]->isFloat()) 1305 k--; 1306 FloatVarArgs va(k); 1307 k=0; 1308 std::vector<std::string> names; 1309 for (unsigned int i=0; i<vars->a.size(); i++) { 1310 if (vars->a[i]->isFloat()) 1311 continue; 1312 va[k++] = fv[vars->a[i]->getFloatVar()]; 1313 fv_searched[vars->a[i]->getFloatVar()] = true; 1314 names.push_back(vars->a[i]->getVarName()); 1315 } 1316 std::string r0, r1; 1317 { 1318 BrancherGroup bg; 1319 branch(bg(*this), va, 1320 ann2fvarsel(args->a[2],rnd,decay), 1321 ann2fvalsel(args->a[3],r0,r1), 1322 nullptr, 1323 &varValPrintF); 1324 branchInfo.add(bg,r0,r1,names); 1325 } 1326#else 1327 if (!ignoreUnknown) { 1328 err << "Warning, ignored search annotation: "; 1329 flatAnn[i]->print(err); 1330 err << std::endl; 1331 } 1332#endif 1333 } else { 1334 if (!ignoreUnknown) { 1335 err << "Warning, ignored search annotation: "; 1336 flatAnn[i]->print(err); 1337 err << std::endl; 1338 } 1339 } 1340 } 1341 } 1342 int introduced = 0; 1343 int funcdep = 0; 1344 int searched = 0; 1345 for (int i=iv.size(); i--;) { 1346 if (iv_searched[i] || (_method != SAT && _optVarIsInt && _optVar==i)) { 1347 searched++; 1348 } else if (iv_introduced[2*i]) { 1349 if (iv_introduced[2*i+1]) { 1350 funcdep++; 1351 } else { 1352 introduced++; 1353 } 1354 } 1355 } 1356 std::vector<std::string> iv_sol_names(iv.size()-(introduced+funcdep+searched)); 1357 IntVarArgs iv_sol(iv.size()-(introduced+funcdep+searched)); 1358 std::vector<std::string> iv_tmp_names(introduced); 1359 IntVarArgs iv_tmp(introduced); 1360 for (int i=iv.size(), j=0, k=0; i--;) { 1361 if (iv_searched[i] || (_method != SAT && _optVarIsInt && _optVar==i)) 1362 continue; 1363 if (iv_introduced[2*i]) { 1364 if (!iv_introduced[2*i+1]) { 1365 iv_tmp_names[j] = p.intVarName(i); 1366 iv_tmp[j++] = iv[i]; 1367 } 1368 } else { 1369 iv_sol_names[k] = p.intVarName(i); 1370 iv_sol[k++] = iv[i]; 1371 } 1372 } 1373 1374 introduced = 0; 1375 funcdep = 0; 1376 searched = 0; 1377 for (int i=bv.size(); i--;) { 1378 if (bv_searched[i]) { 1379 searched++; 1380 } else if (bv_introduced[2*i]) { 1381 if (bv_introduced[2*i+1]) { 1382 funcdep++; 1383 } else { 1384 introduced++; 1385 } 1386 } 1387 } 1388 std::vector<std::string> bv_sol_names(bv.size()-(introduced+funcdep+searched)); 1389 BoolVarArgs bv_sol(bv.size()-(introduced+funcdep+searched)); 1390 BoolVarArgs bv_tmp(introduced); 1391 std::vector<std::string> bv_tmp_names(introduced); 1392 for (int i=bv.size(), j=0, k=0; i--;) { 1393 if (bv_searched[i]) 1394 continue; 1395 if (bv_introduced[2*i]) { 1396 if (!bv_introduced[2*i+1]) { 1397 bv_tmp_names[j] = p.boolVarName(i); 1398 bv_tmp[j++] = bv[i]; 1399 } 1400 } else { 1401 bv_sol_names[k] = p.boolVarName(i); 1402 bv_sol[k++] = bv[i]; 1403 } 1404 } 1405 1406 if (iv_sol.size() > 0 && bv_sol.size() > 0) { 1407 branch(*this, iv_sol, bv_sol, def_intbool_varsel, def_int_valsel); 1408 } else if (iv_sol.size() > 0) { 1409 BrancherGroup bg; 1410 branch(bg(*this), iv_sol, def_int_varsel, def_int_valsel, nullptr, 1411 &varValPrint<IntVar>); 1412 branchInfo.add(bg,def_int_rel_left,def_int_rel_right,iv_sol_names); 1413 } else if (bv_sol.size() > 0) { 1414 BrancherGroup bg; 1415 branch(bg(*this), bv_sol, def_bool_varsel, def_bool_valsel, nullptr, 1416 &varValPrint<BoolVar>); 1417 branchInfo.add(bg,def_bool_rel_left,def_bool_rel_right,bv_sol_names); 1418 } 1419#ifdef GECODE_HAS_FLOAT_VARS 1420 introduced = 0; 1421 funcdep = 0; 1422 searched = 0; 1423 for (int i=fv.size(); i--;) { 1424 if (fv_searched[i] || (_method != SAT && !_optVarIsInt && _optVar==i)) { 1425 searched++; 1426 } else if (fv_introduced[2*i]) { 1427 if (fv_introduced[2*i+1]) { 1428 funcdep++; 1429 } else { 1430 introduced++; 1431 } 1432 } 1433 } 1434 std::vector<std::string> fv_sol_names(fv.size()-(introduced+funcdep+searched)); 1435 FloatVarArgs fv_sol(fv.size()-(introduced+funcdep+searched)); 1436 FloatVarArgs fv_tmp(introduced); 1437 std::vector<std::string> fv_tmp_names(introduced); 1438 for (int i=fv.size(), j=0, k=0; i--;) { 1439 if (fv_searched[i] || (_method != SAT && !_optVarIsInt && _optVar==i)) 1440 continue; 1441 if (fv_introduced[2*i]) { 1442 if (!fv_introduced[2*i+1]) { 1443 fv_tmp_names[j] = p.floatVarName(i); 1444 fv_tmp[j++] = fv[i]; 1445 } 1446 } else { 1447 fv_sol_names[k] = p.floatVarName(i); 1448 fv_sol[k++] = fv[i]; 1449 } 1450 } 1451 1452 if (fv_sol.size() > 0) { 1453 BrancherGroup bg; 1454 branch(bg(*this), fv_sol, def_float_varsel, def_float_valsel, nullptr, 1455 &varValPrintF); 1456 branchInfo.add(bg,def_float_rel_left,def_float_rel_right,fv_sol_names); 1457 } 1458#endif 1459#ifdef GECODE_HAS_SET_VARS 1460 introduced = 0; 1461 funcdep = 0; 1462 searched = 0; 1463 for (int i=sv.size(); i--;) { 1464 if (sv_searched[i]) { 1465 searched++; 1466 } else if (sv_introduced[2*i]) { 1467 if (sv_introduced[2*i+1]) { 1468 funcdep++; 1469 } else { 1470 introduced++; 1471 } 1472 } 1473 } 1474 std::vector<std::string> sv_sol_names(sv.size()-(introduced+funcdep+searched)); 1475 SetVarArgs sv_sol(sv.size()-(introduced+funcdep+searched)); 1476 SetVarArgs sv_tmp(introduced); 1477 std::vector<std::string> sv_tmp_names(introduced); 1478 for (int i=sv.size(), j=0, k=0; i--;) { 1479 if (sv_searched[i]) 1480 continue; 1481 if (sv_introduced[2*i]) { 1482 if (!sv_introduced[2*i+1]) { 1483 sv_tmp_names[j] = p.setVarName(i); 1484 sv_tmp[j++] = sv[i]; 1485 } 1486 } else { 1487 sv_sol_names[k] = p.setVarName(i); 1488 sv_sol[k++] = sv[i]; 1489 } 1490 } 1491 1492 if (sv_sol.size() > 0) { 1493 BrancherGroup bg; 1494 branch(bg(*this), sv_sol, def_set_varsel, def_set_valsel, nullptr, 1495 &varValPrint<SetVar>); 1496 branchInfo.add(bg,def_set_rel_left,def_set_rel_right,sv_sol_names); 1497 1498 } 1499#endif 1500 iv_aux = IntVarArray(*this, iv_tmp); 1501 bv_aux = BoolVarArray(*this, bv_tmp); 1502 int n_aux = iv_aux.size() + bv_aux.size(); 1503#ifdef GECODE_HAS_SET_VARS 1504 sv_aux = SetVarArray(*this, sv_tmp); 1505 n_aux += sv_aux.size(); 1506#endif 1507#ifdef GECODE_HAS_FLOAT_VARS 1508 fv_aux = FloatVarArray(*this, fv_tmp); 1509 n_aux += fv_aux.size(); 1510#endif 1511 1512 if (n_aux > 0) { 1513 if (_method == SAT) { 1514 AuxVarBrancher::post(*this, def_int_varsel, def_int_valsel, 1515 def_bool_varsel, def_bool_valsel 1516#ifdef GECODE_HAS_SET_VARS 1517 , def_set_varsel, def_set_valsel 1518#endif 1519#ifdef GECODE_HAS_FLOAT_VARS 1520 , def_float_varsel, def_float_valsel 1521#endif 1522 ); 1523 } else { 1524 { 1525 BrancherGroup bg; 1526 branch(bg(*this),iv_aux,def_int_varsel,def_int_valsel, nullptr, 1527 &varValPrint<IntVar>); 1528 branchInfo.add(bg,def_int_rel_left,def_int_rel_right,iv_tmp_names); 1529 } 1530 { 1531 BrancherGroup bg; 1532 branch(bg(*this),bv_aux,def_bool_varsel,def_bool_valsel, nullptr, 1533 &varValPrint<BoolVar>); 1534 branchInfo.add(bg,def_bool_rel_left,def_bool_rel_right,bv_tmp_names); 1535 } 1536 #ifdef GECODE_HAS_SET_VARS 1537 { 1538 BrancherGroup bg; 1539 branch(bg(*this),sv_aux,def_set_varsel,def_set_valsel, nullptr, 1540 &varValPrint<SetVar>); 1541 branchInfo.add(bg,def_set_rel_left,def_set_rel_right,sv_tmp_names); 1542 } 1543 #endif 1544 #ifdef GECODE_HAS_FLOAT_VARS 1545 { 1546 BrancherGroup bg; 1547 branch(bg(*this),fv_aux,def_float_varsel,def_float_valsel, nullptr, 1548 &varValPrintF); 1549 branchInfo.add(bg,def_float_rel_left,def_float_rel_right,fv_tmp_names); 1550 } 1551 #endif 1552 1553 } 1554 } 1555 1556 if (_method == MIN) { 1557 if (_optVarIsInt) { 1558 std::vector<std::string> names(1); 1559 names[0] = p.intVarName(_optVar); 1560 BrancherGroup bg; 1561 branch(bg(*this), iv[_optVar], INT_VAL_MIN(), 1562 &varValPrint<IntVar>); 1563 branchInfo.add(bg,"=","!=",names); 1564 } else { 1565#ifdef GECODE_HAS_FLOAT_VARS 1566 std::vector<std::string> names(1); 1567 names[0] = p.floatVarName(_optVar); 1568 BrancherGroup bg; 1569 branch(bg(*this), fv[_optVar], FLOAT_VAL_SPLIT_MIN(), 1570 &varValPrintF); 1571 branchInfo.add(bg,"<=",">",names); 1572#endif 1573 } 1574 } else if (_method == MAX) { 1575 if (_optVarIsInt) { 1576 std::vector<std::string> names(1); 1577 names[0] = p.intVarName(_optVar); 1578 BrancherGroup bg; 1579 branch(bg(*this), iv[_optVar], INT_VAL_MAX(), 1580 &varValPrint<IntVar>); 1581 branchInfo.add(bg,"=","!=",names); 1582 } else { 1583#ifdef GECODE_HAS_FLOAT_VARS 1584 std::vector<std::string> names(1); 1585 names[0] = p.floatVarName(_optVar); 1586 BrancherGroup bg; 1587 branch(bg(*this), fv[_optVar], FLOAT_VAL_SPLIT_MAX(), 1588 &varValPrintF); 1589 branchInfo.add(bg,"<=",">",names); 1590#endif 1591 } 1592 } 1593 1594 } 1595 1596 AST::Array* 1597 FlatZincSpace::solveAnnotations(void) const { 1598 return _solveAnnotations; 1599 } 1600 1601 void 1602 FlatZincSpace::solve(AST::Array* ann) { 1603 _method = SAT; 1604 _solveAnnotations = ann; 1605 } 1606 1607 void 1608 FlatZincSpace::minimize(int var, bool isInt, AST::Array* ann) { 1609 _method = MIN; 1610 _optVar = var; 1611 _optVarIsInt = isInt; 1612 _solveAnnotations = ann; 1613 } 1614 1615 void 1616 FlatZincSpace::maximize(int var, bool isInt, AST::Array* ann) { 1617 _method = MAX; 1618 _optVar = var; 1619 _optVarIsInt = isInt; 1620 _solveAnnotations = ann; 1621 } 1622 1623 FlatZincSpace::~FlatZincSpace(void) { 1624 delete _initData; 1625 delete _solveAnnotations; 1626 } 1627 1628#ifdef GECODE_HAS_GIST 1629 1630 /** 1631 * \brief Traits class for search engines 1632 */ 1633 template<class Engine> 1634 class GistEngine { 1635 }; 1636 1637 /// Specialization for DFS 1638 template<typename S> 1639 class GistEngine<DFS<S> > { 1640 public: 1641 static void explore(S* root, const FlatZincOptions& opt, 1642 Gist::Inspector* i, Gist::Comparator* c) { 1643 Gecode::Gist::Options o; 1644 o.c_d = opt.c_d(); o.a_d = opt.a_d(); 1645 o.inspect.click(i); 1646 o.inspect.compare(c); 1647 (void) Gecode::Gist::dfs(root, o); 1648 } 1649 }; 1650 1651 /// Specialization for BAB 1652 template<typename S> 1653 class GistEngine<BAB<S> > { 1654 public: 1655 static void explore(S* root, const FlatZincOptions& opt, 1656 Gist::Inspector* i, Gist::Comparator* c) { 1657 Gecode::Gist::Options o; 1658 o.c_d = opt.c_d(); o.a_d = opt.a_d(); 1659 o.inspect.click(i); 1660 o.inspect.compare(c); 1661 (void) Gecode::Gist::bab(root, o); 1662 } 1663 }; 1664 1665 /// \brief An inspector for printing simple text output 1666 template<class S> 1667 class FZPrintingInspector 1668 : public Gecode::Gist::TextOutput, public Gecode::Gist::Inspector { 1669 private: 1670 const Printer& p; 1671 public: 1672 /// Constructor 1673 FZPrintingInspector(const Printer& p0); 1674 /// Use the print method of the template class S to print a space 1675 virtual void inspect(const Space& node); 1676 /// Finalize when Gist exits 1677 virtual void finalize(void); 1678 }; 1679 1680 template<class S> 1681 FZPrintingInspector<S>::FZPrintingInspector(const Printer& p0) 1682 : TextOutput("Gecode/FlatZinc"), p(p0) {} 1683 1684 template<class S> 1685 void 1686 FZPrintingInspector<S>::inspect(const Space& node) { 1687 init(); 1688 dynamic_cast<const S&>(node).print(getStream(), p); 1689 getStream() << std::endl; 1690 } 1691 1692 template<class S> 1693 void 1694 FZPrintingInspector<S>::finalize(void) { 1695 Gecode::Gist::TextOutput::finalize(); 1696 } 1697 1698 template<class S> 1699 class FZPrintingComparator 1700 : public Gecode::Gist::VarComparator<S> { 1701 private: 1702 const Printer& p; 1703 public: 1704 /// Constructor 1705 FZPrintingComparator(const Printer& p0); 1706 1707 /// Use the compare method of the template class S to compare two spaces 1708 virtual void compare(const Space& s0, const Space& s1); 1709 }; 1710 1711 template<class S> 1712 FZPrintingComparator<S>::FZPrintingComparator(const Printer& p0) 1713 : Gecode::Gist::VarComparator<S>("Gecode/FlatZinc"), p(p0) {} 1714 1715 template<class S> 1716 void 1717 FZPrintingComparator<S>::compare(const Space& s0, const Space& s1) { 1718 this->init(); 1719 try { 1720 dynamic_cast<const S&>(s0).compare(dynamic_cast<const S&>(s1), 1721 this->getStream(), p); 1722 } catch (Exception& e) { 1723 this->getStream() << "Exception: " << e.what(); 1724 } 1725 this->getStream() << std::endl; 1726 } 1727 1728#endif 1729 1730 template<template<class> class Engine> 1731 void 1732 FlatZincSpace::runEngine(std::ostream& out, const Printer& p, 1733 const FlatZincOptions& opt, Support::Timer& t_total) { 1734 if (opt.restart()==RM_NONE) { 1735 runMeta<Engine,Driver::EngineToMeta>(out,p,opt,t_total); 1736 } else { 1737 runMeta<Engine,RBS>(out,p,opt,t_total); 1738 } 1739 } 1740 1741#ifdef GECODE_HAS_CPPROFILER 1742 1743 class FlatZincGetInfo : public CPProfilerSearchTracer::GetInfo { 1744 public: 1745 const Printer& p; 1746 FlatZincGetInfo(const Printer& printer) : p(printer) {} 1747 virtual std::string 1748 getInfo(const Space& space) const { 1749 std::stringstream ss; 1750 if (const FlatZincSpace* fz_space = dynamic_cast<const FlatZincSpace*>(&space)) { 1751 ss << "{\n\t\"domains\": \""; 1752 ss << fz_space->getDomains(p); 1753 ss << "\"\n}"; 1754 } 1755 return ss.str(); 1756 } 1757 ~FlatZincGetInfo(void) {}; 1758 }; 1759 1760 void printIntVar(std::ostream& os, const std::string name, const Int::IntView& x) { 1761 os << "var "; 1762 if (x.assigned()) { 1763 os << "int: " << name << " = " << x.val() << ";"; 1764 } else if (x.range()) { 1765 os << x.min() << ".." << x.max() << ": " << name << ";"; 1766 } else { 1767 os << "array_union(["; 1768 Gecode::Int::ViewRanges<Int::IntView> r(x); 1769 while (true) { 1770 os << r.min() << ".." << r.max(); 1771 ++r; 1772 if (!r()) break; 1773 os << ','; 1774 } 1775 os << "]): " << name << ";"; 1776 } 1777 os << "\n"; 1778 } 1779 void printBoolVar(std::ostream& os, const std::string name, const BoolVar& b) { 1780 os << "var bool: " << name; 1781 if(b.assigned()) 1782 os << " = " << (b.val() ? "true" : "false"); 1783 os << ";\n"; 1784 } 1785#ifdef GECODE_HAS_FLOAT_VARS 1786 void printFloatVar(std::ostream& os, const std::string name, const Float::FloatView& f) { 1787 os << "var "; 1788 if(f.assigned()) 1789 os << "float: " << name << " = " << f.med() << ";"; 1790 else 1791 os << f.min() << ".." << f.max() << ": " << name << ";"; 1792 os << "\n"; 1793 } 1794#endif 1795 std::string FlatZincSpace::getDomains(const Printer& p) const { 1796 std::ostringstream oss; 1797 1798 for (int i = 0; i < iv.size(); i++) 1799 printIntVar(oss, p.intVarName(i), iv[i]); 1800 1801 for (int i = 0; i < bv.size(); i++) 1802 printBoolVar(oss, p.boolVarName(i), bv[i]); 1803 1804#ifdef GECODE_HAS_FLOAT_VARS 1805 for (int i = 0; i < fv.size(); i++) 1806 printFloatVar(oss, p.floatVarName(i), fv[i]); 1807#endif 1808#ifdef GECODE_HAS_SET_VARS 1809 for (int i = 0; i < sv.size(); i++) 1810 oss << "var " << sv[i] << ": " << p.setVarName(i) << ";" << std::endl; 1811#endif 1812 1813 return oss.str(); 1814 } 1815 1816#endif 1817 1818 template<template<class> class Engine, 1819 template<class,template<class> class> class Meta> 1820 void 1821 FlatZincSpace::runMeta(std::ostream& out, const Printer& p, 1822 const FlatZincOptions& opt, Support::Timer& t_total) { 1823#ifdef GECODE_HAS_GIST 1824 if (opt.mode() == SM_GIST) { 1825 FZPrintingInspector<FlatZincSpace> pi(p); 1826 FZPrintingComparator<FlatZincSpace> pc(p); 1827 (void) GistEngine<Engine<FlatZincSpace> >::explore(this,opt,&pi,&pc); 1828 return; 1829 } 1830#endif 1831 StatusStatistics sstat; 1832 unsigned int n_p = 0; 1833 Support::Timer t_solve; 1834 t_solve.start(); 1835 if (status(sstat) != SS_FAILED) { 1836 n_p = PropagatorGroup::all.size(*this); 1837 } 1838 Search::Options o; 1839 o.stop = Driver::CombinedStop::create(opt.node(), opt.fail(), opt.time(), 1840 true); 1841 o.c_d = opt.c_d(); 1842 o.a_d = opt.a_d(); 1843 1844#ifdef GECODE_HAS_CPPROFILER 1845 if (opt.profiler_port()) { 1846 FlatZincGetInfo* getInfo = nullptr; 1847 if (opt.profiler_info()) 1848 getInfo = new FlatZincGetInfo(p); 1849 o.tracer = new CPProfilerSearchTracer(opt.profiler_id(), 1850 opt.name(), opt.profiler_port(), 1851 getInfo); 1852 } 1853 1854#endif 1855 1856#ifdef GECODE_HAS_FLOAT_VARS 1857 step = opt.step(); 1858#endif 1859 o.threads = opt.threads(); 1860 o.nogoods_limit = opt.nogoods() ? opt.nogoods_limit() : 0; 1861 o.cutoff = new Search::CutoffAppend(new Search::CutoffConstant(0), 1, Driver::createCutoff(opt)); 1862 if (opt.interrupt()) 1863 Driver::CombinedStop::installCtrlHandler(true); 1864 { 1865 Meta<FlatZincSpace,Engine> se(this,o); 1866 int noOfSolutions = opt.solutions(); 1867 if (noOfSolutions == -1) { 1868 noOfSolutions = (_method == SAT) ? 1 : 0; 1869 } 1870 bool printAll = _method == SAT || opt.allSolutions() || noOfSolutions != 0; 1871 int findSol = noOfSolutions; 1872 FlatZincSpace* sol = nullptr; 1873 while (FlatZincSpace* next_sol = se.next()) { 1874 delete sol; 1875 sol = next_sol; 1876 if (printAll) { 1877 sol->print(out, p); 1878 out << "----------" << std::endl; 1879 } 1880 if (--findSol==0) 1881 goto stopped; 1882 } 1883 if (sol && !printAll) { 1884 sol->print(out, p); 1885 out << "----------" << std::endl; 1886 } 1887 if (!se.stopped()) { 1888 if (sol) { 1889 out << "==========" << std::endl; 1890 } else { 1891 out << "=====UNSATISFIABLE=====" << std::endl; 1892 } 1893 } else if (!sol) { 1894 out << "=====UNKNOWN=====" << std::endl; 1895 } 1896 delete sol; 1897 stopped: 1898 if (opt.interrupt()) 1899 Driver::CombinedStop::installCtrlHandler(false); 1900 if (opt.mode() == SM_STAT) { 1901 Gecode::Search::Statistics stat = se.statistics(); 1902 double totalTime = (t_total.stop() / 1000.0); 1903 double solveTime = (t_solve.stop() / 1000.0); 1904 double initTime = totalTime - solveTime; 1905 out << std::endl 1906 << "%%%mzn-stat: initTime=" << initTime 1907 << std::endl; 1908 out << "%%%mzn-stat: solveTime=" << solveTime 1909 << std::endl; 1910 out << "%%%mzn-stat: solutions=" 1911 << std::abs(noOfSolutions - findSol) << std::endl 1912 << "%%%mzn-stat: variables=" 1913 << (intVarCount + boolVarCount + setVarCount) << std::endl 1914 << "%%%mzn-stat: propagators=" << n_p << std::endl 1915 << "%%%mzn-stat: propagations=" << sstat.propagate+stat.propagate << std::endl 1916 << "%%%mzn-stat: nodes=" << stat.node << std::endl 1917 << "%%%mzn-stat: failures=" << stat.fail << std::endl 1918 << "%%%mzn-stat: restarts=" << stat.restart << std::endl 1919 << "%%%mzn-stat: peakDepth=" << stat.depth << std::endl 1920 << "%%%mzn-stat-end" << std::endl 1921 << std::endl; 1922 } 1923 } 1924 delete o.stop; 1925 delete o.tracer; 1926 } 1927 1928#ifdef GECODE_HAS_QT 1929 void 1930 FlatZincSpace::branchWithPlugin(AST::Node* ann) { 1931 if (AST::Call* c = dynamic_cast<AST::Call*>(ann)) { 1932 QString pluginName(c->id.c_str()); 1933 if (QLibrary::isLibrary(pluginName+".dll")) { 1934 pluginName += ".dll"; 1935 } else if (QLibrary::isLibrary(pluginName+".dylib")) { 1936 pluginName = "lib" + pluginName + ".dylib"; 1937 } else if (QLibrary::isLibrary(pluginName+".so")) { 1938 // Must check .so after .dylib so that Mac OS uses .dylib 1939 pluginName = "lib" + pluginName + ".so"; 1940 } 1941 QPluginLoader pl(pluginName); 1942 QObject* plugin_o = pl.instance(); 1943 if (!plugin_o) { 1944 throw FlatZinc::Error("FlatZinc", 1945 "Error loading plugin "+pluginName.toStdString()+ 1946 ": "+pl.errorString().toStdString()); 1947 } 1948 BranchPlugin* pb = qobject_cast<BranchPlugin*>(plugin_o); 1949 if (!pb) { 1950 throw FlatZinc::Error("FlatZinc", 1951 "Error loading plugin "+pluginName.toStdString()+ 1952 ": does not contain valid PluginBrancher"); 1953 } 1954 pb->branch(*this, c); 1955 } 1956 } 1957#else 1958 void 1959 FlatZincSpace::branchWithPlugin(AST::Node*) { 1960 throw FlatZinc::Error("FlatZinc", 1961 "Branching with plugins not supported (requires Qt support)"); 1962 } 1963#endif 1964 1965 void 1966 FlatZincSpace::run(std::ostream& out, const Printer& p, 1967 const FlatZincOptions& opt, Support::Timer& t_total) { 1968 switch (_method) { 1969 case MIN: 1970 case MAX: 1971 runEngine<BAB>(out,p,opt,t_total); 1972 break; 1973 case SAT: 1974 runEngine<DFS>(out,p,opt,t_total); 1975 break; 1976 } 1977 } 1978 1979 void 1980 FlatZincSpace::constrain(const Space& s) { 1981 if (_optVarIsInt) { 1982 if (_method == MIN) 1983 rel(*this, iv[_optVar], IRT_LE, 1984 static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val()); 1985 else if (_method == MAX) 1986 rel(*this, iv[_optVar], IRT_GR, 1987 static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val()); 1988 } else { 1989#ifdef GECODE_HAS_FLOAT_VARS 1990 if (_method == MIN) 1991 rel(*this, fv[_optVar], FRT_LE, 1992 static_cast<const FlatZincSpace*>(&s)->fv[_optVar].val()-step); 1993 else if (_method == MAX) 1994 rel(*this, fv[_optVar], FRT_GR, 1995 static_cast<const FlatZincSpace*>(&s)->fv[_optVar].val()+step); 1996#endif 1997 } 1998 } 1999 2000 bool 2001 FlatZincSpace::slave(const MetaInfo& mi) { 2002 if ((mi.type() == MetaInfo::RESTART) && (mi.restart() != 0) && 2003 (_lns > 0) && (mi.last()==nullptr) && (_lnsInitialSolution.size()>0)) { 2004 for (unsigned int i=iv_lns.size(); i--;) { 2005 if (_random(99U) <= _lns) { 2006 rel(*this, iv_lns[i], IRT_EQ, _lnsInitialSolution[i]); 2007 } 2008 } 2009 return false; 2010 } else if ((mi.type() == MetaInfo::RESTART) && (mi.restart() != 0) && 2011 (_lns > 0) && mi.last()) { 2012 const FlatZincSpace& last = 2013 static_cast<const FlatZincSpace&>(*mi.last()); 2014 for (unsigned int i=iv_lns.size(); i--;) { 2015 if (_random(99U) <= _lns) { 2016 rel(*this, iv_lns[i], IRT_EQ, last.iv_lns[i]); 2017 } 2018 } 2019 return false; 2020 } 2021 return true; 2022 } 2023 2024 Space* 2025 FlatZincSpace::copy(void) { 2026 return new FlatZincSpace(*this); 2027 } 2028 2029 FlatZincSpace::Meth 2030 FlatZincSpace::method(void) const { 2031 return _method; 2032 } 2033 2034 int 2035 FlatZincSpace::optVar(void) const { 2036 return _optVar; 2037 } 2038 2039 bool 2040 FlatZincSpace::optVarIsInt(void) const { 2041 return _optVarIsInt; 2042 } 2043 2044 void 2045 FlatZincSpace::print(std::ostream& out, const Printer& p) const { 2046 p.print(out, iv, bv 2047#ifdef GECODE_HAS_SET_VARS 2048 , sv 2049#endif 2050#ifdef GECODE_HAS_FLOAT_VARS 2051 , fv 2052#endif 2053 ); 2054 } 2055 2056 void 2057 FlatZincSpace::compare(const Space& s, std::ostream& out) const { 2058 (void) s; (void) out; 2059#ifdef GECODE_HAS_GIST 2060 const FlatZincSpace& fs = dynamic_cast<const FlatZincSpace&>(s); 2061 for (int i = 0; i < iv.size(); ++i) { 2062 std::stringstream ss; 2063 ss << "iv[" << i << "]"; 2064 std::string result(Gecode::Gist::Comparator::compare(ss.str(), iv[i], 2065 fs.iv[i])); 2066 if (result.length() > 0) out << result << std::endl; 2067 } 2068 for (int i = 0; i < bv.size(); ++i) { 2069 std::stringstream ss; 2070 ss << "bv[" << i << "]"; 2071 std::string result(Gecode::Gist::Comparator::compare(ss.str(), bv[i], 2072 fs.bv[i])); 2073 if (result.length() > 0) out << result << std::endl; 2074 } 2075#ifdef GECODE_HAS_SET_VARS 2076 for (int i = 0; i < sv.size(); ++i) { 2077 std::stringstream ss; 2078 ss << "sv[" << i << "]"; 2079 std::string result(Gecode::Gist::Comparator::compare(ss.str(), sv[i], 2080 fs.sv[i])); 2081 if (result.length() > 0) out << result << std::endl; 2082 } 2083#endif 2084#ifdef GECODE_HAS_FLOAT_VARS 2085 for (int i = 0; i < fv.size(); ++i) { 2086 std::stringstream ss; 2087 ss << "fv[" << i << "]"; 2088 std::string result(Gecode::Gist::Comparator::compare(ss.str(), fv[i], 2089 fs.fv[i])); 2090 if (result.length() > 0) out << result << std::endl; 2091 } 2092#endif 2093#endif 2094 } 2095 2096 void 2097 FlatZincSpace::compare(const FlatZincSpace& s, std::ostream& out, 2098 const Printer& p) const { 2099 p.printDiff(out, iv, s.iv, bv, s.bv 2100#ifdef GECODE_HAS_SET_VARS 2101 , sv, s.sv 2102#endif 2103#ifdef GECODE_HAS_FLOAT_VARS 2104 , fv, s.fv 2105#endif 2106 ); 2107 } 2108 2109 void 2110 FlatZincSpace::shrinkArrays(Printer& p) { 2111 p.shrinkArrays(*this, _optVar, _optVarIsInt, iv, bv 2112#ifdef GECODE_HAS_SET_VARS 2113 , sv 2114#endif 2115#ifdef GECODE_HAS_FLOAT_VARS 2116 , fv 2117#endif 2118 ); 2119 } 2120 2121 IntArgs 2122 FlatZincSpace::arg2intargs(AST::Node* arg, int offset) { 2123 AST::Array* a = arg->getArray(); 2124 IntArgs ia(a->a.size()+offset); 2125 for (int i=offset; i--;) 2126 ia[i] = 0; 2127 for (int i=a->a.size(); i--;) 2128 ia[i+offset] = a->a[i]->getInt(); 2129 return ia; 2130 } 2131 TupleSet 2132 FlatZincSpace::arg2tupleset(const IntArgs& a, int noOfVars) { 2133 int noOfTuples = a.size() == 0 ? 0 : (a.size()/noOfVars); 2134 2135 // Build TupleSet 2136 TupleSet ts(noOfVars); 2137 for (int i=0; i<noOfTuples; i++) { 2138 IntArgs t(noOfVars); 2139 for (int j=0; j<noOfVars; j++) { 2140 t[j] = a[i*noOfVars+j]; 2141 } 2142 ts.add(t); 2143 } 2144 ts.finalize(); 2145 2146 if (_initData) { 2147 FlatZincSpaceInitData::TupleSetSet::iterator it = _initData->tupleSetSet.find(ts); 2148 if (it != _initData->tupleSetSet.end()) { 2149 return *it; 2150 } 2151 _initData->tupleSetSet.insert(ts); 2152 } 2153 2154 2155 return ts; 2156 } 2157 IntSharedArray 2158 FlatZincSpace::arg2intsharedarray(AST::Node* arg, int offset) { 2159 IntArgs ia(arg2intargs(arg,offset)); 2160 SharedArray<int> sia(ia); 2161 if (_initData) { 2162 FlatZincSpaceInitData::IntSharedArraySet::iterator it = _initData->intSharedArraySet.find(sia); 2163 if (it != _initData->intSharedArraySet.end()) { 2164 return *it; 2165 } 2166 _initData->intSharedArraySet.insert(sia); 2167 } 2168 2169 return sia; 2170 } 2171 IntArgs 2172 FlatZincSpace::arg2boolargs(AST::Node* arg, int offset) { 2173 AST::Array* a = arg->getArray(); 2174 IntArgs ia(a->a.size()+offset); 2175 for (int i=offset; i--;) 2176 ia[i] = 0; 2177 for (int i=a->a.size(); i--;) 2178 ia[i+offset] = a->a[i]->getBool(); 2179 return ia; 2180 } 2181 IntSharedArray 2182 FlatZincSpace::arg2boolsharedarray(AST::Node* arg, int offset) { 2183 IntArgs ia(arg2boolargs(arg,offset)); 2184 SharedArray<int> sia(ia); 2185 if (_initData) { 2186 FlatZincSpaceInitData::IntSharedArraySet::iterator it = _initData->intSharedArraySet.find(sia); 2187 if (it != _initData->intSharedArraySet.end()) { 2188 return *it; 2189 } 2190 _initData->intSharedArraySet.insert(sia); 2191 } 2192 2193 return sia; 2194 } 2195 IntSet 2196 FlatZincSpace::arg2intset(AST::Node* n) { 2197 AST::SetLit* sl = n->getSet(); 2198 IntSet d; 2199 if (sl->interval) { 2200 d = IntSet(sl->min, sl->max); 2201 } else { 2202 Region re; 2203 int* is = re.alloc<int>(static_cast<unsigned long int>(sl->s.size())); 2204 for (int i=sl->s.size(); i--; ) 2205 is[i] = sl->s[i]; 2206 d = IntSet(is, sl->s.size()); 2207 } 2208 return d; 2209 } 2210 IntSetArgs 2211 FlatZincSpace::arg2intsetargs(AST::Node* arg, int offset) { 2212 AST::Array* a = arg->getArray(); 2213 if (a->a.size() == 0) { 2214 IntSetArgs emptyIa(0); 2215 return emptyIa; 2216 } 2217 IntSetArgs ia(a->a.size()+offset); 2218 for (int i=offset; i--;) 2219 ia[i] = IntSet::empty; 2220 for (int i=a->a.size(); i--;) { 2221 ia[i+offset] = arg2intset(a->a[i]); 2222 } 2223 return ia; 2224 } 2225 IntVarArgs 2226 FlatZincSpace::arg2intvarargs(AST::Node* arg, int offset) { 2227 AST::Array* a = arg->getArray(); 2228 if (a->a.size() == 0) { 2229 IntVarArgs emptyIa(0); 2230 return emptyIa; 2231 } 2232 IntVarArgs ia(a->a.size()+offset); 2233 for (int i=offset; i--;) 2234 ia[i] = IntVar(*this, 0, 0); 2235 for (int i=a->a.size(); i--;) { 2236 if (a->a[i]->isIntVar()) { 2237 ia[i+offset] = iv[a->a[i]->getIntVar()]; 2238 } else { 2239 int value = a->a[i]->getInt(); 2240 IntVar iv(*this, value, value); 2241 ia[i+offset] = iv; 2242 } 2243 } 2244 return ia; 2245 } 2246 BoolVarArgs 2247 FlatZincSpace::arg2boolvarargs(AST::Node* arg, int offset, int siv) { 2248 AST::Array* a = arg->getArray(); 2249 if (a->a.size() == 0) { 2250 BoolVarArgs emptyIa(0); 2251 return emptyIa; 2252 } 2253 BoolVarArgs ia(a->a.size()+offset-(siv==-1?0:1)); 2254 for (int i=offset; i--;) 2255 ia[i] = BoolVar(*this, 0, 0); 2256 for (int i=0; i<static_cast<int>(a->a.size()); i++) { 2257 if (i==siv) 2258 continue; 2259 if (a->a[i]->isBool()) { 2260 bool value = a->a[i]->getBool(); 2261 BoolVar iv(*this, value, value); 2262 ia[offset++] = iv; 2263 } else if (a->a[i]->isIntVar() && 2264 aliasBool2Int(a->a[i]->getIntVar()) != -1) { 2265 ia[offset++] = bv[aliasBool2Int(a->a[i]->getIntVar())]; 2266 } else { 2267 ia[offset++] = bv[a->a[i]->getBoolVar()]; 2268 } 2269 } 2270 return ia; 2271 } 2272 BoolVar 2273 FlatZincSpace::arg2BoolVar(AST::Node* n) { 2274 BoolVar x0; 2275 if (n->isBool()) { 2276 x0 = BoolVar(*this, n->getBool(), n->getBool()); 2277 } 2278 else { 2279 x0 = bv[n->getBoolVar()]; 2280 } 2281 return x0; 2282 } 2283 IntVar 2284 FlatZincSpace::arg2IntVar(AST::Node* n) { 2285 IntVar x0; 2286 if (n->isIntVar()) { 2287 x0 = iv[n->getIntVar()]; 2288 } else { 2289 x0 = IntVar(*this, n->getInt(), n->getInt()); 2290 } 2291 return x0; 2292 } 2293 bool 2294 FlatZincSpace::isBoolArray(AST::Node* b, int& singleInt) { 2295 AST::Array* a = b->getArray(); 2296 singleInt = -1; 2297 if (a->a.size() == 0) 2298 return true; 2299 for (int i=a->a.size(); i--;) { 2300 if (a->a[i]->isBoolVar() || a->a[i]->isBool()) { 2301 } else if (a->a[i]->isIntVar()) { 2302 if (aliasBool2Int(a->a[i]->getIntVar()) == -1) { 2303 if (singleInt != -1) { 2304 return false; 2305 } 2306 singleInt = i; 2307 } 2308 } else { 2309 return false; 2310 } 2311 } 2312 return singleInt==-1 || a->a.size() > 1; 2313 } 2314#ifdef GECODE_HAS_SET_VARS 2315 SetVar 2316 FlatZincSpace::arg2SetVar(AST::Node* n) { 2317 SetVar x0; 2318 if (!n->isSetVar()) { 2319 IntSet d = arg2intset(n); 2320 x0 = SetVar(*this, d, d); 2321 } else { 2322 x0 = sv[n->getSetVar()]; 2323 } 2324 return x0; 2325 } 2326 SetVarArgs 2327 FlatZincSpace::arg2setvarargs(AST::Node* arg, int offset, int doffset, 2328 const IntSet& od) { 2329 AST::Array* a = arg->getArray(); 2330 SetVarArgs ia(a->a.size()+offset); 2331 for (int i=offset; i--;) { 2332 IntSet d = i<doffset ? od : IntSet::empty; 2333 ia[i] = SetVar(*this, d, d); 2334 } 2335 for (int i=a->a.size(); i--;) { 2336 ia[i+offset] = arg2SetVar(a->a[i]); 2337 } 2338 return ia; 2339 } 2340#endif 2341#ifdef GECODE_HAS_FLOAT_VARS 2342 FloatValArgs 2343 FlatZincSpace::arg2floatargs(AST::Node* arg, int offset) { 2344 AST::Array* a = arg->getArray(); 2345 FloatValArgs fa(a->a.size()+offset); 2346 for (int i=offset; i--;) 2347 fa[i] = 0.0; 2348 for (int i=a->a.size(); i--;) 2349 fa[i+offset] = a->a[i]->getFloat(); 2350 return fa; 2351 } 2352 FloatVarArgs 2353 FlatZincSpace::arg2floatvarargs(AST::Node* arg, int offset) { 2354 AST::Array* a = arg->getArray(); 2355 if (a->a.size() == 0) { 2356 FloatVarArgs emptyFa(0); 2357 return emptyFa; 2358 } 2359 FloatVarArgs fa(a->a.size()+offset); 2360 for (int i=offset; i--;) 2361 fa[i] = FloatVar(*this, 0.0, 0.0); 2362 for (int i=a->a.size(); i--;) { 2363 if (a->a[i]->isFloatVar()) { 2364 fa[i+offset] = fv[a->a[i]->getFloatVar()]; 2365 } else { 2366 double value = a->a[i]->getFloat(); 2367 FloatVar fv(*this, value, value); 2368 fa[i+offset] = fv; 2369 } 2370 } 2371 return fa; 2372 } 2373 FloatVar 2374 FlatZincSpace::arg2FloatVar(AST::Node* n) { 2375 FloatVar x0; 2376 if (n->isFloatVar()) { 2377 x0 = fv[n->getFloatVar()]; 2378 } else { 2379 x0 = FloatVar(*this, n->getFloat(), n->getFloat()); 2380 } 2381 return x0; 2382 } 2383#endif 2384 IntPropLevel 2385 FlatZincSpace::ann2ipl(AST::Node* ann) { 2386 if (ann) { 2387 if (ann->hasAtom("val")) 2388 return IPL_VAL; 2389 if (ann->hasAtom("domain")) 2390 return IPL_DOM; 2391 if (ann->hasAtom("bounds") || 2392 ann->hasAtom("boundsR") || 2393 ann->hasAtom("boundsD") || 2394 ann->hasAtom("boundsZ")) 2395 return IPL_BND; 2396 } 2397 return IPL_DEF; 2398 } 2399 2400 DFA 2401 FlatZincSpace::getSharedDFA(DFA& a) { 2402 if (_initData) { 2403 FlatZincSpaceInitData::DFASet::iterator it = _initData->dfaSet.find(a); 2404 if (it != _initData->dfaSet.end()) { 2405 return *it; 2406 } 2407 _initData->dfaSet.insert(a); 2408 } 2409 return a; 2410 } 2411 2412 void 2413 Printer::init(AST::Array* output) { 2414 _output = output; 2415 } 2416 2417 void 2418 Printer::printElem(std::ostream& out, 2419 AST::Node* ai, 2420 const Gecode::IntVarArray& iv, 2421 const Gecode::BoolVarArray& bv 2422#ifdef GECODE_HAS_SET_VARS 2423 , const Gecode::SetVarArray& sv 2424#endif 2425#ifdef GECODE_HAS_FLOAT_VARS 2426 , 2427 const Gecode::FloatVarArray& fv 2428#endif 2429 ) const { 2430 int k; 2431 if (ai->isInt(k)) { 2432 out << k; 2433 } else if (ai->isIntVar()) { 2434 out << iv[ai->getIntVar()]; 2435 } else if (ai->isBoolVar()) { 2436 if (bv[ai->getBoolVar()].min() == 1) { 2437 out << "true"; 2438 } else if (bv[ai->getBoolVar()].max() == 0) { 2439 out << "false"; 2440 } else { 2441 out << "false..true"; 2442 } 2443#ifdef GECODE_HAS_SET_VARS 2444 } else if (ai->isSetVar()) { 2445 if (!sv[ai->getSetVar()].assigned()) { 2446 out << sv[ai->getSetVar()]; 2447 return; 2448 } 2449 SetVarGlbRanges svr(sv[ai->getSetVar()]); 2450 if (!svr()) { 2451 out << "{}"; 2452 return; 2453 } 2454 int min = svr.min(); 2455 int max = svr.max(); 2456 ++svr; 2457 if (svr()) { 2458 SetVarGlbValues svv(sv[ai->getSetVar()]); 2459 int i = svv.val(); 2460 out << "{" << i; 2461 ++svv; 2462 for (; svv(); ++svv) 2463 out << ", " << svv.val(); 2464 out << "}"; 2465 } else { 2466 out << min << ".." << max; 2467 } 2468#endif 2469#ifdef GECODE_HAS_FLOAT_VARS 2470 } else if (ai->isFloatVar()) { 2471 if (fv[ai->getFloatVar()].assigned()) { 2472 FloatVal vv = fv[ai->getFloatVar()].val(); 2473 FloatNum v; 2474 if (vv.singleton()) 2475 v = vv.min(); 2476 else if (vv < 0.0) 2477 v = vv.max(); 2478 else 2479 v = vv.min(); 2480 std::ostringstream oss; 2481 // oss << std::scientific; 2482 oss << std::setprecision(std::numeric_limits<double>::digits10); 2483 oss << v; 2484 if (oss.str().find(".") == std::string::npos) 2485 oss << ".0"; 2486 out << oss.str(); 2487 } else { 2488 out << fv[ai->getFloatVar()]; 2489 } 2490#endif 2491 } else if (ai->isBool()) { 2492 out << (ai->getBool() ? "true" : "false"); 2493 } else if (ai->isSet()) { 2494 AST::SetLit* s = ai->getSet(); 2495 if (s->interval) { 2496 out << s->min << ".." << s->max; 2497 } else { 2498 out << "{"; 2499 for (unsigned int i=0; i<s->s.size(); i++) { 2500 out << s->s[i] << (i < s->s.size()-1 ? ", " : "}"); 2501 } 2502 } 2503 } else if (ai->isString()) { 2504 std::string s = ai->getString(); 2505 for (unsigned int i=0; i<s.size(); i++) { 2506 if (s[i] == '\\' && i<s.size()-1) { 2507 switch (s[i+1]) { 2508 case 'n': out << "\n"; break; 2509 case '\\': out << "\\"; break; 2510 case 't': out << "\t"; break; 2511 default: out << "\\" << s[i+1]; 2512 } 2513 i++; 2514 } else { 2515 out << s[i]; 2516 } 2517 } 2518 } 2519 } 2520 2521 void 2522 Printer::printElemDiff(std::ostream& out, 2523 AST::Node* ai, 2524 const Gecode::IntVarArray& iv1, 2525 const Gecode::IntVarArray& iv2, 2526 const Gecode::BoolVarArray& bv1, 2527 const Gecode::BoolVarArray& bv2 2528#ifdef GECODE_HAS_SET_VARS 2529 , const Gecode::SetVarArray& sv1, 2530 const Gecode::SetVarArray& sv2 2531#endif 2532#ifdef GECODE_HAS_FLOAT_VARS 2533 , const Gecode::FloatVarArray& fv1, 2534 const Gecode::FloatVarArray& fv2 2535#endif 2536 ) const { 2537#ifdef GECODE_HAS_GIST 2538 using namespace Gecode::Gist; 2539 int k; 2540 if (ai->isInt(k)) { 2541 out << k; 2542 } else if (ai->isIntVar()) { 2543 std::string res(Comparator::compare("",iv1[ai->getIntVar()], 2544 iv2[ai->getIntVar()])); 2545 if (res.length() > 0) { 2546 res.erase(0, 1); // Remove '=' 2547 out << res; 2548 } else { 2549 out << iv1[ai->getIntVar()]; 2550 } 2551 } else if (ai->isBoolVar()) { 2552 std::string res(Comparator::compare("",bv1[ai->getBoolVar()], 2553 bv2[ai->getBoolVar()])); 2554 if (res.length() > 0) { 2555 res.erase(0, 1); // Remove '=' 2556 out << res; 2557 } else { 2558 out << bv1[ai->getBoolVar()]; 2559 } 2560#ifdef GECODE_HAS_SET_VARS 2561 } else if (ai->isSetVar()) { 2562 std::string res(Comparator::compare("",sv1[ai->getSetVar()], 2563 sv2[ai->getSetVar()])); 2564 if (res.length() > 0) { 2565 res.erase(0, 1); // Remove '=' 2566 out << res; 2567 } else { 2568 out << sv1[ai->getSetVar()]; 2569 } 2570#endif 2571#ifdef GECODE_HAS_FLOAT_VARS 2572 } else if (ai->isFloatVar()) { 2573 std::string res(Comparator::compare("",fv1[ai->getFloatVar()], 2574 fv2[ai->getFloatVar()])); 2575 if (res.length() > 0) { 2576 res.erase(0, 1); // Remove '=' 2577 out << res; 2578 } else { 2579 out << fv1[ai->getFloatVar()]; 2580 } 2581#endif 2582 } else if (ai->isBool()) { 2583 out << (ai->getBool() ? "true" : "false"); 2584 } else if (ai->isSet()) { 2585 AST::SetLit* s = ai->getSet(); 2586 if (s->interval) { 2587 out << s->min << ".." << s->max; 2588 } else { 2589 out << "{"; 2590 for (unsigned int i=0; i<s->s.size(); i++) { 2591 out << s->s[i] << (i < s->s.size()-1 ? ", " : "}"); 2592 } 2593 } 2594 } else if (ai->isString()) { 2595 std::string s = ai->getString(); 2596 for (unsigned int i=0; i<s.size(); i++) { 2597 if (s[i] == '\\' && i<s.size()-1) { 2598 switch (s[i+1]) { 2599 case 'n': out << "\n"; break; 2600 case '\\': out << "\\"; break; 2601 case 't': out << "\t"; break; 2602 default: out << "\\" << s[i+1]; 2603 } 2604 i++; 2605 } else { 2606 out << s[i]; 2607 } 2608 } 2609 } 2610#else 2611 (void) out; 2612 (void) ai; 2613 (void) iv1; 2614 (void) iv2; 2615 (void) bv1; 2616 (void) bv2; 2617#ifdef GECODE_HAS_SET_VARS 2618 (void) sv1; 2619 (void) sv2; 2620#endif 2621#ifdef GECODE_HAS_FLOAT_VARS 2622 (void) fv1; 2623 (void) fv2; 2624#endif 2625 2626#endif 2627 } 2628 2629 void 2630 Printer::print(std::ostream& out, 2631 const Gecode::IntVarArray& iv, 2632 const Gecode::BoolVarArray& bv 2633#ifdef GECODE_HAS_SET_VARS 2634 , 2635 const Gecode::SetVarArray& sv 2636#endif 2637#ifdef GECODE_HAS_FLOAT_VARS 2638 , 2639 const Gecode::FloatVarArray& fv 2640#endif 2641 ) const { 2642 if (_output == nullptr) 2643 return; 2644 for (unsigned int i=0; i< _output->a.size(); i++) { 2645 AST::Node* ai = _output->a[i]; 2646 if (ai->isArray()) { 2647 AST::Array* aia = ai->getArray(); 2648 int size = aia->a.size(); 2649 out << "["; 2650 for (int j=0; j<size; j++) { 2651 printElem(out,aia->a[j],iv,bv 2652#ifdef GECODE_HAS_SET_VARS 2653 ,sv 2654#endif 2655#ifdef GECODE_HAS_FLOAT_VARS 2656 ,fv 2657#endif 2658 ); 2659 if (j<size-1) 2660 out << ", "; 2661 } 2662 out << "]"; 2663 } else { 2664 printElem(out,ai,iv,bv 2665#ifdef GECODE_HAS_SET_VARS 2666 ,sv 2667#endif 2668#ifdef GECODE_HAS_FLOAT_VARS 2669 ,fv 2670#endif 2671 ); 2672 } 2673 } 2674 } 2675 2676 void 2677 Printer::printDiff(std::ostream& out, 2678 const Gecode::IntVarArray& iv1, 2679 const Gecode::IntVarArray& iv2, 2680 const Gecode::BoolVarArray& bv1, 2681 const Gecode::BoolVarArray& bv2 2682#ifdef GECODE_HAS_SET_VARS 2683 , 2684 const Gecode::SetVarArray& sv1, 2685 const Gecode::SetVarArray& sv2 2686#endif 2687#ifdef GECODE_HAS_FLOAT_VARS 2688 , 2689 const Gecode::FloatVarArray& fv1, 2690 const Gecode::FloatVarArray& fv2 2691#endif 2692 ) const { 2693 if (_output == nullptr) 2694 return; 2695 for (unsigned int i=0; i< _output->a.size(); i++) { 2696 AST::Node* ai = _output->a[i]; 2697 if (ai->isArray()) { 2698 AST::Array* aia = ai->getArray(); 2699 int size = aia->a.size(); 2700 out << "["; 2701 for (int j=0; j<size; j++) { 2702 printElemDiff(out,aia->a[j],iv1,iv2,bv1,bv2 2703#ifdef GECODE_HAS_SET_VARS 2704 ,sv1,sv2 2705#endif 2706#ifdef GECODE_HAS_FLOAT_VARS 2707 ,fv1,fv2 2708#endif 2709 ); 2710 if (j<size-1) 2711 out << ", "; 2712 } 2713 out << "]"; 2714 } else { 2715 printElemDiff(out,ai,iv1,iv2,bv1,bv2 2716#ifdef GECODE_HAS_SET_VARS 2717 ,sv1,sv2 2718#endif 2719#ifdef GECODE_HAS_FLOAT_VARS 2720 ,fv1,fv2 2721#endif 2722 ); 2723 } 2724 } 2725 } 2726 2727 void 2728 Printer::addIntVarName(const std::string& n) { 2729 iv_names.push_back(n); 2730 } 2731 void 2732 Printer::addBoolVarName(const std::string& n) { 2733 bv_names.push_back(n); 2734 } 2735#ifdef GECODE_HAS_FLOAT_VARS 2736 void 2737 Printer::addFloatVarName(const std::string& n) { 2738 fv_names.push_back(n); 2739 } 2740#endif 2741#ifdef GECODE_HAS_SET_VARS 2742 void 2743 Printer::addSetVarName(const std::string& n) { 2744 sv_names.push_back(n); 2745 } 2746#endif 2747 2748 void 2749 Printer::shrinkElement(AST::Node* node, 2750 std::map<int,int>& iv, std::map<int,int>& bv, 2751 std::map<int,int>& sv, std::map<int,int>& fv) { 2752 if (node->isIntVar()) { 2753 AST::IntVar* x = static_cast<AST::IntVar*>(node); 2754 if (iv.find(x->i) == iv.end()) { 2755 int newi = iv.size(); 2756 iv[x->i] = newi; 2757 } 2758 x->i = iv[x->i]; 2759 } else if (node->isBoolVar()) { 2760 AST::BoolVar* x = static_cast<AST::BoolVar*>(node); 2761 if (bv.find(x->i) == bv.end()) { 2762 int newi = bv.size(); 2763 bv[x->i] = newi; 2764 } 2765 x->i = bv[x->i]; 2766 } else if (node->isSetVar()) { 2767 AST::SetVar* x = static_cast<AST::SetVar*>(node); 2768 if (sv.find(x->i) == sv.end()) { 2769 int newi = sv.size(); 2770 sv[x->i] = newi; 2771 } 2772 x->i = sv[x->i]; 2773 } else if (node->isFloatVar()) { 2774 AST::FloatVar* x = static_cast<AST::FloatVar*>(node); 2775 if (fv.find(x->i) == fv.end()) { 2776 int newi = fv.size(); 2777 fv[x->i] = newi; 2778 } 2779 x->i = fv[x->i]; 2780 } 2781 } 2782 2783 void 2784 Printer::shrinkArrays(Space& home, 2785 int& optVar, bool optVarIsInt, 2786 Gecode::IntVarArray& iv, 2787 Gecode::BoolVarArray& bv 2788#ifdef GECODE_HAS_SET_VARS 2789 , 2790 Gecode::SetVarArray& sv 2791#endif 2792#ifdef GECODE_HAS_FLOAT_VARS 2793 , 2794 Gecode::FloatVarArray& fv 2795#endif 2796 ) { 2797 if (_output == nullptr) { 2798 if (optVarIsInt && optVar != -1) { 2799 IntVar ov = iv[optVar]; 2800 iv = IntVarArray(home, 1); 2801 iv[0] = ov; 2802 optVar = 0; 2803 } else { 2804 iv = IntVarArray(home, 0); 2805 } 2806 bv = BoolVarArray(home, 0); 2807#ifdef GECODE_HAS_SET_VARS 2808 sv = SetVarArray(home, 0); 2809#endif 2810#ifdef GECODE_HAS_FLOAT_VARS 2811 if (!optVarIsInt && optVar != -1) { 2812 FloatVar ov = fv[optVar]; 2813 fv = FloatVarArray(home, 1); 2814 fv[0] = ov; 2815 optVar = 0; 2816 } else { 2817 fv = FloatVarArray(home,0); 2818 } 2819#endif 2820 return; 2821 } 2822 std::map<int,int> iv_new; 2823 std::map<int,int> bv_new; 2824 std::map<int,int> sv_new; 2825 std::map<int,int> fv_new; 2826 2827 if (optVar != -1) { 2828 if (optVarIsInt) 2829 iv_new[optVar] = 0; 2830 else 2831 fv_new[optVar] = 0; 2832 optVar = 0; 2833 } 2834 2835 for (unsigned int i=0; i< _output->a.size(); i++) { 2836 AST::Node* ai = _output->a[i]; 2837 if (ai->isArray()) { 2838 AST::Array* aia = ai->getArray(); 2839 for (unsigned int j=0; j<aia->a.size(); j++) { 2840 shrinkElement(aia->a[j],iv_new,bv_new,sv_new,fv_new); 2841 } 2842 } else { 2843 shrinkElement(ai,iv_new,bv_new,sv_new,fv_new); 2844 } 2845 } 2846 2847 IntVarArgs iva(iv_new.size()); 2848 std::vector<std::string> iv_names_new(iv_new.size()); 2849 for (std::map<int,int>::iterator i=iv_new.begin(); i != iv_new.end(); ++i) { 2850 iva[(*i).second] = iv[(*i).first]; 2851 iv_names_new[(*i).second] = iv_names[(*i).first]; 2852 } 2853 iv = IntVarArray(home, iva); 2854 iv_names = iv_names_new; 2855 2856 BoolVarArgs bva(bv_new.size()); 2857 std::vector<std::string> bv_names_new(bv_new.size()); 2858 for (std::map<int,int>::iterator i=bv_new.begin(); i != bv_new.end(); ++i) { 2859 bva[(*i).second] = bv[(*i).first]; 2860 bv_names_new[(*i).second] = bv_names[(*i).first]; 2861 } 2862 bv = BoolVarArray(home, bva); 2863 bv_names = bv_names_new; 2864 2865#ifdef GECODE_HAS_SET_VARS 2866 SetVarArgs sva(sv_new.size()); 2867 std::vector<std::string> sv_names_new(sv_new.size()); 2868 for (std::map<int,int>::iterator i=sv_new.begin(); i != sv_new.end(); ++i) { 2869 sva[(*i).second] = sv[(*i).first]; 2870 sv_names_new[(*i).second] = sv_names[(*i).first]; 2871 } 2872 sv = SetVarArray(home, sva); 2873 sv_names = sv_names_new; 2874#endif 2875 2876#ifdef GECODE_HAS_FLOAT_VARS 2877 FloatVarArgs fva(fv_new.size()); 2878 std::vector<std::string> fv_names_new(fv_new.size()); 2879 for (std::map<int,int>::iterator i=fv_new.begin(); i != fv_new.end(); ++i) { 2880 fva[(*i).second] = fv[(*i).first]; 2881 fv_names_new[(*i).second] = fv_names[(*i).first]; 2882 } 2883 fv = FloatVarArray(home, fva); 2884 fv_names = fv_names_new; 2885#endif 2886 } 2887 2888 Printer::~Printer(void) { 2889 delete _output; 2890 } 2891 2892}} 2893 2894// STATISTICS: flatzinc-any