00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <string.h>
00017 #include <algorithm>
00018 #include <string>
00019 #include <vector>
00020
00021 #include "base/integral_types.h"
00022 #include "base/logging.h"
00023 #include "base/scoped_ptr.h"
00024 #include "base/stringprintf.h"
00025 #include "base/concise_iterator.h"
00026 #include "constraint_solver/constraint_solver.h"
00027 #include "constraint_solver/constraint_solveri.h"
00028 #include "util/string_array.h"
00029
00030 namespace operations_research {
00031
00032
00033
00034
00035
00036 namespace {
00037 class CountValueEqCst : public Constraint {
00038 public:
00039 CountValueEqCst(Solver* const s,
00040 const IntVar* const* vars,
00041 int size,
00042 int64 value,
00043 int64 count);
00044 virtual ~CountValueEqCst() {}
00045
00046 virtual void Post();
00047 virtual void InitialPropagate();
00048 void OneBound(int index);
00049 void OneDomain(int index);
00050 void CardMin();
00051 void CardMax();
00052 virtual string DebugString() const;
00053
00054 virtual void Accept(ModelVisitor* const visitor) const {
00055 visitor->BeginVisitConstraint(ModelVisitor::kCountEqual, this);
00056 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00057 vars_.get(),
00058 size_);
00059 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
00060 visitor->VisitIntegerArgument(ModelVisitor::kCountArgument, count_);
00061 visitor->EndVisitConstraint(ModelVisitor::kCountEqual, this);
00062 }
00063
00064 private:
00065 scoped_array<IntVar*> vars_;
00066 int size_;
00067 int64 value_;
00068 RevBitSet undecided_;
00069 int64 count_;
00070 NumericalRev<int> min_;
00071 NumericalRev<int> max_;
00072 };
00073
00074 CountValueEqCst::CountValueEqCst(Solver* const s,
00075 const IntVar* const* vars,
00076 int size,
00077 int64 value,
00078 int64 count)
00079 : Constraint(s), vars_(new IntVar*[size]), size_(size),
00080 value_(value), undecided_(size), count_(count),
00081 min_(0), max_(0) {
00082 memcpy(vars_.get(), vars, size * sizeof(*vars));
00083 }
00084
00085 string CountValueEqCst::DebugString() const {
00086 return StringPrintf("CountValueEqCst([%s], value=%" GG_LL_FORMAT
00087 "d, count=%" GG_LL_FORMAT "d)",
00088 DebugStringArray(vars_.get(), size_, ", ").c_str(),
00089 value_,
00090 count_);
00091 }
00092
00093 void CountValueEqCst::Post() {
00094 for (int i = 0; i < size_; ++i) {
00095 IntVar* const var = vars_[i];
00096 if (!var->Bound()) {
00097 Demon* d = MakeConstraintDemon1(solver(),
00098 this,
00099 &CountValueEqCst::OneBound,
00100 "OneBound",
00101 i);
00102 var->WhenBound(d);
00103 if (var->Contains(value_)) {
00104 d = MakeConstraintDemon1(solver(),
00105 this,
00106 &CountValueEqCst::OneDomain,
00107 "OneDomain",
00108 i);
00109 var->WhenDomain(d);
00110 }
00111 }
00112 }
00113 }
00114
00115 void CountValueEqCst::InitialPropagate() {
00116 int min = 0;
00117 int max = 0;
00118 int i;
00119 Solver* const s = solver();
00120 for (i = 0; i < size_; ++i) {
00121 IntVar* const var = vars_[i];
00122 if (var->Bound()) {
00123 if (var->Min() == value_) {
00124 min++;
00125 max++;
00126 }
00127 } else {
00128 if (var->Contains(value_)) {
00129 max++;
00130 undecided_.SetToOne(s, i);
00131 }
00132 }
00133 }
00134 if (count_ < min || count_ > max) {
00135 s->Fail();
00136 }
00137 if (count_ == min) {
00138 CardMin();
00139 } else if (count_ == max) {
00140 CardMax();
00141 }
00142 min_.SetValue(s, min);
00143 max_.SetValue(s, max);
00144 }
00145
00146 void CountValueEqCst::OneBound(int index) {
00147 IntVar* const var = vars_[index];
00148 Solver* const s = solver();
00149 if (undecided_.IsSet(index)) {
00150 undecided_.SetToZero(s, index);
00151 if (var->Min() == value_) {
00152 min_.Incr(s);
00153 if (min_.Value() == count_) {
00154 CardMin();
00155 }
00156 } else {
00157 max_.Decr(s);
00158 if (max_.Value() == count_) {
00159 CardMax();
00160 }
00161 }
00162 }
00163 }
00164
00165 void CountValueEqCst::OneDomain(int index) {
00166 Solver* const s = solver();
00167 if (undecided_.IsSet(index) && !vars_[index]->Contains(value_)) {
00168 max_.Decr(s);
00169 undecided_.SetToZero(s, index);
00170 if (max_.Value() == count_) {
00171 CardMax();
00172 }
00173 }
00174 }
00175
00176 void CountValueEqCst::CardMin() {
00177 int i;
00178 for (i = 0; i < size_; ++i) {
00179 if (undecided_.IsSet(i)) {
00180 vars_[i]->RemoveValue(value_);
00181 }
00182 }
00183 }
00184
00185 void CountValueEqCst::CardMax() {
00186 int i;
00187 for (i = 0; i < size_; ++i) {
00188 if (undecided_.IsSet(i)) {
00189 vars_[i]->SetValue(value_);
00190 }
00191 }
00192 }
00193
00194 }
00195 Constraint* Solver::MakeCount(const std::vector<IntVar*>& vars, int64 v, int64 c) {
00196 for (ConstIter<std::vector<IntVar*> > it(vars); !it.at_end(); ++it) {
00197 CHECK_EQ(this, (*it)->solver());
00198 }
00199 return RevAlloc(new CountValueEqCst(this, vars.data(), vars.size(), v, c));
00200 }
00201
00202
00203
00204
00205
00206 namespace {
00207 class CountValueEq : public Constraint {
00208 public:
00209 CountValueEq(Solver* const s,
00210 const IntVar* const* vars,
00211 int size,
00212 int64 value,
00213 IntVar* count);
00214 virtual ~CountValueEq() {}
00215
00216 virtual void Post();
00217 virtual void InitialPropagate();
00218 void OneBound(int index);
00219 void OneDomain(int index);
00220 void CountVar();
00221 void CardMin();
00222 void CardMax();
00223 virtual string DebugString() const;
00224
00225 virtual void Accept(ModelVisitor* const visitor) const {
00226 visitor->BeginVisitConstraint(ModelVisitor::kCountEqual, this);
00227 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00228 vars_.get(),
00229 size_);
00230 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, value_);
00231 visitor->VisitIntegerExpressionArgument(ModelVisitor::kCountArgument,
00232 count_);
00233 visitor->EndVisitConstraint(ModelVisitor::kCountEqual, this);
00234 }
00235
00236 private:
00237 scoped_array<IntVar*> vars_;
00238 int size_;
00239 int64 value_;
00240 RevBitSet undecided_;
00241 IntVar* const count_;
00242 NumericalRev<int> min_;
00243 NumericalRev<int> max_;
00244 };
00245
00246 CountValueEq::CountValueEq(Solver* const s, const IntVar* const* vars, int size,
00247 int64 value, IntVar* count)
00248 : Constraint(s), vars_(new IntVar*[size]), size_(size),
00249 value_(value), undecided_(size), count_(count), min_(kint32min),
00250 max_(kint32max) {
00251 memcpy(vars_.get(), vars, size * sizeof(*vars));
00252 }
00253
00254 string CountValueEq::DebugString() const {
00255 return StringPrintf("CountValueEq([%s], value = %" GG_LL_FORMAT
00256 "d, count = %s)",
00257 DebugStringArray(vars_.get(), size_, ", ").c_str(),
00258 value_,
00259 count_->DebugString().c_str());
00260 }
00261
00262 void CountValueEq::Post() {
00263 for (int i = 0; i < size_; ++i) {
00264 IntVar* const var = vars_[i];
00265 if (!var->Bound()) {
00266 Demon* d = MakeConstraintDemon1(solver(),
00267 this,
00268 &CountValueEq::OneBound,
00269 "OneBound",
00270 i);
00271 var->WhenBound(d);
00272 if (var->Contains(value_)) {
00273 d = MakeConstraintDemon1(solver(),
00274 this,
00275 &CountValueEq::OneDomain,
00276 "OneDomain",
00277 i);
00278 var->WhenDomain(d);
00279 }
00280 }
00281 }
00282 if (!count_->Bound()) {
00283 Demon* d = MakeConstraintDemon0(solver(),
00284 this,
00285 &CountValueEq::CountVar,
00286 "Var");
00287 count_->WhenRange(d);
00288 }
00289 }
00290
00291 void CountValueEq::InitialPropagate() {
00292 int min = 0;
00293 int max = 0;
00294 int i;
00295 Solver* const s = solver();
00296 for (i = 0; i < size_; ++i) {
00297 IntVar* const var = vars_[i];
00298 if (var->Bound()) {
00299 if (var->Min() == value_) {
00300 min++;
00301 max++;
00302 }
00303 } else {
00304 if (var->Contains(value_)) {
00305 max++;
00306 undecided_.SetToOne(s, i);
00307 }
00308 }
00309 }
00310 count_->SetRange(min, max);
00311 if (count_->Max() == min) {
00312 CardMin();
00313 } else if (count_->Min() == max) {
00314 CardMax();
00315 }
00316 min_.SetValue(s, min);
00317 max_.SetValue(s, max);
00318 }
00319
00320 void CountValueEq::OneBound(int index) {
00321 IntVar* const var = vars_[index];
00322 Solver* const s = solver();
00323 if (undecided_.IsSet(index)) {
00324 undecided_.SetToZero(s, index);
00325 if (var->Min() == value_) {
00326 min_.Incr(s);
00327 count_->SetMin(min_.Value());
00328 if (min_.Value() == count_->Max()) {
00329 CardMin();
00330 }
00331 } else {
00332 max_.Decr(s);
00333 count_->SetMax(max_.Value());
00334 if (max_.Value() == count_->Min()) {
00335 CardMax();
00336 }
00337 }
00338 }
00339 }
00340
00341 void CountValueEq::OneDomain(int index) {
00342 Solver* const s = solver();
00343 if (undecided_.IsSet(index) && !vars_[index]->Contains(value_)) {
00344 max_.Decr(s);
00345 undecided_.SetToZero(s, index);
00346 count_->SetMax(max_.Value());
00347 if (max_.Value() == count_->Min()) {
00348 CardMax();
00349 }
00350 }
00351 }
00352
00353 void CountValueEq::CountVar() {
00354 if (count_->Min() > max_.Value()) {
00355 solver()->Fail();
00356 }
00357 if (count_->Min() == max_.Value()) {
00358 CardMax();
00359 }
00360 if (count_->Max() < min_.Value()) {
00361 solver()->Fail();
00362 }
00363 if (count_->Max() == min_.Value()) {
00364 CardMin();
00365 }
00366 }
00367
00368 void CountValueEq::CardMin() {
00369 int i;
00370 for (i = 0; i < size_; ++i) {
00371 if (undecided_.IsSet(i)) {
00372 vars_[i]->RemoveValue(value_);
00373 }
00374 }
00375 }
00376
00377 void CountValueEq::CardMax() {
00378 int i;
00379 for (i = 0; i < size_; ++i) {
00380 if (undecided_.IsSet(i)) {
00381 vars_[i]->SetValue(value_);
00382 }
00383 }
00384 }
00385
00386 }
00387 Constraint* Solver::MakeCount(const std::vector<IntVar*>& vars, int64 v, IntVar* c) {
00388 for (ConstIter<std::vector<IntVar*> > it(vars); !it.at_end(); ++it) {
00389 CHECK_EQ(this, (*it)->solver());
00390 }
00391 CHECK_EQ(this, c->solver());
00392 return RevAlloc(new CountValueEq(this, vars.data(), vars.size(), v, c));
00393 }
00394
00395
00396
00397 namespace {
00398 class Distribute : public Constraint {
00399 public:
00400 Distribute(Solver* const s,
00401 const IntVar* const * vars,
00402 int vsize,
00403 const int64* values,
00404 const IntVar* const * cards,
00405 int csize);
00406 Distribute(Solver* const s,
00407 const IntVar* const * vars,
00408 int vsize,
00409 const int* values,
00410 const IntVar* const * cards,
00411 int csize);
00412 virtual ~Distribute() {}
00413
00414 virtual void Post();
00415 virtual void InitialPropagate();
00416 void OneBound(int vindex);
00417 void OneDomain(int vindex);
00418 void CountVar(int cindex);
00419 void CardMin(int cindex);
00420 void CardMax(int cindex);
00421 virtual string DebugString() const;
00422
00423 virtual void Accept(ModelVisitor* const visitor) const {
00424 visitor->BeginVisitConstraint(ModelVisitor::kDistribute, this);
00425 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00426 vars_.get(),
00427 var_size_);
00428 visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
00429 values_.get(),
00430 card_size_);
00431 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kCardsArgument,
00432 cards_.get(),
00433 card_size_);
00434 visitor->EndVisitConstraint(ModelVisitor::kDistribute, this);
00435 }
00436
00437 private:
00438 const scoped_array<IntVar*> vars_;
00439 const int var_size_;
00440 const scoped_array<int64> values_;
00441 const scoped_array<IntVar*> cards_;
00442 const int card_size_;
00443 RevBitMatrix undecided_;
00444 NumericalRevArray<int> min_;
00445 NumericalRevArray<int> max_;
00446 };
00447
00448 Distribute::Distribute(Solver* const s,
00449 const IntVar* const * vars,
00450 int vsize,
00451 const int64* values,
00452 const IntVar* const * cards,
00453 int csize)
00454 : Constraint(s),
00455 vars_(new IntVar*[vsize]),
00456 var_size_(vsize),
00457 values_(new int64[csize]),
00458 cards_(new IntVar*[csize]),
00459 card_size_(csize),
00460 undecided_(var_size_, card_size_),
00461 min_(card_size_, 0),
00462 max_(card_size_, 0) {
00463 memcpy(vars_.get(), vars, var_size_ * sizeof(*vars));
00464 memcpy(values_.get(), values, card_size_ * sizeof(*values));
00465 memcpy(cards_.get(), cards, card_size_ * sizeof(*cards));
00466 }
00467
00468 Distribute::Distribute(Solver* const s,
00469 const IntVar* const * vars,
00470 int vsize,
00471 const int* values,
00472 const IntVar* const * cards,
00473 int csize)
00474 : Constraint(s),
00475 vars_(new IntVar*[vsize]),
00476 var_size_(vsize),
00477 values_(new int64[csize]),
00478 cards_(new IntVar*[csize]),
00479 card_size_(csize),
00480 undecided_(var_size_, card_size_),
00481 min_(card_size_, 0),
00482 max_(card_size_, 0) {
00483 memcpy(vars_.get(), vars, var_size_ * sizeof(*vars));
00484 memcpy(cards_.get(), cards, card_size_ * sizeof(*cards));
00485 for (int i = 0; i < card_size_; ++i) {
00486 values_[i] = values[i];
00487 }
00488 }
00489
00490 string Distribute::DebugString() const {
00491 return StringPrintf(
00492 "Distribute(vars = [%s], values = [%s], cards = [%s])",
00493 DebugStringArray(vars_.get(), var_size_, ", ").c_str(),
00494 Int64ArrayToString(values_.get(), card_size_, ", ").c_str(),
00495 DebugStringArray(cards_.get(), card_size_, ", ").c_str());
00496 }
00497
00498 void Distribute::Post() {
00499 for (int i = 0; i < var_size_; ++i) {
00500 IntVar* const var = vars_[i];
00501 if (!var->Bound()) {
00502 Demon* d = MakeConstraintDemon1(solver(),
00503 this,
00504 &Distribute::OneBound,
00505 "OneBound",
00506 i);
00507 var->WhenBound(d);
00508 d = MakeConstraintDemon1(solver(),
00509 this,
00510 &Distribute::OneDomain,
00511 "OneDomain",
00512 i);
00513 var->WhenDomain(d);
00514 }
00515 }
00516 for (int i = 0; i < card_size_; ++i) {
00517 if (!cards_[i]->Bound()) {
00518 Demon* d = MakeConstraintDemon1(solver(),
00519 this,
00520 &Distribute::CountVar,
00521 "Var",
00522 i);
00523 cards_[i]->WhenRange(d);
00524 }
00525 }
00526 }
00527
00528 void Distribute::InitialPropagate() {
00529 Solver* const s = solver();
00530 for (int j = 0; j < card_size_; ++j) {
00531 int min = 0;
00532 int max = 0;
00533 for (int i = 0; i < var_size_; ++i) {
00534 IntVar* const var = vars_[i];
00535 if (var->Bound()) {
00536 if (var->Min() == values_[j]) {
00537 min++;
00538 max++;
00539 }
00540 } else {
00541 if (var->Contains(values_[j])) {
00542 max++;
00543 undecided_.SetToOne(s, i, j);
00544 }
00545 }
00546 }
00547 cards_[j]->SetRange(min, max);
00548 if (cards_[j]->Max() == min) {
00549 CardMin(j);
00550 } else if (cards_[j]->Min() == max) {
00551 CardMax(j);
00552 }
00553 min_.SetValue(s, j, min);
00554 max_.SetValue(s, j, max);
00555 }
00556 }
00557
00558 void Distribute::OneBound(int index) {
00559 IntVar* const var = vars_[index];
00560 Solver* const s = solver();
00561 for (int j = 0; j < card_size_; ++j) {
00562 if (undecided_.IsSet(index, j)) {
00563 undecided_.SetToZero(s, index, j);
00564 if (var->Min() == values_[j]) {
00565 min_.Incr(s, j);
00566 cards_[j]->SetMin(min_[j]);
00567 if (min_[j] == cards_[j]->Max()) {
00568 CardMin(j);
00569 }
00570 } else {
00571 max_.Decr(s, j);
00572 cards_[j]->SetMax(max_[j]);
00573 if (max_[j] == cards_[j]->Min()) {
00574 CardMax(j);
00575 }
00576 }
00577 }
00578 }
00579 }
00580
00581 void Distribute::OneDomain(int index) {
00582 IntVar* const var = vars_[index];
00583 Solver* const s = solver();
00584 for (int j = 0; j < card_size_; ++j) {
00585 if (undecided_.IsSet(index, j)) {
00586 if (!var->Contains(values_[j])) {
00587 undecided_.SetToZero(s, index, j);
00588 max_.Decr(s, j);
00589 cards_[j]->SetMax(max_[j]);
00590 if (max_[j] == cards_[j]->Min()) {
00591 CardMax(j);
00592 }
00593 }
00594 }
00595 }
00596 }
00597
00598 void Distribute::CountVar(int cindex) {
00599 if (cards_[cindex]->Min() > max_[cindex] ||
00600 cards_[cindex]->Max() < min_[cindex]) {
00601 solver()->Fail();
00602 }
00603 if (cards_[cindex]->Min() == max_[cindex]) {
00604 CardMax(cindex);
00605 }
00606 if (cards_[cindex]->Max() == min_[cindex]) {
00607 CardMin(cindex);
00608 }
00609 }
00610
00611 void Distribute::CardMin(int cindex) {
00612 for (int i = 0; i < var_size_; ++i) {
00613 if (undecided_.IsSet(i, cindex)) {
00614 vars_[i]->RemoveValue(values_[cindex]);
00615 }
00616 }
00617 }
00618
00619 void Distribute::CardMax(int cindex) {
00620 for (int i = 0; i < var_size_; ++i) {
00621 if (undecided_.IsSet(i, cindex)) {
00622 vars_[i]->SetValue(values_[cindex]);
00623 }
00624 }
00625 }
00626
00627
00628
00629 class FastDistribute : public Constraint {
00630 public:
00631 FastDistribute(Solver* const s,
00632 const IntVar* const * vars,
00633 int vsize,
00634 const IntVar* const * cards,
00635 int csize);
00636 virtual ~FastDistribute() {}
00637
00638 virtual void Post();
00639 virtual void InitialPropagate();
00640 void OneBound(int vindex);
00641 void OneDomain(int vindex);
00642 void CountVar(int card_index);
00643 void CardMin(int card_index);
00644 void CardMax(int card_index);
00645 virtual string DebugString() const;
00646 void SetRevCannotContribute(int64 var_index, int64 card_index) {
00647 Solver* const s = solver();
00648 undecided_.SetToZero(s, var_index, card_index);
00649 max_.Decr(s, card_index);
00650 cards_[card_index]->SetMax(max_[card_index]);
00651 if (max_[card_index] == cards_[card_index]->Min()) {
00652 CardMax(card_index);
00653 }
00654 }
00655 void SetRevDoContribute(int64 var_index, int64 card_index) {
00656 Solver* const s = solver();
00657 undecided_.SetToZero(s, var_index, card_index);
00658 min_.Incr(s, card_index);
00659 cards_[card_index]->SetMin(min_[card_index]);
00660 if (min_[card_index] == cards_[card_index]->Max()) {
00661 CardMin(card_index);
00662 }
00663 }
00664
00665 virtual void Accept(ModelVisitor* const visitor) const {
00666 visitor->BeginVisitConstraint(ModelVisitor::kDistribute, this);
00667 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00668 vars_.get(),
00669 var_size_);
00670 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kCardsArgument,
00671 cards_.get(),
00672 card_size_);
00673 visitor->EndVisitConstraint(ModelVisitor::kDistribute, this);
00674 }
00675
00676 private:
00677 const scoped_array<IntVar*> vars_;
00678 const int var_size_;
00679 const scoped_array<IntVar*> cards_;
00680 const int64 card_size_;
00681 RevBitMatrix undecided_;
00682 NumericalRevArray<int> min_;
00683 NumericalRevArray<int> max_;
00684 scoped_array<IntVarIterator*> holes_;
00685 };
00686
00687 FastDistribute::FastDistribute(Solver* const s,
00688 const IntVar* const * vars,
00689 int vsize,
00690 const IntVar* const * cards,
00691 int csize)
00692 : Constraint(s),
00693 vars_(new IntVar*[vsize]),
00694 var_size_(vsize),
00695 cards_(new IntVar*[csize]),
00696 card_size_(csize),
00697 undecided_(vsize, csize),
00698 min_(card_size_, 0),
00699 max_(card_size_, 0),
00700 holes_(new IntVarIterator*[var_size_]) {
00701 memcpy(vars_.get(), vars, var_size_ * sizeof(*vars));
00702 memcpy(cards_.get(), cards, card_size_ * sizeof(*cards));
00703 for (int var_index = 0; var_index < var_size_; ++var_index) {
00704 holes_[var_index] = vars_[var_index]->MakeHoleIterator(true);
00705 }
00706 }
00707
00708
00709 string FastDistribute::DebugString() const {
00710 return StringPrintf("FastDistribute(vars = [%s], cards = [%s])",
00711 DebugStringArray(vars_.get(), var_size_, ", ").c_str(),
00712 DebugStringArray(cards_.get(), card_size_, ", ").c_str());
00713 }
00714
00715 void FastDistribute::Post() {
00716 for (int var_index = 0; var_index < var_size_; ++var_index) {
00717 IntVar* const var = vars_[var_index];
00718 if (!var->Bound()) {
00719 Demon* d = MakeConstraintDemon1(solver(),
00720 this,
00721 &FastDistribute::OneBound,
00722 "OneBound",
00723 var_index);
00724 var->WhenBound(d);
00725 d = MakeConstraintDemon1(solver(),
00726 this,
00727 &FastDistribute::OneDomain,
00728 "OneDomain",
00729 var_index);
00730 var->WhenDomain(d);
00731 }
00732 }
00733 for (int card_index = 0; card_index < card_size_; ++card_index) {
00734 if (!cards_[card_index]->Bound()) {
00735 Demon* d = MakeConstraintDemon1(solver(),
00736 this,
00737 &FastDistribute::CountVar,
00738 "Var",
00739 card_index);
00740 cards_[card_index]->WhenRange(d);
00741 }
00742 }
00743 }
00744
00745 void FastDistribute::InitialPropagate() {
00746 Solver* const s = solver();
00747 for (int card_index = 0; card_index < card_size_; ++card_index) {
00748 int min = 0;
00749 int max = 0;
00750 for (int var_index = 0; var_index < var_size_; ++var_index) {
00751 IntVar* const var = vars_[var_index];
00752 if (var->Bound() && var->Min() == card_index) {
00753 min++;
00754 max++;
00755 } else if (var->Contains(card_index)) {
00756 max++;
00757 undecided_.SetToOne(s, var_index, card_index);
00758 }
00759 }
00760 min_.SetValue(s, card_index, min);
00761 max_.SetValue(s, card_index, max);
00762 CountVar(card_index);
00763 }
00764 }
00765
00766 void FastDistribute::OneBound(int index) {
00767 IntVar* const var = vars_[index];
00768 for (int card_index = 0; card_index < card_size_; ++card_index) {
00769 if (undecided_.IsSet(index, card_index)) {
00770 if (var->Min() == card_index) {
00771 SetRevDoContribute(index, card_index);
00772 } else {
00773 SetRevCannotContribute(index, card_index);
00774 }
00775 }
00776 }
00777 }
00778
00779 void FastDistribute::OneDomain(int index) {
00780 IntVar* const var = vars_[index];
00781 const int64 oldmin = var->OldMin();
00782 const int64 oldmax = var->OldMax();
00783 const int64 vmin = var->Min();
00784 const int64 vmax = var->Max();
00785 for (int64 card_index = std::max(oldmin, 0LL);
00786 card_index < std::min(vmin, card_size_);
00787 ++card_index) {
00788 if (undecided_.IsSet(index, card_index)) {
00789 SetRevCannotContribute(index, card_index);
00790 }
00791 }
00792 IntVarIterator* const holes = holes_[index];
00793 for (holes->Init(); holes->Ok(); holes->Next()) {
00794 const int64 card_index = holes->Value();
00795 if (card_index >= 0 &&
00796 card_index < card_size_ &&
00797 undecided_.IsSet(index, card_index)) {
00798 SetRevCannotContribute(index, card_index);
00799 }
00800 }
00801 for (int64 card_index = std::max(vmax + 1, 0LL);
00802 card_index <= std::min(oldmax, card_size_ - 1);
00803 ++card_index) {
00804 if (undecided_.IsSet(index, card_index)) {
00805 SetRevCannotContribute(index, card_index);
00806 }
00807 }
00808 }
00809
00810 void FastDistribute::CountVar(int card_index) {
00811 const int64 stored_min = min_[card_index];
00812 const int64 stored_max = max_[card_index];
00813 cards_[card_index]->SetRange(min_[card_index], max_[card_index]);
00814 if (cards_[card_index]->Min() == stored_max) {
00815 CardMax(card_index);
00816 }
00817 if (cards_[card_index]->Max() == stored_min) {
00818 CardMin(card_index);
00819 }
00820 }
00821
00822 void FastDistribute::CardMin(int card_index) {
00823 for (int var_index = 0; var_index < var_size_; ++var_index) {
00824 if (undecided_.IsSet(var_index, card_index)) {
00825 vars_[var_index]->RemoveValue(card_index);
00826 }
00827 }
00828 }
00829
00830 void FastDistribute::CardMax(int card_index) {
00831 for (int var_index = 0; var_index < var_size_; ++var_index) {
00832 if (undecided_.IsSet(var_index, card_index)) {
00833 vars_[var_index]->SetValue(card_index);
00834 }
00835 }
00836 }
00837
00838
00839
00840 class BoundedDistribute : public Constraint {
00841 public:
00842 BoundedDistribute(Solver* const s,
00843 const IntVar* const * vars,
00844 int vsize,
00845 int64 card_min,
00846 int64 card_max,
00847 int64 csize);
00848 virtual ~BoundedDistribute() {}
00849
00850 virtual void Post();
00851 virtual void InitialPropagate();
00852 void OneBound(int vindex);
00853 void OneDomain(int vindex);
00854 void CountVar(int card_index);
00855 void CardMin(int card_index);
00856 void CardMax(int card_index);
00857 virtual string DebugString() const;
00858 void SetRevCannotContribute(int64 var_index, int64 card_index) {
00859 Solver* const s = solver();
00860 undecided_.SetToZero(s, var_index, card_index);
00861 max_.Decr(s, card_index);
00862 if (max_[card_index] < card_min_) {
00863 solver()->Fail();
00864 }
00865 if (max_[card_index] == card_min_) {
00866 CardMax(card_index);
00867 }
00868 }
00869 void SetRevDoContribute(int64 var_index, int64 card_index) {
00870 Solver* const s = solver();
00871 undecided_.SetToZero(s, var_index, card_index);
00872 min_.Incr(s, card_index);
00873 if (min_[card_index] > card_max_) {
00874 solver()->Fail();
00875 }
00876 if (min_[card_index] == card_max_) {
00877 CardMin(card_index);
00878 }
00879 }
00880
00881 virtual void Accept(ModelVisitor* const visitor) const {
00882 visitor->BeginVisitConstraint(ModelVisitor::kDistribute, this);
00883 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00884 vars_.get(),
00885 var_size_);
00886 visitor->VisitIntegerArgument(ModelVisitor::kMinArgument, card_min_);
00887 visitor->VisitIntegerArgument(ModelVisitor::kMaxArgument, card_max_);
00888 visitor->VisitIntegerArgument(ModelVisitor::kSizeArgument,
00889 card_size_);
00890 visitor->EndVisitConstraint(ModelVisitor::kDistribute, this);
00891 }
00892
00893 private:
00894 const scoped_array<IntVar*> vars_;
00895 const int var_size_;
00896 const int64 card_min_;
00897 const int64 card_max_;
00898 const int64 card_size_;
00899 RevBitMatrix undecided_;
00900 NumericalRevArray<int> min_;
00901 NumericalRevArray<int> max_;
00902 scoped_array<IntVarIterator*> holes_;
00903 };
00904
00905 BoundedDistribute::BoundedDistribute(Solver* const s,
00906 const IntVar* const * vars,
00907 int vsize,
00908 int64 card_min,
00909 int64 card_max,
00910 int64 csize)
00911 : Constraint(s),
00912 vars_(new IntVar*[vsize]),
00913 var_size_(vsize),
00914 card_min_(card_min),
00915 card_max_(card_max),
00916 card_size_(csize),
00917 undecided_(var_size_, card_size_),
00918 min_(card_size_, 0),
00919 max_(card_size_, 0),
00920 holes_(new IntVarIterator*[var_size_]) {
00921 memcpy(vars_.get(), vars, var_size_ * sizeof(*vars));
00922 for (int var_index = 0; var_index < var_size_; ++var_index) {
00923 holes_[var_index] = vars_[var_index]->MakeHoleIterator(true);
00924 }
00925 }
00926
00927
00928 string BoundedDistribute::DebugString() const {
00929 return StringPrintf("BoundedDistribute([%s], cards = %" GG_LL_FORMAT
00930 "d * [%" GG_LL_FORMAT "d -- %"
00931 GG_LL_FORMAT "d])",
00932 DebugStringArray(vars_.get(), var_size_, ", ").c_str(),
00933 card_size_,
00934 card_min_,
00935 card_max_);
00936 }
00937
00938 void BoundedDistribute::Post() {
00939 for (int var_index = 0; var_index < var_size_; ++var_index) {
00940 IntVar* const var = vars_[var_index];
00941 if (!var->Bound()) {
00942 Demon* d = MakeConstraintDemon1(solver(),
00943 this,
00944 &BoundedDistribute::OneBound,
00945 "OneBound",
00946 var_index);
00947 var->WhenBound(d);
00948 d = MakeConstraintDemon1(solver(),
00949 this,
00950 &BoundedDistribute::OneDomain,
00951 "OneDomain",
00952 var_index);
00953 var->WhenDomain(d);
00954 }
00955 }
00956 }
00957
00958 void BoundedDistribute::InitialPropagate() {
00959 Solver* const s = solver();
00960
00961
00962 if (card_max_ < card_min_ || card_min_ * card_size_ > var_size_) {
00963 solver()->Fail();
00964 }
00965 if (card_min_ * card_size_ == var_size_) {
00966 for (int i = 0; i < var_size_; ++i) {
00967 vars_[i]->SetRange(0, card_size_ - 1);
00968 }
00969 }
00970
00971 for (int card_index = 0; card_index < card_size_; ++card_index) {
00972 int min = 0;
00973 int max = 0;
00974 for (int i = 0; i < var_size_; ++i) {
00975 IntVar* const var = vars_[i];
00976 if (var->Bound()) {
00977 if (var->Min() == card_index) {
00978 min++;
00979 max++;
00980 }
00981 } else if (var->Contains(card_index)) {
00982 max++;
00983 undecided_.SetToOne(s, i, card_index);
00984 }
00985 }
00986 min_.SetValue(s, card_index, min);
00987 max_.SetValue(s, card_index, max);
00988 CountVar(card_index);
00989 }
00990 }
00991
00992 void BoundedDistribute::OneBound(int index) {
00993 IntVar* const var = vars_[index];
00994 const int64 var_min = var->Min();
00995 for (int card_index = 0; card_index < card_size_; ++card_index) {
00996 if (undecided_.IsSet(index, card_index)) {
00997 if (var_min == card_index) {
00998 SetRevDoContribute(index, card_index);
00999 } else {
01000 SetRevCannotContribute(index, card_index);
01001 }
01002 }
01003 }
01004 }
01005
01006 void BoundedDistribute::OneDomain(int index) {
01007 IntVar* const var = vars_[index];
01008 const int64 oldmin = var->OldMin();
01009 const int64 oldmax = var->OldMax();
01010 const int64 vmin = var->Min();
01011 const int64 vmax = var->Max();
01012 for (int64 card_index = std::max(oldmin, 0LL);
01013 card_index < std::min(vmin, card_size_);
01014 ++card_index) {
01015 if (undecided_.IsSet(index, card_index)) {
01016 SetRevCannotContribute(index, card_index);
01017 }
01018 }
01019 IntVarIterator* const holes = holes_[index];
01020 for (holes->Init(); holes->Ok(); holes->Next()) {
01021 const int64 card_index = holes->Value();
01022 if (card_index >= 0 &&
01023 card_index < card_size_ &&
01024 undecided_.IsSet(index, card_index)) {
01025 SetRevCannotContribute(index, card_index);
01026 }
01027 }
01028 for (int64 card_index = std::max(vmax + 1, 0LL);
01029 card_index <= std::min(oldmax, card_size_ - 1);
01030 ++card_index) {
01031 if (undecided_.IsSet(index, card_index)) {
01032 SetRevCannotContribute(index, card_index);
01033 }
01034 }
01035 }
01036
01037 void BoundedDistribute::CountVar(int card_index) {
01038 const int64 stored_min = min_[card_index];
01039 const int64 stored_max = max_[card_index];
01040 if (card_min_ > stored_max || card_max_ < stored_min) {
01041 solver()->Fail();
01042 }
01043 if (card_min_ == stored_max) {
01044 CardMax(card_index);
01045 }
01046 if (card_max_ == stored_min) {
01047 CardMin(card_index);
01048 }
01049 }
01050
01051 void BoundedDistribute::CardMin(int card_index) {
01052 for (int var_index = 0; var_index < var_size_; ++var_index) {
01053 if (undecided_.IsSet(var_index, card_index)) {
01054 vars_[var_index]->RemoveValue(card_index);
01055 }
01056 }
01057 }
01058
01059 void BoundedDistribute::CardMax(int card_index) {
01060 for (int var_index = 0; var_index < var_size_; ++var_index) {
01061 if (undecided_.IsSet(var_index, card_index)) {
01062 vars_[var_index]->SetValue(card_index);
01063 }
01064 }
01065 }
01066
01067
01068
01069 class SetAllToZero : public Constraint {
01070 public:
01071 SetAllToZero(Solver* const s, const IntVar* const * vars, int size)
01072 : Constraint(s), vars_(new IntVar*[size]), size_(size) {
01073 DCHECK_GE(size_, 0);
01074 memcpy(vars_.get(), vars, size * sizeof(*vars));
01075 }
01076 virtual ~SetAllToZero() {}
01077
01078 virtual void Post() {}
01079
01080 virtual void InitialPropagate() {
01081 for (int i = 0; i < size_; ++i) {
01082 vars_[i]->SetValue(0);
01083 }
01084 }
01085
01086 virtual string DebugString() const {
01087 return "SetAllToZero()";
01088 }
01089
01090 virtual void Accept(ModelVisitor* const visitor) const {
01091 visitor->BeginVisitConstraint(ModelVisitor::kDistribute, this);
01092 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kCardsArgument,
01093 vars_.get(),
01094 size_);
01095 visitor->EndVisitConstraint(ModelVisitor::kDistribute, this);
01096 }
01097
01098 private:
01099 scoped_array<IntVar*> vars_;
01100 const int size_;
01101 };
01102
01103 }
01104
01105
01106
01107 Constraint* Solver::MakeDistribute(const std::vector<IntVar*>& vars,
01108 const std::vector<int64>& values,
01109 const std::vector<IntVar*>& cards) {
01110 if (vars.size() == 0) {
01111 return RevAlloc(new SetAllToZero(this, cards.data(), cards.size()));
01112 }
01113 CHECK_EQ(values.size(), cards.size());
01114 for (ConstIter<std::vector<IntVar*> > it(vars); !it.at_end(); ++it) {
01115 CHECK_EQ(this, (*it)->solver());
01116 }
01117
01118
01119 bool fast = true;
01120 for (int i = 0; i < values.size(); ++i) {
01121 if (values[i] != i) {
01122 fast = false;
01123 break;
01124 }
01125 }
01126 for (ConstIter<std::vector<IntVar*> > it(cards); !it.at_end(); ++it) {
01127 CHECK_EQ(this, (*it)->solver());
01128 }
01129 if (fast) {
01130 return RevAlloc(new FastDistribute(this, vars.data(), vars.size(),
01131 cards.data(), cards.size()));
01132 } else {
01133 return RevAlloc(new Distribute(this, vars.data(), vars.size(),
01134 values.data(), cards.data(), cards.size()));
01135 }
01136 }
01137
01138 Constraint* Solver::MakeDistribute(const std::vector<IntVar*>& vars,
01139 const std::vector<int>& values,
01140 const std::vector<IntVar*>& cards) {
01141 if (vars.size() == 0) {
01142 return RevAlloc(new SetAllToZero(this, cards.data(), cards.size()));
01143 }
01144 CHECK_EQ(values.size(), cards.size());
01145 for (ConstIter<std::vector<IntVar*> > it(vars); !it.at_end(); ++it) {
01146 CHECK_EQ(this, (*it)->solver());
01147 }
01148
01149
01150 bool fast = true;
01151 for (int i = 0; i < values.size(); ++i) {
01152 if (values[i] != i) {
01153 fast = false;
01154 break;
01155 }
01156 }
01157 for (ConstIter<std::vector<IntVar*> > it(cards); !it.at_end(); ++it) {
01158 CHECK_EQ(this, (*it)->solver());
01159 }
01160 if (fast) {
01161 return RevAlloc(new FastDistribute(this, vars.data(), vars.size(),
01162 cards.data(), cards.size()));
01163 } else {
01164 return RevAlloc(new Distribute(this, vars.data(), vars.size(),
01165 values.data(), cards.data(), cards.size()));
01166 }
01167 }
01168
01169 Constraint* Solver::MakeDistribute(const std::vector<IntVar*>& vars,
01170 const std::vector<IntVar*>& cards) {
01171 if (vars.size() == 0) {
01172 return RevAlloc(new SetAllToZero(this, cards.data(), cards.size()));
01173 }
01174 for (ConstIter<std::vector<IntVar*> > it(vars); !it.at_end(); ++it) {
01175 CHECK_EQ(this, (*it)->solver());
01176 }
01177 for (ConstIter<std::vector<IntVar*> > it(cards); !it.at_end(); ++it) {
01178 CHECK_EQ(this, (*it)->solver());
01179 }
01180 return RevAlloc(new FastDistribute(this, vars.data(), vars.size(),
01181 cards.data(), cards.size()));
01182 }
01183
01184 Constraint* Solver::MakeDistribute(const std::vector<IntVar*>& vars,
01185 int64 card_min,
01186 int64 card_max,
01187 int64 card_size) {
01188 CHECK_NE(vars.size(), 0);
01189 for (ConstIter<std::vector<IntVar*> > it(vars); !it.at_end(); ++it) {
01190 CHECK_EQ(this, (*it)->solver());
01191 }
01192 return RevAlloc(new BoundedDistribute(this, vars.data(), vars.size(),
01193 card_min, card_max, card_size));
01194 }
01195
01196 }