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