this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Patrick Pekczynski <pekczynski@ps.uni-sb.de> 5 * 6 * Contributing authors: 7 * Christian Schulte <schulte@gecode.org> 8 * Guido Tack <tack@gecode.org> 9 * 10 * Copyright: 11 * Patrick Pekczynski, 2005 12 * Christian Schulte, 2009 13 * Guido Tack, 2009 14 * 15 * This file is part of Gecode, the generic constraint 16 * development environment: 17 * http://www.gecode.org 18 * 19 * Permission is hereby granted, free of charge, to any person obtaining 20 * a copy of this software and associated documentation files (the 21 * "Software"), to deal in the Software without restriction, including 22 * without limitation the rights to use, copy, modify, merge, publish, 23 * distribute, sublicense, and/or sell copies of the Software, and to 24 * permit persons to whom the Software is furnished to do so, subject to 25 * the following conditions: 26 * 27 * The above copyright notice and this permission notice shall be 28 * included in all copies or substantial portions of the Software. 29 * 30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 34 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 35 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 36 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 37 * 38 */ 39 40namespace Gecode { namespace Int { namespace GCC { 41 42 /** 43 * \brief Bounds constraint (BC) type 44 * 45 * If BC = UBC, then we argue about the Upper Bounds Constraint 46 * else we use the functions for the Lower Bounds Constraint 47 */ 48 enum BC {UBC = 1, LBC = 0}; 49 50 class Edge; 51 /// Base class for nodes in the variable-value-graph 52 class Node { 53 protected: 54 /// Stores all incident edges on the node 55 Edge* e; 56 /// First edge 57 Edge* fst; 58 /// Last edge 59 Edge* lst; 60 /// Single incoming edge used for storing a path in the algorithms 61 Edge* ie; 62 /// Index 63 int idx; 64 /// Flags for nodes 65 enum NodeFlag { 66 /// No flags set 67 NF_NONE = 0, 68 /// Whether node is a value node 69 NF_VAL = 1 << 0, 70 /// Whether matched for LBC 71 NF_M_LBC = 1 << 1, 72 /// Whether matched for UBC 73 NF_M_UBC = 1 << 2 74 }; 75 /// Flags for node 76 unsigned char nf; 77 public: 78 /// stores the number of incident edges on the node 79 int noe; 80 81 /// \name Constructors and initialization 82 //@{ 83 /// Default constructor 84 Node(void); 85 /// Constructor for index \a i that sets type to \a t 86 Node(NodeFlag nf, int i); 87 //@} 88 89 /// \name Access 90 //@{ 91 /// Return the type of the node (false for a variable node) 92 bool type(void) const; 93 /// Return reference to the incident edges 94 Edge** adj(void); 95 /// Return pointer to the first incident edge 96 Edge* first(void) const; 97 /// Return pointer to the last incident edge 98 Edge* last(void) const; 99 /// Return pointer to the node's inedge 100 Edge* inedge(void) const; 101 /// Get index of either variable or value 102 int index(void) const; 103 /// check whether a node has been removed from the graph 104 bool removed(void) const; 105 //@} 106 107 /// \name Update 108 //@{ 109 /// Set the first edge pointer to \a p 110 void first(Edge* p); 111 /// Set the last edge pointer to \a p 112 void last(Edge* p); 113 /// Set the inedge pointer to \a p 114 void inedge(Edge* p); 115 /// Set index of either variable or value 116 void index(int i); 117 //@} 118 119 /// \name Memory management 120 //@{ 121 /// Allocate memory from space 122 static void* operator new(size_t s, Space& home); 123 /// Free memory (unused) 124 static void operator delete(void*, Space&) {}; 125 /// Needed for exceptions 126 static void operator delete(void*) {}; 127 //@} 128 }; 129 130 /// %Variable node 131 class VarNode : public Node { 132 protected: 133 /// Stores the matching edge on this node in the UBC 134 Edge* ubm; 135 /// Stores the matching edge on this node in the LBC 136 Edge* lbm; 137 public: 138 /// \name Constructors and initialization 139 //@{ 140 /// Default constructor 141 VarNode(void); 142 /// Creates a variable node with index \a i 143 VarNode(int i); 144 //@} 145 146 /// \name Access 147 //@{ 148 /// Return the matching edge on the node 149 Edge* get_match(BC bc) const; 150 /// tests whether the node is matched or not 151 bool matched(BC bc) const; 152 //@} 153 154 /// \name Update 155 //@{ 156 /// Set the pointer of the matching edge to m 157 void set_match(BC bc, Edge* m); 158 /// Set node to matched 159 void match(BC bc); 160 /// Unmatch the node 161 void unmatch(BC bc); 162 //@} 163 }; 164 165 /// Value node 166 class ValNode : public Node { 167 protected: 168 /// Minimal required occurence of the value as stored in k 169 int _klb; 170 /// Maximal required occurence of the value as stored in k 171 int _kub; 172 /// Index to acces the value via cardinality array k 173 int _kidx; 174 /// Stores the current number of occurences of the value 175 int _kcount; 176 /// Store numbre of conflicting matching edges 177 int noc; 178 /// Minimal capacity of the value node 179 int lb; 180 /// Smallest maximal capacity of the value node 181 int ublow; 182 /// Maximal capacity of the value node 183 int ub; 184 public: 185 /// Stores the value of the node 186 int val; 187 188 /// \name Constructors and destructors 189 //@{ 190 /// Default constructor 191 ValNode(void); 192 /** 193 * \brief Constructor for value node 194 * 195 * with minimal capacity \a min, 196 * maximal capacity \a max, 197 * the value \a value and the index \a k_access in \a k 198 */ 199 ValNode(int min, int max, int value, int kidx, int kshift, int count); 200 //@} 201 202 /// \name Access 203 //@{ 204 /// get max cap for LBC 205 int maxlow(void) const; 206 /// Mark the value node as conflicting in case of variable cardinalities 207 void card_conflict(int c); 208 /// Check whether the value node is conflicting 209 int card_conflict(void) const; 210 /// Reduce the conflict counter 211 void red_conflict(void); 212 /// increases the value counter 213 void inc(void); 214 /// returns the current number of occurences of the value 215 int kcount(void) const; 216 /// returns the number of incident matching edges on a value node 217 int incid_match(BC bc) const; 218 /// returns the index in cardinality array k 219 int kindex(void) const; 220 /// returns \a true if the node is matched in BC, \a false otherwise 221 bool matched(BC bc) const; 222 /// tests whether the node is a sink 223 bool sink(void) const; 224 /// tests whether the node is a source 225 bool source(void) const; 226 /// return the minimal node capacity as stored in \a k 227 int kmin(void) const; 228 /// return the maximal node capacity as stored in \a k 229 int kmax(void) const; 230 /// return minimal or maximal capacity 231 int kbound(BC bc) const; 232 //@} 233 234 /// \name Update 235 //@{ 236 /// set the max cap for LBC 237 void maxlow(int i); 238 /// Set how often value occurs 239 void kcount(int); 240 /// changes the index in the cardinality array k 241 void kindex(int); 242 /// decrease the node-capacity 243 void dec(BC bc); 244 /// increase the node-capacity 245 void inc(BC bc); 246 /// return the the node-capacity 247 int cap(BC bc) const; 248 /// set the node-capacity to \a c 249 void cap(BC bc, int c); 250 /// match the node 251 void match(BC bc); 252 /// unmatch the node 253 void unmatch(BC bc); 254 /// node reset to original capacity values 255 void reset(void); 256 /// set the minimal k-capacity to min 257 void kmin(int min); 258 /// set the maximal k-capacity to max 259 void kmax(int max); 260 //@} 261 }; 262 263 /// Class for edges \f$ e(x,v) \f$ in the variable-value-graph 264 class Edge { 265 private: 266 /// pointer to the variable node 267 VarNode* x; 268 /// pointer to the value node 269 ValNode* v; 270 /// pointer to the next edge incident on the same variable node 271 Edge* next_edge; 272 /// pointer to the previous edge incident on the same variable node 273 Edge* prev_edge; 274 /// pointer to the next edge on the same value node 275 Edge* next_vedge; 276 /// pointer to the previous edge on the same value node 277 Edge* prev_vedge; 278 /// Flags for edges 279 enum EdgeFlag { 280 /// No flags set 281 EF_NONE = 0, 282 /// Whether edge is used in LBC 283 EF_MRKLB = 1 << 0, 284 /// Whether edge is used in UBC 285 EF_MRKUB = 1 << 1, 286 /// Whether edge is matched in LBC 287 EF_LM = 1 << 2, 288 /// Whether edge is matched in UBC 289 EF_UM = 1 << 3, 290 /// Whether edge has been deleted 291 EF_DEL = 1 << 4 292 }; 293 /// Flags for edges 294 unsigned char ef; 295 public: 296 /// \name Constructors 297 //@{ 298 /// Default constructor 299 Edge(void) {} 300 /** 301 * \brief Construct edge \f$e(x,v)\f$ from variable node \a x 302 * and value node \a y 303 */ 304 Edge(VarNode* x, ValNode* v); 305 //@} 306 307 /// \name Access 308 //@{ 309 /// Whether the edge is used 310 bool used(BC bc) const; 311 /// return whether the edge is matched 312 bool matched(BC bc) const; 313 /// return whether the edge has been deleted from the graph 314 bool deleted(void) const; 315 /** 316 * \brief return a pointer to the next edge 317 * If \a t is false the function returns the next edge incident on \a x 318 * otherwise it returns the next edge incident on \a v 319 */ 320 Edge* next(bool t) const; 321 /// return the pointer to the next edge incident on \a x 322 Edge* next(void) const; 323 /// return the pointer to the previous edge incident on \a x 324 Edge* prev(void) const; 325 /// return the pointer to the next edge incident on \a v 326 Edge* vnext(void) const; 327 /// return the pointer to the previous edge incident on \a v 328 Edge* vprev(void) const; 329 /// return the pointer to the variable node \a x of this edge 330 VarNode* getVar(void) const; 331 /// return the pointer to the value node \a v of this edge 332 ValNode* getVal(void) const; 333 /** 334 * \brief return pointer to \a x if \a t = true otherwise return \a v 335 * 336 */ 337 Node* getMate(bool t) const; 338 //@} 339 340 /// Update 341 //@{ 342 /// Mark the edge as used 343 void use(BC bc); 344 /// Mark the edge as unused 345 void free(BC bc); 346 /// Reset the edge (free the edge, and unmatch the edge) 347 void reset(BC bc); 348 /// Match the edge 349 void match(BC bc); 350 /// Unmatch the edge and the incident nodes 351 void unmatch(BC bc); 352 /// Unmatch the edge and ( \a x if t=false, \a v otherwise ) 353 void unmatch(BC bc, bool t); 354 /// Unlink the edge from the linked list of edges 355 void unlink(void); 356 /// Mark the edge as deleted during synchronization 357 void del_edge(void); 358 /// Insert the edge again 359 void insert_edge(void); 360 /// return the reference to the next edge incident on \a x 361 Edge** next_ref(void); 362 /// return the reference to the previous edge incident on \a x 363 Edge** prev_ref(void); 364 /// return the reference to the next edge incident on \a v 365 Edge** vnext_ref(void); 366 /// return the reference to the previous edge incident on \a v 367 Edge** vprev_ref(void); 368 //@} 369 370 /// \name Memory management 371 //@{ 372 /// Allocate memory from space 373 static void* operator new(size_t s, Space& home); 374 /// Free memory (unused) 375 static void operator delete(void*, Space&) {}; 376 /// Needed for exceptions 377 static void operator delete(void*) {}; 378 //@} 379 }; 380 381 382 /** 383 * \brief Variable-value-graph used during propagation 384 * 385 */ 386 template<class Card> 387 class VarValGraph { 388 private: 389 /// Temporary stack for nodes 390 typedef Support::StaticStack<Node*,Region> NodeStack; 391 /// Bitset 392 typedef Support::BitSet<Region> BitSet; 393 /// Variable partition representing the problem variables 394 VarNode** vars; 395 /** 396 * \brief Value partition 397 * For each value 398 * \f$ v_i\in V=\left(\bigcup_\{0, \dots, |x|-1\}\right) D_i \f$ 399 * in the domains of the 400 * problem variables there is a node in the graph. 401 */ 402 ValNode** vals; 403 /// Cardinality of the variable partition 404 int n_var; 405 /** 406 * \brief Cardinality of the value partition 407 * 408 * Computed as \f$ |V| = \left(\bigcup_\{0, \dots, |x|-1\}\right) D_i \f$ 409 */ 410 int n_val; 411 /// Total number of nodes in the graph 412 int n_node; 413 /** 414 * \brief The sum over the minimal capacities of all value nodes 415 * 416 * \f$sum_min = \sum_{v_i \in V} l_i= k[i].min() \f$ 417 */ 418 int sum_min; 419 /** 420 * \brief The sum over the maximal capacities of all value nodes 421 * 422 * \f$sum_max = \sum_{v_i \in V} l_i= k[i].max() \f$ 423 */ 424 int sum_max; 425 public: 426 /// \name Constructors and Destructors 427 //@{ 428 /** 429 * \brief Constructor for the variable-value-graph 430 * 431 * The variable parition is initialized with the variables from \a x, 432 * the value partition is initialized with the values from \a k. 433 **/ 434 VarValGraph(Space& home, 435 ViewArray<IntView>& x, ViewArray<Card>& k, 436 int smin, int smax); 437 //@} 438 /// \name Graph-interface 439 //@{ 440 /// Check whether minimum requirements shrink variable domains 441 ExecStatus min_require(Space& home, 442 ViewArray<IntView>& x, ViewArray<Card>& k); 443 444 /** 445 * \brief Synchronization of the graph 446 * 447 * If the graph has already been constructed and some edges have 448 * been removed during propagation, this function removes those edges 449 * that do not longer belong to the graph associated with the current 450 * variable domains. 451 */ 452 ExecStatus sync(ViewArray<IntView>& x, ViewArray<Card>& k); 453 /// Remove edges that do not belong to any maximal matching 454 template<BC> 455 ExecStatus narrow(Space& home, 456 ViewArray<IntView>& x, ViewArray<Card>& k); 457 458 /** \brief Compute a maximum matching M on the graph 459 * 460 * - If BC=UBC then \f$|M|= |X|\f$ 461 * - If BC=LBC then \f$|M|= \sum_{i\in \{ 0, \dots, |X|-1\}} 462 * k[i].min()\f$ 463 */ 464 template<BC> 465 ExecStatus maximum_matching(void); 466 467 /// Compute possible free alternating paths in the graph 468 template<BC> 469 void free_alternating_paths(void); 470 /// Compute possible strongly connected components of the graph 471 template<BC> 472 void strongly_connected_components(void); 473 /** 474 * \brief Test whether the current maximal matching on the graph 475 * can be augmented by an alternating path starting and ending with 476 * a free node. 477 */ 478 template<BC> 479 bool augmenting_path(Node*); 480 481 protected: 482 /** 483 * \brief Perform depth-first search on the graph 484 * 485 * Depth first search used to compute the 486 * strongly connected components of the graph. 487 */ 488 template<BC> 489 void dfs(Node*, BitSet&, BitSet&, int[], 490 NodeStack&, NodeStack&, int&); 491 492 //@} 493 public: 494 /// Allocate memory for the graph 495 void* operator new(size_t t, Space& home); 496 /// Deallocation (void) 497 void operator delete(void*, Space&) {} 498 }; 499 500 501 502 /* 503 * Nodes 504 * 505 */ 506 forceinline 507 Node::Node(void) {} 508 forceinline 509 Node::Node(NodeFlag nf0, int i) 510 : e(nullptr), fst(nullptr), lst(nullptr), ie(nullptr), idx(i), 511 nf(static_cast<unsigned char>(nf0)), noe(0) {} 512 513 forceinline Edge** 514 Node::adj(void) { 515 return &e; 516 } 517 forceinline Edge* 518 Node::first(void) const { 519 return fst; 520 } 521 forceinline Edge* 522 Node::last(void) const { 523 return lst; 524 } 525 forceinline void 526 Node::first(Edge* p) { 527 fst = p; 528 } 529 forceinline void 530 Node::last(Edge* p) { 531 lst = p; 532 } 533 forceinline bool 534 Node::type(void) const { 535 return (nf & NF_VAL) != 0; 536 } 537 forceinline Edge* 538 Node::inedge(void) const { 539 return ie; 540 } 541 forceinline void 542 Node::inedge(Edge* p) { 543 ie = p; 544 } 545 forceinline bool 546 Node::removed(void) const { 547 return noe == 0; 548 } 549 forceinline void 550 Node::index(int i) { 551 idx = i; 552 } 553 forceinline int 554 Node::index(void) const { 555 return idx; 556 } 557 558 forceinline void* 559 Node::operator new(size_t s, Space& home) { 560 return home.ralloc(s); 561 } 562 563 564 565 /* 566 * Variable nodes 567 * 568 */ 569 forceinline 570 VarNode::VarNode(void) {} 571 572 forceinline 573 VarNode::VarNode(int x) : 574 Node(NF_NONE,x), ubm(nullptr), lbm(nullptr) {} 575 576 forceinline bool 577 VarNode::matched(BC bc) const { 578 if (bc == UBC) 579 return (nf & NF_M_UBC) != 0; 580 else 581 return (nf & NF_M_LBC) != 0; 582 } 583 584 forceinline void 585 VarNode::match(BC bc) { 586 if (bc == UBC) 587 nf |= NF_M_UBC; 588 else 589 nf |= NF_M_LBC; 590 } 591 592 forceinline void 593 VarNode::set_match(BC bc, Edge* p) { 594 if (bc == UBC) 595 ubm = p; 596 else 597 lbm = p; 598 } 599 600 forceinline void 601 VarNode::unmatch(BC bc) { 602 if (bc == UBC) { 603 nf &= ~NF_M_UBC; ubm = nullptr; 604 } else { 605 nf &= ~NF_M_LBC; lbm = nullptr; 606 } 607 } 608 609 forceinline Edge* 610 VarNode::get_match(BC bc) const { 611 if (bc == UBC) 612 return ubm; 613 else 614 return lbm; 615 } 616 617 618 619 620 /* 621 * Value nodes 622 * 623 */ 624 forceinline 625 ValNode::ValNode(void) {} 626 627 forceinline 628 ValNode::ValNode(int min, int max, int value, 629 int kidx, int kshift, int count) : 630 Node(NF_VAL,kshift), _klb(min), _kub(max), _kidx(kidx), _kcount(count), 631 noc(0), 632 lb(min), ublow(max), ub(max), 633 val(value) {} 634 635 forceinline void 636 ValNode::maxlow(int i) { 637 assert(i >= lb); 638 ublow = i; 639 } 640 641 forceinline int 642 ValNode::maxlow(void) const { 643 if (_klb == _kub) { 644 assert(ublow == lb); 645 } 646 return ublow; 647 } 648 649 650 forceinline void 651 ValNode::card_conflict(int c) { 652 noc = c; 653 } 654 655 forceinline void 656 ValNode::red_conflict(void) { 657 noc--; 658 assert(noc >= 0); 659 } 660 661 forceinline int 662 ValNode::card_conflict(void) const { 663 return noc; 664 } 665 666 forceinline int 667 ValNode::cap(BC bc) const { 668 if (bc == UBC) 669 return ub; 670 else 671 return lb; 672 } 673 forceinline bool 674 ValNode::matched(BC bc) const { 675 return cap(bc) == 0; 676 } 677 678 forceinline void 679 ValNode::reset(void) { 680 lb = _klb; 681 ublow = _kub; 682 ub = _kub; 683 noe = 0; 684 } 685 686 forceinline int 687 ValNode::kbound(BC bc) const { 688 if (bc == UBC) { 689 return _kub; 690 } else { 691 return _klb; 692 } 693 } 694 695 forceinline int 696 ValNode::kmax(void) const { 697 return _kub; 698 } 699 700 forceinline int 701 ValNode::kmin(void) const { 702 return _klb; 703 } 704 705 forceinline void 706 ValNode::kmin(int klb) { 707 _klb = klb; 708 } 709 710 forceinline void 711 ValNode::kmax(int kub) { 712 _kub = kub; 713 } 714 715 716 forceinline void 717 ValNode::dec(BC bc) { 718 if (bc == UBC) { 719 ub--; 720 } else { 721 lb--; ublow--; 722 } 723 } 724 725 forceinline void 726 ValNode::inc(BC bc) { 727 if (bc == UBC) { 728 ub++; 729 } else { 730 lb++; ublow++; 731 } 732 } 733 734 forceinline void 735 ValNode::match(BC bc) { 736 dec(bc); 737 } 738 739 forceinline void 740 ValNode::unmatch(BC bc) { 741 inc(bc); 742 } 743 744 forceinline void 745 ValNode::cap(BC bc, int c) { 746 if (bc == UBC) 747 ub = c; 748 else 749 lb = c; 750 } 751 752 forceinline void 753 ValNode::inc(void) { 754 _kcount++; 755 } 756 757 forceinline int 758 ValNode::kcount(void) const { 759 return _kcount; 760 } 761 762 forceinline void 763 ValNode::kcount(int c) { 764 _kcount = c; 765 } 766 767 forceinline void 768 ValNode::kindex(int i) { 769 _kidx = i; 770 } 771 772 forceinline int 773 ValNode::kindex(void) const { 774 return _kidx; 775 } 776 777 /// Returs the number of incident matching edges on the node 778 forceinline int 779 ValNode::incid_match(BC bc) const { 780 if (bc == LBC) 781 return _kub - ublow + _kcount; 782 else 783 return _kub - ub + _kcount; 784 } 785 786 787 forceinline bool 788 ValNode::sink(void) const { 789 // there are only incoming edges 790 // in case of the UBC-matching 791 return _kub - ub == noe; 792 } 793 794 forceinline bool 795 ValNode::source(void) const { 796 // there are only incoming edges 797 // in case of the UBC-matching 798 return _klb - lb == noe; 799 } 800 801 802 803 /* 804 * Edges 805 * 806 */ 807 forceinline void 808 Edge::unlink(void) { 809 // unlink from variable side 810 Edge* p = prev_edge; 811 Edge* n = next_edge; 812 813 if (p != nullptr) 814 *p->next_ref() = n; 815 if (n != nullptr) 816 *n->prev_ref() = p; 817 818 if (this == x->first()) { 819 Edge** ref = x->adj(); 820 *ref = n; 821 x->first(n); 822 } 823 824 if (this == x->last()) 825 x->last(p); 826 827 // unlink from value side 828 Edge* pv = prev_vedge; 829 Edge* nv = next_vedge; 830 831 if (pv != nullptr) 832 *pv->vnext_ref() = nv; 833 if (nv != nullptr) 834 *nv->vprev_ref() = pv; 835 if (this == v->first()) { 836 Edge** ref = v->adj(); 837 *ref = nv; 838 v->first(nv); 839 } 840 if (this == v->last()) 841 v->last(pv); 842 } 843 844 forceinline 845 Edge::Edge(VarNode* var, ValNode* val) : 846 x(var), v(val), 847 next_edge(nullptr), prev_edge(nullptr), 848 next_vedge(nullptr), prev_vedge(nullptr), ef(EF_NONE) {} 849 850 forceinline void 851 Edge::use(BC bc) { 852 if (bc == UBC) 853 ef |= EF_MRKUB; 854 else 855 ef |= EF_MRKLB; 856 } 857 forceinline void 858 Edge::free(BC bc) { 859 if (bc == UBC) 860 ef &= ~EF_MRKUB; 861 else 862 ef &= ~EF_MRKLB; 863 } 864 forceinline bool 865 Edge::used(BC bc) const { 866 if (bc == UBC) 867 return (ef & EF_MRKUB) != 0; 868 else 869 return (ef & EF_MRKLB) != 0; 870 } 871 forceinline Edge* 872 Edge::next(void) const { 873 return next_edge; 874 } 875 forceinline Edge* 876 Edge::next(bool t) const { 877 if (t) { 878 return next_vedge; 879 } else { 880 return next_edge; 881 } 882 } 883 884 forceinline Edge* 885 Edge::vnext(void) const { 886 return next_vedge; 887 } 888 forceinline Edge** 889 Edge::vnext_ref(void) { 890 return &next_vedge; 891 } 892 forceinline Edge* 893 Edge::prev(void) const { 894 return prev_edge; 895 } 896 forceinline Edge** 897 Edge::prev_ref(void) { 898 return &prev_edge; 899 } 900 forceinline Edge* 901 Edge::vprev(void) const { 902 return prev_vedge; 903 } 904 forceinline Edge** 905 Edge::vprev_ref(void) { 906 return &prev_vedge; 907 } 908 forceinline Edge** 909 Edge::next_ref(void) { 910 return &next_edge; 911 } 912 forceinline VarNode* 913 Edge::getVar(void) const { 914 assert(x != nullptr); 915 return x; 916 } 917 918 forceinline ValNode* 919 Edge::getVal(void) const { 920 assert(v != nullptr); 921 return v; 922 } 923 924 forceinline Node* 925 Edge::getMate(bool type) const { 926 if (type) 927 return x; 928 else 929 return v; 930 } 931 932 forceinline void 933 Edge::unmatch(BC bc) { 934 if (bc == UBC) 935 ef &= ~EF_UM; 936 else 937 ef &= ~EF_LM; 938 x->unmatch(bc); v->unmatch(bc); 939 } 940 941 forceinline void 942 Edge::unmatch(BC bc, bool node) { 943 if (bc == UBC) 944 ef &= ~EF_UM; 945 else 946 ef &= ~EF_LM; 947 if (node) 948 v->unmatch(bc); 949 else 950 x->unmatch(bc); 951 } 952 953 forceinline void 954 Edge::reset(BC bc) { 955 free(bc); unmatch(bc); 956 } 957 958 forceinline void 959 Edge::match(BC bc) { 960 if (bc == UBC) 961 ef |= EF_UM; 962 else 963 ef |= EF_LM; 964 x->match(bc); 965 x->set_match(bc,this); 966 v->match(bc); 967 } 968 969 forceinline bool 970 Edge::matched(BC bc) const { 971 if (bc == UBC) 972 return (ef & EF_UM) != 0; 973 else 974 return (ef & EF_LM) != 0; 975 } 976 977 forceinline void 978 Edge::del_edge(void) { 979 ef |= EF_DEL; 980 } 981 982 forceinline void 983 Edge::insert_edge(void) { 984 ef &= ~EF_DEL; 985 } 986 987 988 forceinline bool 989 Edge::deleted(void) const { 990 return (ef & EF_DEL) != 0; 991 } 992 993 forceinline void* 994 Edge::operator new(size_t s, Space& home) { 995 return home.ralloc(s); 996 } 997 998 999 /* 1000 * Variable value graph 1001 * 1002 */ 1003 template<class Card> 1004 VarValGraph<Card>::VarValGraph(Space& home, 1005 ViewArray<IntView>& x, ViewArray<Card>& k, 1006 int smin, int smax) 1007 : n_var(x.size()), 1008 n_val(k.size()), 1009 n_node(n_var + n_val), 1010 sum_min(smin), 1011 sum_max(smax) { 1012 1013 unsigned int noe = 0; 1014 for (int i=x.size(); i--; ) 1015 noe += x[i].size(); 1016 1017 vars = home.alloc<VarNode*>(n_var); 1018 vals = home.alloc<ValNode*>(n_val); 1019 1020 for (int i = n_val; i--; ) { 1021 int kmi = k[i].min(); 1022 int kma = k[i].max(); 1023 int kc = k[i].counter(); 1024 if (kc != kma) { 1025 if (kmi >= kc) { 1026 kmi -=kc; 1027 assert(kmi >=0); 1028 } else { 1029 kmi = 0; 1030 } 1031 kma -= kc; 1032 assert (kma > 0); 1033 vals[i] = new (home) 1034 ValNode(kmi, kma, k[i].card(), i, i + n_var, kc); 1035 } else { 1036 vals[i] = new (home) 1037 ValNode(0, 0, k[i].card(), i, i + n_var, kc); 1038 } 1039 } 1040 1041 for (int i = n_var; i--; ) { 1042 vars[i] = new (home) VarNode(i); 1043 // get the space for the edges of the varnode 1044 Edge** xadjacent = vars[i]->adj(); 1045 1046 int j = 0; 1047 for (ViewValues<IntView> xi(x[i]); xi(); ++xi) { 1048 // get the correct index for the value 1049 while(vals[j]->val < xi.val()) 1050 j++; 1051 *xadjacent = new (home) Edge(vars[i],vals[j]); 1052 vars[i]->noe++; 1053 if (vars[i]->first() == nullptr) 1054 vars[i]->first(*xadjacent); 1055 Edge* oldprev = vars[i]->last(); 1056 vars[i]->last(*xadjacent); 1057 *vars[i]->last()->prev_ref() = oldprev; 1058 1059 if (vals[j]->first() == nullptr) { 1060 vals[j]->first(*xadjacent); 1061 vals[j]->last(*xadjacent); 1062 } else { 1063 Edge* old = vals[j]->first(); 1064 vals[j]->first(*xadjacent); 1065 *vals[j]->first()->vnext_ref() = old; 1066 *old->vprev_ref() = vals[j]->first(); 1067 } 1068 vals[j]->noe++; 1069 xadjacent = (*xadjacent)->next_ref(); 1070 } 1071 *xadjacent = nullptr; 1072 } 1073 } 1074 1075 1076 template<class Card> 1077 inline ExecStatus 1078 VarValGraph<Card>::min_require(Space& home, 1079 ViewArray<IntView>& x, 1080 ViewArray<Card>& k) { 1081 for (int i = n_val; i--; ) { 1082 ValNode* vln = vals[i]; 1083 if (vln->noe > 0) { 1084 if (k[i].min() == vln->noe) { 1085 // all variable nodes reachable from vln should be equal to vln->val 1086 for (Edge* e = vln->first(); e != nullptr; e = e->vnext()) { 1087 VarNode* vrn = e->getVar(); 1088 for (Edge* f = vrn->first(); f != nullptr; f = f->next()) 1089 if (f != e) { 1090 ValNode* w = f->getVal(); 1091 w->noe--; 1092 vrn->noe--; 1093 f->del_edge(); 1094 f->unlink(); 1095 } 1096 assert(vrn->noe == 1); 1097 1098 int vi = vrn->index(); 1099 GECODE_ME_CHECK(x[vi].eq(home, vln->val)); 1100 1101 vars[vi] = vars[--n_var]; 1102 vars[vi]->index(vi); 1103 x.move_lst(vi); 1104 n_node--; 1105 vln->noe--; 1106 } 1107 1108 1109 int vidx = vln->kindex(); 1110 if (Card::propagate) 1111 GECODE_ME_CHECK(k[vidx].eq(home, k[vidx].min())); 1112 1113 k[vidx].counter(k[vidx].min()); 1114 1115 vln->cap(UBC,0); 1116 vln->cap(LBC,0); 1117 vln->maxlow(0); 1118 1119 if (sum_min >= k[vidx].min()) 1120 sum_min -= k[vidx].min(); 1121 if (sum_max >= k[vidx].max()) 1122 sum_max -= k[vidx].max(); 1123 } 1124 } else { 1125 vals[i]->cap(UBC,0); 1126 vals[i]->cap(LBC,0); 1127 vals[i]->maxlow(0); 1128 vals[i]->kmax(0); 1129 vals[i]->kmin(0); 1130 } 1131 1132 if (Card::propagate && (k[i].counter() == 0)) 1133 GECODE_ME_CHECK(k[i].lq(home, vals[i]->noe)); 1134 } 1135 1136 for (int i = n_val; i--; ) 1137 vals[i]->index(n_var + i); 1138 1139 return ES_OK; 1140 } 1141 1142 template<class Card> template<BC bc> 1143 forceinline bool 1144 VarValGraph<Card>::augmenting_path(Node* v) { 1145 Region r; 1146 NodeStack ns(r,n_node); 1147 BitSet visited(r,static_cast<unsigned int>(n_node)); 1148 Edge** start = r.alloc<Edge*>(n_node); 1149 1150 // keep track of the nodes that have already been visited 1151 Node* sn = v; 1152 1153 // mark the start partition 1154 bool sp = sn->type(); 1155 1156 // nodes in sp only follow free edges 1157 // nodes in V - sp only follow matched edges 1158 1159 for (int i = n_node; i--; ) 1160 if (i >= n_var) { 1161 vals[i-n_var]->inedge(nullptr); 1162 start[i] = vals[i-n_var]->first(); 1163 } else { 1164 vars[i]->inedge(nullptr); 1165 start[i] = vars[i]->first(); 1166 } 1167 1168 v->inedge(nullptr); 1169 ns.push(v); 1170 visited.set(static_cast<unsigned int>(v->index())); 1171 while (!ns.empty()) { 1172 Node* vv = ns.top(); 1173 Edge* e = nullptr; 1174 if (vv->type() == sp) { 1175 e = start[vv->index()]; 1176 while ((e != nullptr) && e->matched(bc)) 1177 e = e->next(vv->type()); 1178 } else { 1179 e = start[vv->index()]; 1180 while ((e != nullptr) && !e->matched(bc)) 1181 e = e->next(vv->type()); 1182 start[vv->index()] = e; 1183 } 1184 if (e != nullptr) { 1185 start[vv->index()] = e->next(vv->type()); 1186 Node* w = e->getMate(vv->type()); 1187 if (!visited.get(static_cast<unsigned int>(w->index()))) { 1188 // unexplored path 1189 bool m = w->type() ? 1190 static_cast<ValNode*>(w)->matched(bc) : 1191 static_cast<VarNode*>(w)->matched(bc); 1192 if (!m && w->type() != sp) { 1193 if (vv->inedge() != nullptr) { 1194 // augmenting path of length l > 1 1195 e->match(bc); 1196 break; 1197 } else { 1198 // augmenting path of length l = 1 1199 e->match(bc); 1200 ns.pop(); 1201 return true; 1202 } 1203 } else { 1204 w->inedge(e); 1205 visited.set(static_cast<unsigned int>(w->index())); 1206 // find matching edge m incident with w 1207 ns.push(w); 1208 } 1209 } 1210 } else { 1211 // tried all outgoing edges without finding an augmenting path 1212 ns.pop(); 1213 } 1214 } 1215 1216 bool pathfound = !ns.empty(); 1217 1218 while (!ns.empty()) { 1219 Node* t = ns.pop(); 1220 if (t != sn) { 1221 Edge* in = t->inedge(); 1222 if (t->type() != sp) { 1223 in->match(bc); 1224 } else if (!sp) { 1225 in->unmatch(bc,!sp); 1226 } else { 1227 in->unmatch(bc); 1228 } 1229 } 1230 } 1231 return pathfound; 1232 } 1233 1234 1235 template<class Card> 1236 inline ExecStatus 1237 VarValGraph<Card>::sync(ViewArray<IntView>& x, ViewArray<Card>& k) { 1238 Region r; 1239 // A node can be pushed twice (once when checking cardinality and later again) 1240 NodeStack re(r,2*n_node); 1241 1242 // synchronize cardinality variables 1243 if (Card::propagate) { 1244 for (int i = n_val; i--; ) { 1245 ValNode* v = vals[i]; 1246 int inc_ubc = v->incid_match(UBC); 1247 int inc_lbc = v->incid_match(LBC); 1248 if (v->noe == 0) { 1249 inc_ubc = 0; 1250 inc_lbc = 0; 1251 } 1252 int rm = v->kmax() - k[i].max(); 1253 // the cardinality bounds have been modified 1254 if ((k[i].max() < v->kmax()) || (k[i].min() > v->kmin())) { 1255 if ((k[i].max() != k[i].counter()) || (k[i].max() == 0)) { 1256 // update the bounds 1257 v->kmax(k[i].max()); 1258 v->kmin(k[i].min()); 1259 1260 //everything is fine 1261 if (inc_ubc <= k[i].max()) { 1262 // adjust capacities 1263 v->cap(UBC, k[i].max() - inc_ubc); 1264 v->maxlow(k[i].max() - inc_lbc); 1265 if (v->kmin() == v->kmax()) 1266 v->cap(LBC, k[i].max() - inc_lbc); 1267 } else { 1268 // set cap to max and resolve conflicts on view side 1269 // set to full capacity for later rescheduling 1270 if (v->cap(UBC)) 1271 v->cap(UBC,k[i].max()); 1272 v->maxlow(k[i].max() - (inc_lbc)); 1273 if (v->kmin() == v->kmax()) 1274 v->cap(LBC,k[i].max() - (inc_lbc)); 1275 v->card_conflict(rm); 1276 } 1277 } 1278 } 1279 if (inc_lbc < k[i].min() && v->noe > 0) { 1280 v->cap(LBC, k[i].min() - inc_lbc); 1281 re.push(v); 1282 } 1283 } 1284 1285 for (int i = n_var; i--; ) { 1286 Edge* mub = vars[i]->get_match(UBC); 1287 if (mub != nullptr) { 1288 ValNode* vu = mub->getVal(); 1289 if ((vars[i]->noe != 1) && vu->card_conflict()) { 1290 vu->red_conflict(); 1291 mub->unmatch(UBC,vars[i]->type()); 1292 re.push(vars[i]); 1293 } 1294 } 1295 } 1296 } 1297 1298 // go on with synchronization 1299 assert(x.size() == n_var); 1300 for (int i = n_var; i--; ) { 1301 1302 VarNode* vrn = vars[i]; 1303 if (static_cast<int>(x[i].size()) != vrn->noe) { 1304 // if the variable is already assigned 1305 if (x[i].assigned()) { 1306 int v = x[i].val(); 1307 Edge* mub = vrn->get_match(UBC); 1308 if ((mub != nullptr) && (v != mub->getVal()->val)) { 1309 mub->unmatch(UBC); 1310 re.push(vars[i]); 1311 } 1312 1313 Edge* mlb = vrn->get_match(LBC); 1314 if (mlb != nullptr) { 1315 ValNode* vln = mlb->getVal(); 1316 if (v != vln->val) { 1317 mlb->unmatch(LBC); 1318 if (vln->incid_match(LBC) < vln->kmin()) 1319 re.push(vln); 1320 } 1321 } 1322 1323 for (Edge* e = vrn->first(); e != nullptr; e = e->next()) { 1324 ValNode* vln = e->getVal(); 1325 if (vln->val != v) { 1326 vrn->noe--; 1327 e->getVal()->noe--; 1328 e->del_edge(); 1329 e->unlink(); 1330 } 1331 } 1332 } else { 1333 1334 // delete the edge 1335 ViewValues<IntView> xiter(x[i]); 1336 Edge* mub = vrn->get_match(UBC); 1337 Edge* mlb = vrn->get_match(LBC); 1338 Edge** p = vrn->adj(); 1339 Edge* e = *p; 1340 GECODE_ASSUME(e != nullptr); 1341 do { 1342 // search the edge that has to be deleted 1343 while ((e != nullptr) && (e->getVal()->val < xiter.val())) { 1344 // Skip edge 1345 e->getVal()->noe--; 1346 vrn->noe--; 1347 e->del_edge(); 1348 e->unlink(); 1349 e = e ->next(); 1350 *p = e; 1351 } 1352 GECODE_ASSUME(e != nullptr); 1353 1354 assert(xiter.val() == e->getVal()->val); 1355 1356 // This edge must be kept 1357 e->free(UBC); 1358 e->free(LBC); 1359 ++xiter; 1360 p = e->next_ref(); 1361 e = e->next(); 1362 } while (xiter()); 1363 *p = nullptr; 1364 while (e != nullptr) { 1365 e->getVar()->noe--; 1366 e->getVal()->noe--; 1367 e->del_edge(); 1368 e->unlink(); 1369 e = e->next(); 1370 } 1371 1372 if ((mub != nullptr) && mub->deleted()) { 1373 mub->unmatch(UBC); 1374 re.push(vars[i]); 1375 } 1376 1377 //lower bound matching can be zero 1378 if ((mlb != nullptr) && mlb->deleted()) { 1379 ValNode* vln = mlb->getVal(); 1380 mlb->unmatch(LBC); 1381 if (vln->incid_match(LBC) < vln->kmin()) 1382 re.push(vln); 1383 } 1384 } 1385 } 1386 vars[i]->index(i); 1387 } 1388 1389 for (int i = n_val; i--; ) { 1390 if ((k[i].min() > vals[i]->noe) && (k[i].counter() == 0)) 1391 return ES_FAILED; 1392 vals[i]->index(n_var + i); 1393 } 1394 1395 // start repair 1396 while (!re.empty()) { 1397 Node* n = re.pop(); 1398 if (!n->removed()) { 1399 if (!n->type()) { 1400 VarNode* vrn = static_cast<VarNode*>(n); 1401 if (!vrn->matched(UBC) && !augmenting_path<UBC>(vrn)) 1402 return ES_FAILED; 1403 } else { 1404 ValNode* vln = static_cast<ValNode*>(n); 1405 while (!vln->matched(LBC)) 1406 if (!augmenting_path<LBC>(vln)) 1407 return ES_FAILED; 1408 } 1409 } 1410 } 1411 1412 return ES_OK; 1413 } 1414 1415 template<class Card> template<BC bc> 1416 inline ExecStatus 1417 VarValGraph<Card>::narrow(Space& home, 1418 ViewArray<IntView>& x, ViewArray<Card>& k) { 1419 for (int i = n_var; i--; ) 1420 if (vars[i]->noe == 1) { 1421 ValNode* v = vars[i]->first()->getVal(); 1422 vars[i]->first()->free(bc); 1423 GECODE_ME_CHECK(x[i].eq(home, v->val)); 1424 v->inc(); 1425 } 1426 1427 for (int i = n_val; i--; ) { 1428 ValNode* v = vals[i]; 1429 if (Card::propagate && (k[i].counter() == 0)) 1430 GECODE_ME_CHECK(k[i].lq(home, v->noe)); 1431 if (v->noe > 0) { 1432 if (Card::propagate) 1433 GECODE_ME_CHECK(k[i].lq(home, v->noe)); 1434 1435 // If the maximum number of occurences of a value is reached 1436 // it cannot be consumed by another view 1437 1438 if (v->kcount() == v->kmax()) { 1439 int vidx = v->kindex(); 1440 1441 k[i].counter(v->kcount()); 1442 1443 if (Card::propagate) 1444 GECODE_ME_CHECK(k[i].eq(home, k[i].counter())); 1445 1446 bool delall = v->card_conflict() && (v->noe > v->kmax()); 1447 1448 for (Edge* e = v->last(); e != nullptr; e = e->vprev()) { 1449 VarNode* vrn = e->getVar(); 1450 if (vrn->noe == 1) { 1451 vrn->noe--; 1452 v->noe--; 1453 int vi= vrn->index(); 1454 1455 x.move_lst(vi); 1456 vars[vi] = vars[--n_var]; 1457 vars[vi]->index(vi); 1458 n_node--; 1459 e->del_edge(); 1460 e->unlink(); 1461 1462 } else if (delall) { 1463 GECODE_ME_CHECK(x[vrn->index()].nq(home, v->val)); 1464 vrn->noe--; 1465 v->noe--; 1466 e->del_edge(); 1467 e->unlink(); 1468 } 1469 } 1470 v->cap(UBC,0); 1471 v->cap(LBC,0); 1472 v->maxlow(0); 1473 if (sum_min >= k[vidx].min()) 1474 sum_min -= k[vidx].min(); 1475 if (sum_max >= k[vidx].max()) 1476 sum_max -= k[vidx].max(); 1477 1478 } else if (v->kcount() > 0) { 1479 v->kcount(0); 1480 } 1481 } 1482 } 1483 for (int i = n_var; i--; ) 1484 vars[i]->index(i); 1485 1486 for (int i = n_val; i--; ) { 1487 if (vals[i]->noe == 0) { 1488 vals[i]->cap(UBC,0); 1489 vals[i]->cap(LBC,0); 1490 vals[i]->maxlow(0); 1491 } 1492 vals[i]->index(n_var + i); 1493 } 1494 1495 for (int i = n_var; i--; ) { 1496 if (vars[i]->noe > 1) { 1497 for (Edge* e = vars[i]->first(); e != nullptr; e = e->next()) { 1498 if (!e->matched(bc) && !e->used(bc)) { 1499 GECODE_ME_CHECK(x[i].nq(home, e->getVal()->val)); 1500 } else { 1501 e->free(bc); 1502 } 1503 } 1504 } 1505 } 1506 return ES_OK; 1507 } 1508 1509 template<class Card> template<BC bc> 1510 inline ExecStatus 1511 VarValGraph<Card>::maximum_matching(void) { 1512 int card_match = 0; 1513 // find an intial matching in O(n*d) 1514 // greedy algorithm 1515 for (int i = n_val; i--; ) 1516 for (Edge* e = vals[i]->first(); e != nullptr ; e = e->vnext()) 1517 if (!e->getVar()->matched(bc) && !vals[i]->matched(bc)) { 1518 e->match(bc); card_match++; 1519 } 1520 1521 Region r; 1522 switch (bc) { 1523 case LBC: 1524 if (card_match < sum_min) { 1525 Support::StaticStack<ValNode*,Region> free(r,n_val); 1526 1527 // find failed nodes 1528 for (int i = n_val; i--; ) 1529 if (!vals[i]->matched(LBC)) 1530 free.push(vals[i]); 1531 1532 while (!free.empty()) { 1533 ValNode* v = free.pop(); 1534 while (!v->matched(LBC)) 1535 if (augmenting_path<LBC>(v)) 1536 card_match++; 1537 else 1538 break; 1539 } 1540 1541 return (card_match >= sum_min) ? ES_OK : ES_FAILED; 1542 } else { 1543 return ES_OK; 1544 } 1545 break; 1546 case UBC: 1547 if (card_match < n_var) { 1548 Support::StaticStack<VarNode*,Region> free(r,n_var); 1549 1550 // find failed nodes 1551 for (int i = n_var; i--; ) 1552 if (!vars[i]->matched(UBC)) 1553 free.push(vars[i]); 1554 1555 while (!free.empty()) { 1556 VarNode* v = free.pop(); 1557 if (!v->matched(UBC) && augmenting_path<UBC>(v)) 1558 card_match++; 1559 } 1560 1561 return (card_match >= n_var) ? ES_OK : ES_FAILED; 1562 } else { 1563 return ES_OK; 1564 } 1565 break; 1566 default: GECODE_NEVER; 1567 } 1568 GECODE_NEVER; 1569 return ES_FAILED; 1570 } 1571 1572 1573 template<class Card> template<BC bc> 1574 forceinline void 1575 VarValGraph<Card>::free_alternating_paths(void) { 1576 Region r; 1577 NodeStack ns(r,n_node); 1578 BitSet visited(r,static_cast<unsigned int>(n_node)); 1579 1580 switch (bc) { 1581 case LBC: 1582 // after a maximum matching on the value nodes there still can be 1583 // free value nodes, hence we have to consider ALL nodes whether 1584 // they are the starting point of an even alternating path in G 1585 for (int i = n_var; i--; ) 1586 if (!vars[i]->matched(LBC)) { 1587 ns.push(vars[i]); 1588 visited.set(static_cast<unsigned int>(vars[i]->index())); 1589 } 1590 for (int i = n_val; i--; ) 1591 if (!vals[i]->matched(LBC)) { 1592 ns.push(vals[i]); 1593 visited.set(static_cast<unsigned int>(vals[i]->index())); 1594 } 1595 break; 1596 case UBC: 1597 // clearly, after a maximum matching on the x variables 1598 // corresponding to a set cover on x there are NO free var nodes 1599 for (int i = n_val; i--; ) 1600 if (!vals[i]->matched(UBC)) { 1601 ns.push(vals[i]); 1602 visited.set(static_cast<unsigned int>(vals[i]->index())); 1603 } 1604 break; 1605 default: GECODE_NEVER; 1606 } 1607 1608 while (!ns.empty()) { 1609 Node* node = ns.pop(); 1610 if (node->type()) { 1611 // ValNode 1612 ValNode* vln = static_cast<ValNode*>(node); 1613 1614 for (Edge* cur = vln->first(); cur != nullptr; cur = cur->vnext()) { 1615 VarNode* mate = cur->getVar(); 1616 switch (bc) { 1617 case LBC: 1618 if (cur->matched(LBC)) { 1619 // mark the edge 1620 cur->use(LBC); 1621 if (!visited.get(static_cast<unsigned int>(mate->index()))) { 1622 ns.push(mate); 1623 visited.set(static_cast<unsigned int>(mate->index())); 1624 } 1625 } 1626 break; 1627 case UBC: 1628 if (!cur->matched(UBC)) { 1629 // mark the edge 1630 cur->use(UBC); 1631 if (!visited.get(static_cast<unsigned int>(mate->index()))) { 1632 ns.push(mate); 1633 visited.set(static_cast<unsigned int>(mate->index())); 1634 } 1635 } 1636 break; 1637 default: GECODE_NEVER; 1638 } 1639 } 1640 1641 } else { 1642 // VarNode 1643 VarNode* vrn = static_cast<VarNode*>(node); 1644 1645 switch (bc) { 1646 case LBC: 1647 // after LBC-matching we can follow every unmatched edge 1648 for (Edge* cur = vrn->first(); cur != nullptr; cur = cur->next()) { 1649 ValNode* mate = cur->getVal(); 1650 if (!cur->matched(LBC)) { 1651 cur->use(LBC); 1652 if (!visited.get(static_cast<unsigned int>(mate->index()))) { 1653 ns.push(mate); 1654 visited.set(static_cast<unsigned int>(mate->index())); 1655 } 1656 } 1657 } 1658 break; 1659 case UBC: 1660 // after UBC-matching we can only follow a matched edge 1661 { 1662 Edge* cur = vrn->get_match(UBC); 1663 if (cur != nullptr) { 1664 cur->use(UBC); 1665 ValNode* mate = cur->getVal(); 1666 if (!visited.get(static_cast<unsigned int>(mate->index()))) { 1667 ns.push(mate); 1668 visited.set(static_cast<unsigned int>(mate->index())); 1669 } 1670 } 1671 } 1672 break; 1673 default: GECODE_NEVER; 1674 } 1675 } 1676 } 1677 } 1678 1679 template<class Card> template<BC bc> 1680 void 1681 VarValGraph<Card>::dfs(Node* v, 1682 BitSet& inscc, BitSet& in_unfinished, int dfsnum[], 1683 NodeStack& roots, NodeStack& unfinished, 1684 int& count) { 1685 count++; 1686 int v_index = v->index(); 1687 dfsnum[v_index] = count; 1688 inscc.set(static_cast<unsigned int>(v_index)); 1689 in_unfinished.set(static_cast<unsigned int>(v_index)); 1690 1691 unfinished.push(v); 1692 roots.push(v); 1693 for (Edge* e = v->first(); e != nullptr; e = e->next(v->type())) { 1694 bool m; 1695 switch (bc) { 1696 case LBC: 1697 m = v->type() ? e->matched(LBC) : !e->matched(LBC); 1698 break; 1699 case UBC: 1700 m = v->type() ? !e->matched(UBC) : e->matched(UBC); 1701 break; 1702 default: GECODE_NEVER; 1703 } 1704 if (m) { 1705 Node* w = e->getMate(v->type()); 1706 int w_index = w->index(); 1707 1708 assert(w_index < n_node); 1709 if (!inscc.get(static_cast<unsigned int>(w_index))) { 1710 // w is an uncompleted scc 1711 w->inedge(e); 1712 dfs<bc>(w, inscc, in_unfinished, dfsnum, 1713 roots, unfinished, count); 1714 } else if (in_unfinished.get(static_cast<unsigned int>(w_index))) { 1715 // even alternating cycle found mark the edge closing the cycle, 1716 // completing the scc 1717 e->use(bc); 1718 // if w belongs to an scc we detected earlier 1719 // merge components 1720 assert(roots.top()->index() < n_node); 1721 while (dfsnum[roots.top()->index()] > dfsnum[w_index]) { 1722 roots.pop(); 1723 } 1724 } 1725 } 1726 } 1727 1728 if (v == roots.top()) { 1729 while (v != unfinished.top()) { 1730 // w belongs to the scc with root v 1731 Node* w = unfinished.top(); 1732 w->inedge()->use(bc); 1733 in_unfinished.clear(static_cast<unsigned int>(w->index())); 1734 unfinished.pop(); 1735 } 1736 assert(v == unfinished.top()); 1737 in_unfinished.clear(static_cast<unsigned int>(v_index)); 1738 roots.pop(); 1739 unfinished.pop(); 1740 } 1741 } 1742 1743 template<class Card> template<BC bc> 1744 forceinline void 1745 VarValGraph<Card>::strongly_connected_components(void) { 1746 Region r; 1747 BitSet inscc(r,static_cast<unsigned int>(n_node)); 1748 BitSet in_unfinished(r,static_cast<unsigned int>(n_node)); 1749 int* dfsnum = r.alloc<int>(n_node); 1750 1751 for (int i = n_node; i--; ) 1752 dfsnum[i]=0; 1753 1754 int count = 0; 1755 NodeStack roots(r,n_node); 1756 NodeStack unfinished(r,n_node); 1757 1758 for (int i = n_var; i--; ) 1759 dfs<bc>(vars[i], inscc, in_unfinished, dfsnum, 1760 roots, unfinished, count); 1761 } 1762 1763 template<class Card> 1764 forceinline void* 1765 VarValGraph<Card>::operator new(size_t t, Space& home) { 1766 return home.ralloc(t); 1767 } 1768 1769}}} 1770 1771// STATISTICS: int-prop 1772 1773