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 "constraint_solver/constraint_solver.h"
00026 #include "constraint_solver/constraint_solveri.h"
00027 #include "util/string_array.h"
00028
00029 namespace operations_research {
00030 namespace {
00031
00032
00033
00034
00035 class ArrayConstraint : public CastConstraint {
00036 public:
00037 ArrayConstraint(Solver* const s,
00038 const IntVar* const * vars,
00039 int size,
00040 IntVar* const var)
00041 : CastConstraint(s, var), vars_(new IntVar*[size]), size_(size) {
00042 CHECK_GT(size, 0);
00043 CHECK_NOTNULL(vars);
00044 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
00045 }
00046 virtual ~ArrayConstraint() {}
00047
00048 protected:
00049 string DebugStringInternal(const string& name) const {
00050 return StringPrintf("%s(%s) == %s",
00051 name.c_str(),
00052 DebugStringArray(vars_.get(), size_, ", ").c_str(),
00053 target_var_->DebugString().c_str());
00054 }
00055
00056 void AcceptInternal(const string& name, ModelVisitor* const visitor) const {
00057 visitor->BeginVisitConstraint(name, this);
00058 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00059 vars_.get(),
00060 size_);
00061 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
00062 target_var_);
00063 visitor->EndVisitConstraint(name, this);
00064 }
00065
00066 scoped_array<IntVar*> vars_;
00067 const int size_;
00068 };
00069
00070
00071
00072 class ArrayExpr : public BaseIntExpr {
00073 public:
00074 ArrayExpr(Solver* const s, const IntVar* const* vars, int size)
00075 : BaseIntExpr(s), vars_(new IntVar*[size]), size_(size) {
00076 CHECK_GT(size, 0);
00077 CHECK_NOTNULL(vars);
00078 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
00079 }
00080
00081 virtual ~ArrayExpr() {}
00082
00083 protected:
00084 string DebugStringInternal(const string& name) const {
00085 return StringPrintf("%s(%s)",
00086 name.c_str(),
00087 DebugStringArray(vars_.get(), size_, ", ").c_str());
00088 }
00089
00090 void AcceptInternal(const string& name, ModelVisitor* const visitor) const {
00091 visitor->BeginVisitIntegerExpression(name, this);
00092 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00093 vars_.get(),
00094 size_);
00095 visitor->EndVisitIntegerExpression(name, this);
00096 }
00097
00098 scoped_array<IntVar*> vars_;
00099 const int size_;
00100 };
00101
00102
00103
00104
00105 class TreeArrayConstraint : public ArrayConstraint {
00106 public:
00107 TreeArrayConstraint(Solver* const solver,
00108 IntVar* const* vars,
00109 int size,
00110 IntVar* const sum_var)
00111 : ArrayConstraint(solver, vars, size, sum_var),
00112 block_size_(solver->parameters().array_split_size) {
00113 std::vector<int> lengths;
00114 lengths.push_back(size_);
00115 while (lengths.back() > 1) {
00116 const int current = lengths.back();
00117 lengths.push_back((current + block_size_ - 1) / block_size_);
00118 }
00119 tree_.resize(lengths.size());
00120 for (int i = 0; i < lengths.size(); ++i) {
00121 tree_[i].resize(lengths[lengths.size() - i - 1]);
00122 }
00123 DCHECK_GE(tree_.size(), 1);
00124 DCHECK_EQ(1, tree_[0].size());
00125 root_node_ = &tree_[0][0];
00126 }
00127
00128
00129 void ReduceRange(int depth, int position, int64 delta_min, int64 delta_max) {
00130 NodeInfo* const info = &tree_[depth][position];
00131 if (delta_min > 0) {
00132 info->node_min.SetValue(solver(), info->node_min.Value() + delta_min);
00133 }
00134 if (delta_max > 0) {
00135 info->node_max.SetValue(solver(), info->node_max.Value() - delta_max);
00136 }
00137 }
00138
00139 void InitLeaf(Solver* const solver,
00140 int position,
00141 int64 var_min,
00142 int64 var_max) {
00143 InitNode(solver, MaxDepth(), position, var_min, var_max);
00144 }
00145
00146 void InitNode(Solver* const solver,
00147 int depth,
00148 int position,
00149 int64 node_min,
00150 int64 node_max) {
00151 tree_[depth][position].node_min.SetValue(solver, node_min);
00152 tree_[depth][position].node_max.SetValue(solver, node_max);
00153 }
00154
00155 int64 Min(int depth, int position) const {
00156 return tree_[depth][position].node_min.Value();
00157 }
00158
00159 int64 Max(int depth, int position) const {
00160 return tree_[depth][position].node_max.Value();
00161 }
00162
00163 int64 RootMin() const {
00164 return root_node_->node_min.Value();
00165 }
00166
00167 int64 RootMax() const {
00168 return root_node_->node_max.Value();
00169 }
00170
00171 int Parent(int position) const {
00172 return position / block_size_;
00173 }
00174
00175 int ChildStart(int position) const {
00176 return position * block_size_;
00177 }
00178
00179 int ChildEnd(int depth, int position) const {
00180 DCHECK_LT(depth + 1, tree_.size());
00181 return std::min((position + 1) * block_size_ - 1, Width(depth + 1) - 1);
00182 }
00183
00184 bool IsLeaf(int depth) const {
00185 return depth == MaxDepth();
00186 }
00187
00188 int MaxDepth() const {
00189 return tree_.size() - 1;
00190 }
00191
00192 int Width(int depth) const {
00193 return tree_[depth].size();
00194 }
00195
00196 private:
00197 struct NodeInfo {
00198 NodeInfo() : node_min(0), node_max(0) {}
00199 Rev<int64> node_min;
00200 Rev<int64> node_max;
00201 };
00202
00203 std::vector<std::vector<NodeInfo> > tree_;
00204 const int block_size_;
00205 NodeInfo* root_node_;
00206 };
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 class SumConstraint : public TreeArrayConstraint {
00221 public:
00222 SumConstraint(Solver* const solver,
00223 IntVar* const * vars,
00224 int size,
00225 IntVar* const sum_var)
00226 : TreeArrayConstraint(solver, vars, size, sum_var), sum_demon_(NULL) {}
00227
00228 virtual ~SumConstraint() {}
00229
00230 virtual void Post() {
00231 for (int i = 0; i < size_; ++i) {
00232 Demon* const demon = MakeConstraintDemon1(solver(),
00233 this,
00234 &SumConstraint::LeafChanged,
00235 "LeafChanged",
00236 i);
00237 vars_[i]->WhenRange(demon);
00238 }
00239 sum_demon_ = solver()->RegisterDemon(
00240 MakeDelayedConstraintDemon0(solver(),
00241 this,
00242 &SumConstraint::SumChanged,
00243 "SumChanged"));
00244 target_var_->WhenRange(sum_demon_);
00245 }
00246
00247 virtual void InitialPropagate() {
00248
00249 for (int i = 0; i < size_; ++i) {
00250 InitLeaf(solver(), i, vars_[i]->Min(), vars_[i]->Max());
00251 }
00252
00253 for (int i = MaxDepth() - 1; i >= 0; --i) {
00254 for (int j = 0; j < Width(i); ++j) {
00255 int64 sum_min = 0;
00256 int64 sum_max = 0;
00257 const int block_start = ChildStart(j);
00258 const int block_end = ChildEnd(i, j);
00259 for (int k = block_start; k <= block_end; ++k) {
00260 sum_min += Min(i + 1, k);
00261 sum_max += Max(i + 1, k);
00262 }
00263 InitNode(solver(), i, j, sum_min, sum_max);
00264 }
00265 }
00266
00267 target_var_->SetRange(RootMin(), RootMax());
00268
00269
00270 SumChanged();
00271 }
00272
00273 void SumChanged() {
00274 if (target_var_->Max() == RootMin()) {
00275
00276 for (int i = 0; i < size_; ++i) {
00277 vars_[i]->SetValue(vars_[i]->Min());
00278 }
00279 } else if (target_var_->Min() == RootMax()) {
00280
00281 for (int i = 0; i < size_; ++i) {
00282 vars_[i]->SetValue(vars_[i]->Max());
00283 }
00284 } else {
00285 PushDown(0, 0, target_var_->Min(), target_var_->Max());
00286 }
00287 }
00288
00289 void PushDown(int depth, int position, int64 new_min, int64 new_max) {
00290
00291 if (new_min <= Min(depth, position) && new_max >= Max(depth, position)) {
00292 return;
00293 }
00294
00295
00296 if (IsLeaf(depth)) {
00297 vars_[position]->SetRange(new_min, new_max);
00298 return;
00299 }
00300
00301
00302
00303
00304
00305 const int64 sum_min = Min(depth, position);
00306 const int64 sum_max = Max(depth, position);
00307
00308
00309 new_max = std::min(sum_max, new_max);
00310 new_min = std::max(sum_min, new_min);
00311
00312
00313 if (new_max < sum_min || new_min > sum_max) {
00314 solver()->Fail();
00315 }
00316
00317
00318 const int block_start = ChildStart(position);
00319 const int block_end = ChildEnd(depth, position);
00320 for (int i = block_start; i <= block_end; ++i) {
00321 const int64 target_var_min = Min(depth + 1, i);
00322 const int64 target_var_max = Max(depth + 1, i);
00323 const int64 residual_min = sum_min - target_var_min;
00324 const int64 residual_max = sum_max - target_var_max;
00325 PushDown(depth + 1, i, new_min - residual_max, new_max - residual_min);
00326 }
00327
00328
00329 }
00330
00331 void LeafChanged(int term_index) {
00332 IntVar* const var = vars_[term_index];
00333 PushUp(term_index, var->Min() - var->OldMin(), var->OldMax() - var->Max());
00334 Enqueue(sum_demon_);
00335 }
00336
00337 void PushUp(int position, int64 delta_min, int64 delta_max) {
00338 DCHECK_GE(delta_max, 0);
00339 DCHECK_GE(delta_min, 0);
00340 DCHECK_GT(delta_min + delta_max, 0);
00341 for (int depth = MaxDepth(); depth >= 0; --depth) {
00342 ReduceRange(depth, position, delta_min, delta_max);
00343 position = Parent(position);
00344 }
00345 DCHECK_EQ(0, position);
00346 target_var_->SetRange(RootMin(), RootMax());
00347 }
00348
00349 string DebugString() const {
00350 return DebugStringInternal("Sum");
00351 }
00352
00353 virtual void Accept(ModelVisitor* const visitor) const {
00354 AcceptInternal(ModelVisitor::kSumEqual, visitor);
00355 }
00356
00357 private:
00358 Demon* sum_demon_;
00359 };
00360
00361
00362
00363
00364
00365
00366
00367 class MinBoolArrayCt : public ArrayConstraint {
00368 public:
00369 MinBoolArrayCt(Solver* const s, const IntVar* const * vars, int size,
00370 IntVar* var);
00371 virtual ~MinBoolArrayCt() {}
00372
00373 virtual void Post();
00374 virtual void InitialPropagate();
00375
00376 void Update(int index);
00377 void UpdateVar();
00378
00379 virtual string DebugString() const;
00380
00381 virtual void Accept(ModelVisitor* const visitor) const {
00382 AcceptInternal(ModelVisitor::kMinEqual, visitor);
00383 }
00384
00385 private:
00386 SmallRevBitSet bits_;
00387 RevSwitch inhibited_;
00388 };
00389
00390 MinBoolArrayCt::MinBoolArrayCt(Solver* const s,
00391 const IntVar* const * vars,
00392 int size,
00393 IntVar* var)
00394 : ArrayConstraint(s, vars, size, var), bits_(size) {}
00395
00396 void MinBoolArrayCt::Post() {
00397 for (int i = 0; i < size_; ++i) {
00398 Demon* d = MakeConstraintDemon1(solver(),
00399 this,
00400 &MinBoolArrayCt::Update,
00401 "Update",
00402 i);
00403 vars_[i]->WhenRange(d);
00404 }
00405
00406 Demon* uv = MakeConstraintDemon0(solver(),
00407 this,
00408 &MinBoolArrayCt::UpdateVar,
00409 "UpdateVar");
00410 target_var_->WhenRange(uv);
00411 }
00412
00413 void MinBoolArrayCt::InitialPropagate() {
00414 if (target_var_->Min() == 1LL) {
00415 for (int i = 0; i < size_; ++i) {
00416 vars_[i]->SetMin(1LL);
00417 }
00418 inhibited_.Switch(solver());
00419 } else {
00420 for (int i = 0; i < size_; ++i) {
00421 IntVar* const var = vars_[i];
00422 if (var->Max() == 0LL) {
00423 target_var_->SetMax(0LL);
00424 inhibited_.Switch(solver());
00425 return;
00426 }
00427 if (var->Min() == 0LL) {
00428 bits_.SetToOne(solver(), i);
00429 }
00430 }
00431 if (bits_.IsCardinalityZero()) {
00432 target_var_->SetValue(1LL);
00433 inhibited_.Switch(solver());
00434 } else if (target_var_->Max() == 0LL && bits_.IsCardinalityOne()) {
00435 vars_[bits_.GetFirstOne()]->SetValue(0LL);
00436 inhibited_.Switch(solver());
00437 }
00438 }
00439 }
00440
00441 void MinBoolArrayCt::Update(int index) {
00442 if (!inhibited_.Switched()) {
00443 if (vars_[index]->Max() == 0LL) {
00444 target_var_->SetValue(0LL);
00445 inhibited_.Switch(solver());
00446 } else {
00447 bits_.SetToZero(solver(), index);
00448 if (bits_.IsCardinalityZero()) {
00449 target_var_->SetValue(1LL);
00450 inhibited_.Switch(solver());
00451 } else if (target_var_->Max() == 0LL && bits_.IsCardinalityOne()) {
00452 vars_[bits_.GetFirstOne()]->SetValue(0LL);
00453 inhibited_.Switch(solver());
00454 }
00455 }
00456 }
00457 }
00458
00459 void MinBoolArrayCt::UpdateVar() {
00460 if (!inhibited_.Switched()) {
00461 if (target_var_->Min() == 1LL) {
00462 for (int i = 0; i < size_; ++i) {
00463 vars_[i]->SetMin(1LL);
00464 }
00465 inhibited_.Switch(solver());
00466 } else {
00467 if (bits_.IsCardinalityOne()) {
00468 vars_[bits_.GetFirstOne()]->SetValue(0LL);
00469 inhibited_.Switch(solver());
00470 }
00471 }
00472 }
00473 }
00474
00475 string MinBoolArrayCt::DebugString() const {
00476 return DebugStringInternal("MinBoolArrayCt");
00477 }
00478
00479
00480
00481 class MinBoolArray : public ArrayExpr {
00482 public:
00483
00484
00485 MinBoolArray(Solver* const s, const IntVar* const* exprs, int size);
00486 virtual ~MinBoolArray();
00487
00488 virtual int64 Min() const;
00489 virtual void SetMin(int64 m);
00490 virtual int64 Max() const;
00491 virtual void SetMax(int64 m);
00492 virtual string DebugString() const;
00493 virtual void WhenRange(Demon* d);
00494 virtual IntVar* CastToVar() {
00495 Solver* const s = solver();
00496 int64 vmin = 0LL;
00497 int64 vmax = 0LL;
00498 Range(&vmin, &vmax);
00499 IntVar* var = solver()->MakeIntVar(vmin, vmax);
00500 CastConstraint* const ct =
00501 s->RevAlloc(new MinBoolArrayCt(s, vars_.get(), size_, var));
00502 s->AddCastConstraint(ct, var, this);
00503 return var;
00504 }
00505
00506 virtual void Accept(ModelVisitor* const visitor) const {
00507 AcceptInternal(ModelVisitor::kMin, visitor);
00508 }
00509 };
00510
00511 MinBoolArray::~MinBoolArray() {}
00512
00513 MinBoolArray::MinBoolArray(Solver* const s, const IntVar* const* vars, int size)
00514 : ArrayExpr(s, vars, size) {}
00515
00516 int64 MinBoolArray::Min() const {
00517 for (int i = 0; i < size_; ++i) {
00518 const int64 vmin = vars_[i]->Min();
00519 if (vmin == 0LL) {
00520 return 0LL;
00521 }
00522 }
00523 return 1LL;
00524 }
00525
00526 void MinBoolArray::SetMin(int64 m) {
00527 if (m <= 0) {
00528 return;
00529 }
00530 if (m > 1) {
00531 solver()->Fail();
00532 }
00533 for (int i = 0; i < size_; ++i) {
00534 vars_[i]->SetMin(1LL);
00535 }
00536 }
00537
00538 int64 MinBoolArray::Max() const {
00539 for (int i = 0; i < size_; ++i) {
00540 const int64 vmax = vars_[i]->Max();
00541 if (vmax == 0LL) {
00542 return 0LL;
00543 }
00544 }
00545 return 1LL;
00546 }
00547
00548 void MinBoolArray::SetMax(int64 m) {
00549 if (m < 0) {
00550 solver()->Fail();
00551 } else if (m >= 1) {
00552 return;
00553 }
00554 DCHECK_EQ(m, 0LL);
00555 int active = 0;
00556 int curr = -1;
00557 for (int i = 0; i < size_; ++i) {
00558 if (vars_[i]->Min() == 0LL) {
00559 active++;
00560 curr = i;
00561 }
00562 }
00563 if (active == 0) {
00564 solver()->Fail();
00565 }
00566 if (active == 1) {
00567 vars_[curr]->SetMax(0LL);
00568 }
00569 }
00570
00571 string MinBoolArray::DebugString() const {
00572 return DebugStringInternal("MinBoolArray");
00573 }
00574
00575 void MinBoolArray::WhenRange(Demon* d) {
00576 for (int i = 0; i < size_; ++i) {
00577 vars_[i]->WhenRange(d);
00578 }
00579 }
00580
00581
00582
00583
00584
00585 class MinArrayCt : public ArrayConstraint {
00586 public:
00587 MinArrayCt(Solver* const s, const IntVar* const * vars, int size,
00588 IntVar* var);
00589 virtual ~MinArrayCt() {}
00590
00591 virtual void Post();
00592 virtual void InitialPropagate();
00593
00594 void Update(int index);
00595 void UpdateVar();
00596
00597 virtual string DebugString() const;
00598
00599 virtual void Accept(ModelVisitor* const visitor) const {
00600 AcceptInternal(ModelVisitor::kMinEqual, visitor);
00601 }
00602
00603 private:
00604 Rev<int> min_support_;
00605 };
00606
00607 MinArrayCt::MinArrayCt(Solver* const s,
00608 const IntVar* const * vars,
00609 int size,
00610 IntVar* var)
00611 : ArrayConstraint(s, vars, size, var), min_support_(0) {}
00612
00613 void MinArrayCt::Post() {
00614 for (int i = 0; i < size_; ++i) {
00615 Demon* d = MakeConstraintDemon1(solver(),
00616 this,
00617 &MinArrayCt::Update,
00618 "Update",
00619 i);
00620 vars_[i]->WhenRange(d);
00621 }
00622 Demon* uv = MakeConstraintDemon0(solver(),
00623 this,
00624 &MinArrayCt::UpdateVar,
00625 "UpdateVar");
00626 target_var_->WhenRange(uv);
00627 }
00628
00629 void MinArrayCt::InitialPropagate() {
00630 int64 vmin = target_var_->Min();
00631 int64 vmax = target_var_->Max();
00632 int64 cmin = kint64max;
00633 int64 cmax = kint64max;
00634 int min_support = -1;
00635 for (int i = 0; i < size_; ++i) {
00636 IntVar* const var = vars_[i];
00637 var->SetMin(vmin);
00638 const int64 tmin = var->Min();
00639 const int64 tmax = var->Max();
00640 if (tmin < cmin) {
00641 cmin = tmin;
00642 min_support = i;
00643 }
00644 if (tmax < cmax) {
00645 cmax = tmax;
00646 }
00647 }
00648 min_support_.SetValue(solver(), min_support);
00649 target_var_->SetRange(cmin, cmax);
00650 vmin = target_var_->Min();
00651 vmax = target_var_->Max();
00652 int active = 0;
00653 int curr = -1;
00654 for (int i = 0; i < size_; ++i) {
00655 if (vars_[i]->Min() <= vmax) {
00656 if (active++ >= 1) {
00657 return;
00658 }
00659 curr = i;
00660 }
00661 }
00662 if (active == 0) {
00663 solver()->Fail();
00664 }
00665 if (active == 1) {
00666 vars_[curr]->SetMax(vmax);
00667 }
00668 }
00669
00670 void MinArrayCt::Update(int index) {
00671 IntVar* const modified = vars_[index];
00672 if (modified->OldMax() != modified->Max()) {
00673 target_var_->SetMax(modified->Max());
00674 }
00675 if (index == min_support_.Value() && modified->OldMin() != modified->Min()) {
00676
00677
00678 int64 cmin = kint64max;
00679 int min_support = -1;
00680 for (int i = 0; i < size_; ++i) {
00681 const int64 tmin = vars_[i]->Min();
00682 if (tmin < cmin) {
00683 cmin = tmin;
00684 min_support = i;
00685 }
00686 }
00687 min_support_.SetValue(solver(), min_support);
00688 target_var_->SetMin(cmin);
00689 }
00690 }
00691
00692 void MinArrayCt::UpdateVar() {
00693 const int64 vmin = target_var_->Min();
00694 if (vmin != target_var_->OldMin()) {
00695 for (int i = 0; i < size_; ++i) {
00696 vars_[i]->SetMin(vmin);
00697 }
00698 }
00699 const int64 vmax = target_var_->Max();
00700 if (vmax != target_var_->OldMax()) {
00701 int active = 0;
00702 int curr = -1;
00703 for (int i = 0; i < size_; ++i) {
00704 if (vars_[i]->Min() <= vmax) {
00705 if (active++ >= 1) {
00706 return;
00707 }
00708 curr = i;
00709 }
00710 }
00711 if (active == 0) {
00712 solver()->Fail();
00713 }
00714 if (active == 1) {
00715 vars_[curr]->SetMax(vmax);
00716 }
00717 }
00718 }
00719
00720 string MinArrayCt::DebugString() const {
00721 return DebugStringInternal("MinArrayCt");
00722 }
00723
00724
00725
00726 class MinArray : public ArrayExpr {
00727 public:
00728
00729
00730 MinArray(Solver* const s, const IntVar* const* exprs, int size);
00731 virtual ~MinArray();
00732
00733 virtual int64 Min() const;
00734 virtual void SetMin(int64 m);
00735 virtual int64 Max() const;
00736 virtual void SetMax(int64 m);
00737 virtual string DebugString() const;
00738 virtual void WhenRange(Demon* d);
00739 virtual IntVar* CastToVar() {
00740 Solver* const s = solver();
00741 int64 vmin = 0LL;
00742 int64 vmax = 0LL;
00743 Range(&vmin, &vmax);
00744 IntVar* var = solver()->MakeIntVar(vmin, vmax);
00745 CastConstraint* const ct =
00746 s->RevAlloc(new MinArrayCt(s, vars_.get(), size_, var));
00747 s->AddCastConstraint(ct, var, this);
00748 return var;
00749 }
00750
00751 virtual void Accept(ModelVisitor* const visitor) const {
00752 AcceptInternal(ModelVisitor::kMin, visitor);
00753 }
00754 };
00755
00756 MinArray::~MinArray() {}
00757
00758 MinArray::MinArray(Solver* const s, const IntVar* const* vars, int size)
00759 : ArrayExpr(s, vars, size) {}
00760
00761 int64 MinArray::Min() const {
00762 int64 min = kint64max;
00763 for (int i = 0; i < size_; ++i) {
00764 const int64 vmin = vars_[i]->Min();
00765 if (min > vmin) {
00766 min = vmin;
00767 }
00768 }
00769 return min;
00770 }
00771
00772 void MinArray::SetMin(int64 m) {
00773 for (int i = 0; i < size_; ++i) {
00774 vars_[i]->SetMin(m);
00775 }
00776 }
00777
00778 int64 MinArray::Max() const {
00779 int64 max = kint64max;
00780 for (int i = 0; i < size_; ++i) {
00781 const int64 vmax = vars_[i]->Max();
00782 if (max > vmax) {
00783 max = vmax;
00784 }
00785 }
00786 return max;
00787 }
00788
00789 void MinArray::SetMax(int64 m) {
00790 int active = 0;
00791 int curr = -1;
00792 for (int i = 0; i < size_; ++i) {
00793 if (vars_[i]->Min() <= m) {
00794 if (active++ >= 1) {
00795 return;
00796 }
00797 curr = i;
00798 }
00799 }
00800 if (active == 0) {
00801 solver()->Fail();
00802 }
00803 if (active == 1) {
00804 vars_[curr]->SetMax(m);
00805 }
00806 }
00807
00808 string MinArray::DebugString() const {
00809 return DebugStringInternal("MinArray");
00810 }
00811
00812 void MinArray::WhenRange(Demon* d) {
00813 for (int i = 0; i < size_; ++i) {
00814 vars_[i]->WhenRange(d);
00815 }
00816 }
00817
00818
00819
00820
00821
00822
00823 class MaxArrayCt : public ArrayConstraint {
00824 public:
00825 MaxArrayCt(Solver* const s, const IntVar* const * vars, int size,
00826 IntVar* var);
00827 virtual ~MaxArrayCt() {}
00828
00829 virtual void Post();
00830 virtual void InitialPropagate();
00831
00832 void Update(int index);
00833 void UpdateVar();
00834
00835 virtual string DebugString() const;
00836
00837 virtual void Accept(ModelVisitor* const visitor) const {
00838 AcceptInternal(ModelVisitor::kMaxEqual, visitor);
00839 }
00840
00841 private:
00842 Rev<int> max_support_;
00843 };
00844
00845 MaxArrayCt::MaxArrayCt(Solver* const s,
00846 const IntVar* const * vars,
00847 int size,
00848 IntVar* var)
00849 : ArrayConstraint(s, vars, size, var), max_support_(0) {}
00850
00851 void MaxArrayCt::Post() {
00852 for (int i = 0; i < size_; ++i) {
00853 Demon* d = MakeConstraintDemon1(solver(),
00854 this,
00855 &MaxArrayCt::Update,
00856 "Update",
00857 i);
00858 vars_[i]->WhenRange(d);
00859 }
00860 Demon* uv = MakeConstraintDemon0(solver(),
00861 this,
00862 &MaxArrayCt::UpdateVar,
00863 "UpdateVar");
00864 target_var_->WhenRange(uv);
00865 }
00866
00867 void MaxArrayCt::InitialPropagate() {
00868 int64 vmin = target_var_->Min();
00869 int64 vmax = target_var_->Max();
00870 int64 cmin = kint64min;
00871 int64 cmax = kint64min;
00872 int max_support = -1;
00873 for (int i = 0; i < size_; ++i) {
00874 IntVar* const var = vars_[i];
00875 var->SetMax(vmax);
00876 const int64 tmin = var->Min();
00877 const int64 tmax = var->Max();
00878 if (tmin > cmin) {
00879 cmin = tmin;
00880 }
00881 if (tmax > cmax) {
00882 cmax = tmax;
00883 max_support = i;
00884 }
00885 }
00886 max_support_.SetValue(solver(), max_support);
00887 target_var_->SetRange(cmin, cmax);
00888 vmin = target_var_->Min();
00889 vmax = target_var_->Max();
00890 int active = 0;
00891 int curr = -1;
00892 for (int i = 0; i < size_; ++i) {
00893 if (vars_[i]->Max() >= vmin) {
00894 if (active++ >= 1) {
00895 return;
00896 }
00897 curr = i;
00898 }
00899 }
00900 if (active == 0) {
00901 solver()->Fail();
00902 }
00903 if (active == 1) {
00904 vars_[curr]->SetMin(vmin);
00905 }
00906 }
00907
00908 void MaxArrayCt::Update(int index) {
00909 IntVar* const modified = vars_[index];
00910 if (modified->OldMin() != modified->Min()) {
00911 target_var_->SetMin(modified->Min());
00912 }
00913 const int64 oldmax = modified->OldMax();
00914 if (index == max_support_.Value() && oldmax != modified->Max()) {
00915
00916
00917 int64 cmax = kint64min;
00918 int max_support = -1;
00919 for (int i = 0; i < size_; ++i) {
00920 const int64 tmax = vars_[i]->Max();
00921 if (tmax > cmax) {
00922 cmax = tmax;
00923 max_support = i;
00924 }
00925 }
00926 max_support_.SetValue(solver(), max_support);
00927 target_var_->SetMax(cmax);
00928 }
00929 }
00930
00931 void MaxArrayCt::UpdateVar() {
00932 const int64 vmax = target_var_->Max();
00933 if (vmax != target_var_->OldMax()) {
00934 for (int i = 0; i < size_; ++i) {
00935 vars_[i]->SetMax(vmax);
00936 }
00937 }
00938 const int64 vmin = target_var_->Min();
00939 if (vmin != target_var_->OldMin()) {
00940 int active = 0;
00941 int curr = -1;
00942 for (int i = 0; i < size_; ++i) {
00943 if (vars_[i]->Max() >= vmin) {
00944 if (active++ >= 1) {
00945 return;
00946 }
00947 curr = i;
00948 }
00949 }
00950 if (active == 0) {
00951 solver()->Fail();
00952 }
00953 if (active == 1) {
00954 vars_[curr]->SetMin(vmin);
00955 }
00956 }
00957 }
00958
00959 string MaxArrayCt::DebugString() const {
00960 return DebugStringInternal("MaxArrayCt");
00961 }
00962
00963
00964
00965 class MaxArray : public ArrayExpr {
00966 public:
00967
00968
00969 MaxArray(Solver* const s, const IntVar* const* exprs, int size);
00970 virtual ~MaxArray();
00971
00972 virtual int64 Min() const;
00973 virtual void SetMin(int64 m);
00974 virtual int64 Max() const;
00975 virtual void SetMax(int64 m);
00976 virtual string DebugString() const;
00977 virtual void WhenRange(Demon* d);
00978 virtual IntVar* CastToVar() {
00979 Solver* const s = solver();
00980 int64 vmin = Min();
00981 int64 vmax = Max();
00982 IntVar* var = solver()->MakeIntVar(vmin, vmax);
00983 CastConstraint* const ct =
00984 s->RevAlloc(new MaxArrayCt(s, vars_.get(), size_, var));
00985 s->AddCastConstraint(ct, var, this);
00986 return var;
00987 }
00988
00989 virtual void Accept(ModelVisitor* const visitor) const {
00990 AcceptInternal(ModelVisitor::kMax, visitor);
00991 }
00992 };
00993
00994 MaxArray::~MaxArray() {}
00995
00996 MaxArray::MaxArray(Solver* const s, const IntVar* const* vars, int size)
00997 : ArrayExpr(s, vars, size) {}
00998
00999 int64 MaxArray::Min() const {
01000 int64 min = kint64min;
01001 for (int i = 0; i < size_; ++i) {
01002 const int64 vmin = vars_[i]->Min();
01003 if (min < vmin) {
01004 min = vmin;
01005 }
01006 }
01007 return min;
01008 }
01009
01010 void MaxArray::SetMin(int64 m) {
01011 int active = 0;
01012 int curr = -1;
01013 for (int i = 0; i < size_; ++i) {
01014 if (vars_[i]->Max() >= m) {
01015 active++;
01016 curr = i;
01017 }
01018 }
01019 if (active == 0) {
01020 solver()->Fail();
01021 }
01022 if (active == 1) {
01023 vars_[curr]->SetMin(m);
01024 }
01025 }
01026
01027 int64 MaxArray::Max() const {
01028 int64 max = kint64min;
01029 for (int i = 0; i < size_; ++i) {
01030 const int64 vmax = vars_[i]->Max();
01031 if (max < vmax) {
01032 max = vmax;
01033 }
01034 }
01035 return max;
01036 }
01037
01038 void MaxArray::SetMax(int64 m) {
01039 for (int i = 0; i < size_; ++i) {
01040 vars_[i]->SetMax(m);
01041 }
01042 }
01043
01044 string MaxArray::DebugString() const {
01045 return DebugStringInternal("MaxArray");
01046 }
01047
01048 void MaxArray::WhenRange(Demon* d) {
01049 for (int i = 0; i < size_; ++i) {
01050 vars_[i]->WhenRange(d);
01051 }
01052 }
01053
01054
01055
01056
01057
01058 class MaxBoolArrayCt : public ArrayConstraint {
01059 public:
01060 MaxBoolArrayCt(Solver* const s, const IntVar* const * vars, int size,
01061 IntVar* var);
01062 virtual ~MaxBoolArrayCt() {}
01063
01064 virtual void Post();
01065 virtual void InitialPropagate();
01066
01067 void Update(int index);
01068 void UpdateVar();
01069
01070 virtual string DebugString() const;
01071
01072 virtual void Accept(ModelVisitor* const visitor) const {
01073 AcceptInternal(ModelVisitor::kMaxEqual, visitor);
01074 }
01075
01076 private:
01077 SmallRevBitSet bits_;
01078 RevSwitch inhibited_;
01079 };
01080
01081 MaxBoolArrayCt::MaxBoolArrayCt(Solver* const s,
01082 const IntVar* const * vars,
01083 int size,
01084 IntVar* var)
01085 : ArrayConstraint(s, vars, size, var), bits_(size) {}
01086
01087 void MaxBoolArrayCt::Post() {
01088 for (int i = 0; i < size_; ++i) {
01089 Demon* d = MakeConstraintDemon1(solver(),
01090 this,
01091 &MaxBoolArrayCt::Update,
01092 "Update",
01093 i);
01094 vars_[i]->WhenRange(d);
01095 }
01096
01097 Demon* uv = MakeConstraintDemon0(solver(),
01098 this,
01099 &MaxBoolArrayCt::UpdateVar,
01100 "UpdateVar");
01101 target_var_->WhenRange(uv);
01102 }
01103
01104 void MaxBoolArrayCt::InitialPropagate() {
01105 if (target_var_->Max() == 0) {
01106 for (int i = 0; i < size_; ++i) {
01107 vars_[i]->SetMax(0LL);
01108 }
01109 inhibited_.Switch(solver());
01110 } else {
01111 for (int i = 0; i < size_; ++i) {
01112 IntVar* const var = vars_[i];
01113 if (var->Min() == 1LL) {
01114 target_var_->SetMin(1LL);
01115 inhibited_.Switch(solver());
01116 return;
01117 }
01118 if (var->Max() == 1LL) {
01119 bits_.SetToOne(solver(), i);
01120 }
01121 }
01122 if (bits_.IsCardinalityZero()) {
01123 target_var_->SetValue(0LL);
01124 inhibited_.Switch(solver());
01125 } else if (target_var_->Min() == 1LL && bits_.IsCardinalityOne()) {
01126 vars_[bits_.GetFirstOne()]->SetValue(1LL);
01127 inhibited_.Switch(solver());
01128 }
01129 }
01130 }
01131
01132 void MaxBoolArrayCt::Update(int index) {
01133 if (!inhibited_.Switched()) {
01134 if (vars_[index]->Min() == 1LL) {
01135 target_var_->SetValue(1LL);
01136 inhibited_.Switch(solver());
01137 } else {
01138 bits_.SetToZero(solver(), index);
01139 if (bits_.IsCardinalityZero()) {
01140 target_var_->SetValue(0LL);
01141 inhibited_.Switch(solver());
01142 } else if (target_var_->Min() == 1LL && bits_.IsCardinalityOne()) {
01143 vars_[bits_.GetFirstOne()]->SetValue(1LL);
01144 inhibited_.Switch(solver());
01145 }
01146 }
01147 }
01148 }
01149
01150 void MaxBoolArrayCt::UpdateVar() {
01151 if (!inhibited_.Switched()) {
01152 if (target_var_->Max() == 0) {
01153 for (int i = 0; i < size_; ++i) {
01154 vars_[i]->SetMax(0LL);
01155 }
01156 inhibited_.Switch(solver());
01157 } else {
01158 if (bits_.IsCardinalityOne()) {
01159 vars_[bits_.GetFirstOne()]->SetValue(1LL);
01160 inhibited_.Switch(solver());
01161 }
01162 }
01163 }
01164 }
01165
01166 string MaxBoolArrayCt::DebugString() const {
01167 return DebugStringInternal("MaxBoolArrayCt");
01168 }
01169
01170
01171
01172 class MaxBoolArray : public ArrayExpr {
01173 public:
01174
01175
01176 MaxBoolArray(Solver* const s, const IntVar* const* exprs, int size);
01177 virtual ~MaxBoolArray();
01178
01179 virtual int64 Min() const;
01180 virtual void SetMin(int64 m);
01181 virtual int64 Max() const;
01182 virtual void SetMax(int64 m);
01183 virtual string DebugString() const;
01184 virtual void WhenRange(Demon* d);
01185 virtual IntVar* CastToVar() {
01186 Solver* const s = solver();
01187 int64 vmin = Min();
01188 int64 vmax = Max();
01189 IntVar* var = solver()->MakeIntVar(vmin, vmax);
01190 CastConstraint* const ct =
01191 s->RevAlloc(new MaxBoolArrayCt(s, vars_.get(), size_, var));
01192 s->AddCastConstraint(ct, var, this);
01193 return var;
01194 }
01195
01196 virtual void Accept(ModelVisitor* const visitor) const {
01197 AcceptInternal(ModelVisitor::kMax, visitor);
01198 }
01199 };
01200
01201 MaxBoolArray::~MaxBoolArray() {}
01202
01203 MaxBoolArray::MaxBoolArray(Solver* const s, const IntVar* const* vars, int size)
01204 : ArrayExpr(s, vars, size) {}
01205
01206 int64 MaxBoolArray::Min() const {
01207 for (int i = 0; i < size_; ++i) {
01208 const int64 vmin = vars_[i]->Min();
01209 if (vmin == 1LL) {
01210 return 1LL;
01211 }
01212 }
01213 return 0LL;
01214 }
01215
01216 void MaxBoolArray::SetMin(int64 m) {
01217 if (m > 1) {
01218 solver()->Fail();
01219 } else if (m <= 0) {
01220 return;
01221 }
01222 DCHECK_EQ(m, 1LL);
01223 int active = 0;
01224 int curr = -1;
01225 for (int i = 0; i < size_; ++i) {
01226 if (vars_[i]->Max() == 1LL) {
01227 active++;
01228 curr = i;
01229 }
01230 }
01231 if (active == 0) {
01232 solver()->Fail();
01233 }
01234 if (active == 1) {
01235 vars_[curr]->SetMin(1LL);
01236 }
01237 }
01238
01239 int64 MaxBoolArray::Max() const {
01240 for (int i = 0; i < size_; ++i) {
01241 const int64 vmax = vars_[i]->Max();
01242 if (vmax == 1LL) {
01243 return 1LL;
01244 }
01245 }
01246 return 0LL;
01247 }
01248
01249 void MaxBoolArray::SetMax(int64 m) {
01250 for (int i = 0; i < size_; ++i) {
01251 vars_[i]->SetMax(m);
01252 }
01253 }
01254
01255 string MaxBoolArray::DebugString() const {
01256 return DebugStringInternal("MaxBoolArray");
01257 }
01258
01259 void MaxBoolArray::WhenRange(Demon* d) {
01260 for (int i = 0; i < size_; ++i) {
01261 vars_[i]->WhenRange(d);
01262 }
01263 }
01264
01265
01266
01267 void ScanArray(IntVar* const* vars, int size, int* bound,
01268 int64* amin, int64* amax, int64* min_max, int64* max_min) {
01269 *amin = kint64max;
01270 *min_max = kint64max;
01271 *max_min = kint64min;
01272 *amax = kint64min;
01273 *bound = 0;
01274 for (int i = 0; i < size; ++i) {
01275 const int64 vmin = vars[i]->Min();
01276 const int64 vmax = vars[i]->Max();
01277 if (vmin < *amin) {
01278 *amin = vmin;
01279 }
01280 if (vmax > *amax) {
01281 *amax = vmax;
01282 }
01283 if (vmax < *min_max) {
01284 *min_max = vmax;
01285 }
01286 if (vmin > *max_min) {
01287 *max_min = vmin;
01288 }
01289 if (vmin == vmax) {
01290 (*bound)++;
01291 }
01292 }
01293 }
01294
01295 IntExpr* BuildMinArray(Solver* const s, IntVar* const* vars, int size) {
01296 int64 amin = 0, amax = 0, min_max = 0, max_min = 0;
01297 int bound = 0;
01298 ScanArray(vars, size, &bound, &amin, &amax, &min_max, &max_min);
01299 if (bound == size || amin == min_max) {
01300 return s->MakeIntConst(amin);
01301 }
01302 if (amin == 0 && amax == 1) {
01303 return s->RegisterIntExpr(s->RevAlloc(new MinBoolArray(s, vars, size)));
01304 }
01305 return s->RegisterIntExpr(s->RevAlloc(new MinArray(s, vars, size)));
01306 }
01307
01308 IntExpr* BuildMaxArray(Solver* const s, IntVar* const* vars, int size) {
01309 int64 amin = 0, amax = 0, min_max = 0, max_min = 0;
01310 int bound = 0;
01311 ScanArray(vars, size, &bound, &amin, &amax, &min_max, &max_min);
01312 if (bound == size || amax == max_min) {
01313 return s->MakeIntConst(amax);
01314 }
01315 if (amin == 0 && amax == 1) {
01316 return s->RegisterIntExpr(s->RevAlloc(new MaxBoolArray(s, vars, size)));
01317 }
01318 return s->RegisterIntExpr(s->RevAlloc(new MaxArray(s, vars, size)));
01319 }
01320
01321 enum BuildOp { MIN_OP, MAX_OP };
01322
01323 IntExpr* BuildLogSplitArray(Solver* const s,
01324 IntVar* const* vars,
01325 int size,
01326 BuildOp op) {
01327 const int split_size = s->parameters().array_split_size;
01328 if (size == 0) {
01329 return s->MakeIntConst(0LL);
01330 } else if (size == 1) {
01331 return vars[0];
01332 } else if (size == 2) {
01333 switch (op) {
01334 case MIN_OP:
01335 return s->MakeMin(vars[0], vars[1]);
01336 case MAX_OP:
01337 return s->MakeMax(vars[0], vars[1]);
01338 };
01339 } else if (size > split_size) {
01340 const int nb_blocks = (size - 1) / split_size + 1;
01341 const int block_size = (size + nb_blocks - 1) / nb_blocks;
01342 std::vector<IntVar*> top_vector;
01343 int start = 0;
01344 while (start < size) {
01345 int real_size = (start + block_size > size ? size - start : block_size);
01346 IntVar* intermediate = NULL;
01347 switch (op) {
01348 case MIN_OP:
01349 intermediate = s->MakeMin(vars + start, real_size)->Var();
01350 break;
01351 case MAX_OP:
01352 intermediate = s->MakeMax(vars + start, real_size)->Var();
01353 break;
01354 }
01355 top_vector.push_back(intermediate);
01356 start += real_size;
01357 }
01358 switch (op) {
01359 case MIN_OP:
01360 return s->MakeMin(top_vector);
01361 case MAX_OP:
01362 return s->MakeMax(top_vector);
01363 };
01364 } else {
01365 for (int i = 0; i < size; ++i) {
01366 CHECK_EQ(s, vars[i]->solver());
01367 }
01368 switch (op) {
01369 case MIN_OP:
01370 return BuildMinArray(s, vars, size);
01371 case MAX_OP:
01372 return BuildMaxArray(s, vars, size);
01373 };
01374 }
01375 LOG(FATAL) << "Unknown operator";
01376 return NULL;
01377 }
01378
01379 IntExpr* BuildLogSplitArray(Solver* const s,
01380 const std::vector<IntVar*>& vars,
01381 BuildOp op) {
01382 return BuildLogSplitArray(s, vars.data(), vars.size(), op);
01383 }
01384 }
01385
01386 IntExpr* Solver::MakeSum(const std::vector<IntVar*>& vars) {
01387 return MakeSum(vars.data(), vars.size());
01388 }
01389
01390 IntExpr* Solver::MakeSum(IntVar* const* vars, int size) {
01391 if (size == 0) {
01392 return MakeIntConst(0LL);
01393 } else if (size == 1) {
01394 return vars[0];
01395 } else if (size == 2) {
01396 return MakeSum(vars[0], vars[1]);
01397 } else {
01398 int64 sum_min = 0;
01399 int64 sum_max = 0;
01400 for (int i = 0; i < size; ++i) {
01401 sum_min += vars[i]->Min();
01402 sum_max += vars[i]->Max();
01403 }
01404 IntVar* const sum_var = MakeIntVar(sum_min, sum_max);
01405 AddConstraint(RevAlloc(new SumConstraint(this, vars, size, sum_var)));
01406 return sum_var;
01407 }
01408 }
01409
01410 IntExpr* Solver::MakeMin(const std::vector<IntVar*>& vars) {
01411 return BuildLogSplitArray(this, vars, MIN_OP);
01412 }
01413
01414 IntExpr* Solver::MakeMin(IntVar* const* vars, int size) {
01415 return BuildLogSplitArray(this, vars, size, MIN_OP);
01416 }
01417
01418 IntExpr* Solver::MakeMax(const std::vector<IntVar*>& vars) {
01419 return BuildLogSplitArray(this, vars, MAX_OP);
01420 }
01421
01422 IntExpr* Solver::MakeMax(IntVar* const* vars, int size) {
01423 return BuildLogSplitArray(this, vars, size, MAX_OP);
01424 }
01425
01426
01427
01428 namespace {
01429 bool AreAllBooleans(const IntVar* const* vars, int size) {
01430 for (int i = 0; i < size; ++i) {
01431 const IntVar* var = vars[i];
01432 if (var->Min() < 0 || var->Max() > 1) {
01433 return false;
01434 }
01435 }
01436 return true;
01437 }
01438
01439 template<class T> bool AreAllPositive(const T* const values, int size) {
01440 for (int i = 0; i < size; ++i) {
01441 if (values[i] < 0) {
01442 return false;
01443 }
01444 }
01445 return true;
01446 }
01447
01448 template<class T> bool AreAllNull(const T* const values, int size) {
01449 for (int i = 0; i < size; ++i) {
01450 if (values[i] != 0) {
01451 return false;
01452 }
01453 }
01454 return true;
01455 }
01456
01457 template <class T> bool AreAllBoundOrNull(const IntVar* const * vars,
01458 const T* const values,
01459 int size) {
01460 for (int i = 0; i < size; ++i) {
01461 if (values[i] != 0 && !vars[i]->Bound()) {
01462 return false;
01463 }
01464 }
01465 return true;
01466 }
01467
01468 class BaseSumBooleanConstraint : public Constraint {
01469 public:
01470 BaseSumBooleanConstraint(Solver* const s,
01471 const IntVar* const* vars,
01472 int size)
01473 : Constraint(s), vars_(new IntVar*[size]), size_(size) {
01474 CHECK_GT(size_, 0);
01475 CHECK(vars != NULL);
01476 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
01477 }
01478 virtual ~BaseSumBooleanConstraint() {}
01479
01480 protected:
01481 string DebugStringInternal(const string& name) const;
01482
01483 const scoped_array<IntVar*> vars_;
01484 const int size_;
01485 RevSwitch inactive_;
01486 };
01487
01488 string BaseSumBooleanConstraint::DebugStringInternal(const string& name) const {
01489 string out = name + "(";
01490 for (int i = 0; i < size_; ++i) {
01491 if (i > 0) {
01492 out += ", ";
01493 }
01494 out += vars_[i]->DebugString();
01495 }
01496 out += ")";
01497 return out;
01498 }
01499
01500
01501
01502 class SumBooleanLessOrEqualToOne : public BaseSumBooleanConstraint {
01503 public:
01504 SumBooleanLessOrEqualToOne(Solver* const s,
01505 const IntVar* const* vars,
01506 int size)
01507 : BaseSumBooleanConstraint(s, vars, size) {}
01508
01509 virtual ~SumBooleanLessOrEqualToOne() {}
01510
01511 virtual void Post() {
01512 for (int i = 0; i < size_; ++i) {
01513 if (!vars_[i]->Bound()) {
01514 Demon* u = MakeConstraintDemon1(solver(),
01515 this,
01516 &SumBooleanLessOrEqualToOne::Update,
01517 "Update",
01518 i);
01519 vars_[i]->WhenBound(u);
01520 }
01521 }
01522 }
01523
01524 virtual void InitialPropagate() {
01525 for (int i = 0; i < size_; ++i) {
01526 if (vars_[i]->Min() == 1) {
01527 PushAllToZeroExcept(i);
01528 return;
01529 }
01530 }
01531 }
01532
01533 void Update(int index) {
01534 if (!inactive_.Switched()) {
01535 DCHECK(vars_[index]->Bound());
01536 if (vars_[index]->Min() == 1) {
01537 PushAllToZeroExcept(index);
01538 }
01539 }
01540 }
01541
01542 void PushAllToZeroExcept(int index) {
01543 inactive_.Switch(solver());
01544 for (int i = 0; i < size_; ++i) {
01545 if (i != index && vars_[i]->Max() != 0) {
01546 vars_[i]->SetMax(0);
01547 }
01548 }
01549 }
01550
01551 virtual string DebugString() const {
01552 return DebugStringInternal("SumBooleanLessOrEqualToOne");
01553 }
01554
01555 virtual void Accept(ModelVisitor* const visitor) const {
01556 visitor->BeginVisitConstraint(ModelVisitor::kSumLessOrEqual, this);
01557 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
01558 vars_.get(),
01559 size_);
01560 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, 1);
01561 visitor->EndVisitConstraint(ModelVisitor::kSumLessOrEqual, this);
01562 }
01563 };
01564
01565
01566
01567
01568
01569 class SumBooleanGreaterOrEqualToOne : public BaseSumBooleanConstraint {
01570 public:
01571 SumBooleanGreaterOrEqualToOne(Solver* const s, const IntVar* const * vars,
01572 int size);
01573 virtual ~SumBooleanGreaterOrEqualToOne() {}
01574
01575 virtual void Post();
01576 virtual void InitialPropagate();
01577
01578 void Update(int index);
01579 void UpdateVar();
01580
01581 virtual string DebugString() const;
01582
01583 virtual void Accept(ModelVisitor* const visitor) const {
01584 visitor->BeginVisitConstraint(ModelVisitor::kSumGreaterOrEqual, this);
01585 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
01586 vars_.get(),
01587 size_);
01588 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, 1);
01589 visitor->EndVisitConstraint(ModelVisitor::kSumGreaterOrEqual, this);
01590 }
01591
01592 private:
01593 RevBitSet bits_;
01594 };
01595
01596 SumBooleanGreaterOrEqualToOne::SumBooleanGreaterOrEqualToOne(
01597 Solver* const s,
01598 const IntVar* const * vars,
01599 int size)
01600 : BaseSumBooleanConstraint(s, vars, size), bits_(size) {}
01601
01602 void SumBooleanGreaterOrEqualToOne::Post() {
01603 for (int i = 0; i < size_; ++i) {
01604 Demon* d = MakeConstraintDemon1(solver(),
01605 this,
01606 &SumBooleanGreaterOrEqualToOne::Update,
01607 "Update",
01608 i);
01609 vars_[i]->WhenRange(d);
01610 }
01611 }
01612
01613 void SumBooleanGreaterOrEqualToOne::InitialPropagate() {
01614 for (int i = 0; i < size_; ++i) {
01615 IntVar* const var = vars_[i];
01616 if (var->Min() == 1LL) {
01617 inactive_.Switch(solver());
01618 return;
01619 }
01620 if (var->Max() == 1LL) {
01621 bits_.SetToOne(solver(), i);
01622 }
01623 }
01624 if (bits_.IsCardinalityZero()) {
01625 solver()->Fail();
01626 } else if (bits_.IsCardinalityOne()) {
01627 vars_[bits_.GetFirstBit(0)]->SetValue(1LL);
01628 inactive_.Switch(solver());
01629 }
01630 }
01631
01632 void SumBooleanGreaterOrEqualToOne::Update(int index) {
01633 if (!inactive_.Switched()) {
01634 if (vars_[index]->Min() == 1LL) {
01635 inactive_.Switch(solver());
01636 } else {
01637 bits_.SetToZero(solver(), index);
01638 if (bits_.IsCardinalityZero()) {
01639 solver()->Fail();
01640 } else if (bits_.IsCardinalityOne()) {
01641 vars_[bits_.GetFirstBit(0)]->SetValue(1LL);
01642 inactive_.Switch(solver());
01643 }
01644 }
01645 }
01646 }
01647
01648 string SumBooleanGreaterOrEqualToOne::DebugString() const {
01649 return DebugStringInternal("SumBooleanGreaterOrEqualToOne");
01650 }
01651
01652
01653
01654 class SumBooleanEqualToOne : public BaseSumBooleanConstraint {
01655 public:
01656 SumBooleanEqualToOne(Solver* const s,
01657 IntVar* const* vars,
01658 int size)
01659 : BaseSumBooleanConstraint(s, vars, size), active_vars_(0) {}
01660
01661 virtual ~SumBooleanEqualToOne() {}
01662
01663 virtual void Post() {
01664 for (int i = 0; i < size_; ++i) {
01665 Demon* u = MakeConstraintDemon1(solver(),
01666 this,
01667 &SumBooleanEqualToOne::Update,
01668 "Update",
01669 i);
01670 vars_[i]->WhenBound(u);
01671 }
01672 }
01673
01674 virtual void InitialPropagate() {
01675 int min1 = 0;
01676 int max1 = 0;
01677 int index_min = -1;
01678 int index_max = -1;
01679 for (int i = 0; i < size_; ++i) {
01680 const IntVar* const var = vars_[i];
01681 if (var->Min() == 1) {
01682 min1++;
01683 index_min = i;
01684 }
01685 if (var->Max() == 1) {
01686 max1++;
01687 index_max = i;
01688 }
01689 }
01690 if (min1 > 1 || max1 == 0) {
01691 solver()->Fail();
01692 } else if (min1 == 1) {
01693 DCHECK_NE(-1, index_min);
01694 PushAllToZeroExcept(index_min);
01695 } else if (max1 == 1) {
01696 DCHECK_NE(-1, index_max);
01697 vars_[index_max]->SetValue(1);
01698 inactive_.Switch(solver());
01699 } else {
01700 active_vars_.SetValue(solver(), max1);
01701 }
01702 }
01703
01704 void Update(int index) {
01705 if (!inactive_.Switched()) {
01706 DCHECK(vars_[index]->Bound());
01707 const int64 value = vars_[index]->Min();
01708 if (value == 0) {
01709 active_vars_.Decr(solver());
01710 DCHECK_GE(active_vars_.Value(), 0);
01711 if (active_vars_.Value() == 0) {
01712 solver()->Fail();
01713 } else if (active_vars_.Value() == 1) {
01714 bool found = false;
01715 for (int i = 0; i < size_; ++i) {
01716 IntVar* const var = vars_[i];
01717 if (var->Max() == 1) {
01718 var->SetValue(1);
01719 PushAllToZeroExcept(i);
01720 found = true;
01721 break;
01722 }
01723 }
01724 if (!found) {
01725 solver()->Fail();
01726 }
01727 }
01728 } else {
01729 PushAllToZeroExcept(index);
01730 }
01731 }
01732 }
01733
01734 void PushAllToZeroExcept(int index) {
01735 inactive_.Switch(solver());
01736 for (int i = 0; i < size_; ++i) {
01737 if (i != index && vars_[i]->Max() != 0) {
01738 vars_[i]->SetMax(0);
01739 }
01740 }
01741 }
01742
01743 virtual string DebugString() const {
01744 return DebugStringInternal("SumBooleanEqualToOne");
01745 }
01746
01747 virtual void Accept(ModelVisitor* const visitor) const {
01748 visitor->BeginVisitConstraint(ModelVisitor::kSumEqual, this);
01749 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
01750 vars_.get(),
01751 size_);
01752 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, 1);
01753 visitor->EndVisitConstraint(ModelVisitor::kSumEqual, this);
01754 }
01755
01756 private:
01757 NumericalRev<int> active_vars_;
01758 };
01759
01760
01761
01762 class SumBooleanEqualToVar : public BaseSumBooleanConstraint {
01763 public:
01764 SumBooleanEqualToVar(Solver* const s,
01765 IntVar* const* bool_vars,
01766 int size,
01767 IntVar* const sum_var)
01768 : BaseSumBooleanConstraint(s, bool_vars, size),
01769 num_possible_true_vars_(0),
01770 num_always_true_vars_(0),
01771 sum_var_(sum_var) {}
01772
01773 virtual ~SumBooleanEqualToVar() {}
01774
01775 virtual void Post() {
01776 for (int i = 0; i < size_; ++i) {
01777 Demon* const u = MakeConstraintDemon1(solver(),
01778 this,
01779 &SumBooleanEqualToVar::Update,
01780 "Update",
01781 i);
01782 vars_[i]->WhenBound(u);
01783 }
01784 if (!sum_var_->Bound()) {
01785 Demon* const u = MakeConstraintDemon0(solver(),
01786 this,
01787 &SumBooleanEqualToVar::UpdateVar,
01788 "UpdateVar");
01789 sum_var_->WhenRange(u);
01790 }
01791 }
01792
01793 virtual void InitialPropagate() {
01794 int num_always_true_vars = 0;
01795 int possible_true = 0;
01796 for (int i = 0; i < size_; ++i) {
01797 const IntVar* const var = vars_[i];
01798 if (var->Min() == 1) {
01799 num_always_true_vars++;
01800 }
01801 if (var->Max() == 1) {
01802 possible_true++;
01803 }
01804 }
01805 sum_var_->SetRange(num_always_true_vars, possible_true);
01806 const int64 var_min = sum_var_->Min();
01807 const int64 var_max = sum_var_->Max();
01808 if (num_always_true_vars == var_max && possible_true > var_max) {
01809 PushAllUnboundToZero();
01810 } else if (possible_true == var_min && num_always_true_vars < var_min) {
01811 PushAllUnboundToOne();
01812 } else {
01813 num_possible_true_vars_.SetValue(solver(), possible_true);
01814 num_always_true_vars_.SetValue(solver(), num_always_true_vars);
01815 }
01816 }
01817
01818 void UpdateVar() {
01819 if (num_possible_true_vars_.Value() == sum_var_->Min()) {
01820 PushAllUnboundToOne();
01821 } else if (num_always_true_vars_.Value() == sum_var_->Max()) {
01822 PushAllUnboundToZero();
01823 }
01824 }
01825
01826 void Update(int index) {
01827 if (!inactive_.Switched()) {
01828 DCHECK(vars_[index]->Bound());
01829 const int64 value = vars_[index]->Min();
01830 if (value == 0) {
01831 num_possible_true_vars_.Decr(solver());
01832 if (num_possible_true_vars_.Value() == sum_var_->Min()) {
01833 PushAllUnboundToOne();
01834 }
01835 } else {
01836 DCHECK_EQ(1, value);
01837 num_always_true_vars_.Incr(solver());
01838 if (num_always_true_vars_.Value() == sum_var_->Max()) {
01839 PushAllUnboundToZero();
01840 }
01841 }
01842 }
01843 }
01844
01845 void PushAllUnboundToZero() {
01846 int64 counter = 0;
01847 inactive_.Switch(solver());
01848 for (int i = 0; i < size_; ++i) {
01849 if (vars_[i]->Min() == 0) {
01850 vars_[i]->SetValue(0);
01851 } else {
01852 counter++;
01853 }
01854 }
01855 if (counter < sum_var_->Min() || counter > sum_var_->Max()) {
01856 solver()->Fail();
01857 }
01858 }
01859
01860 void PushAllUnboundToOne() {
01861 int64 counter = 0;
01862 inactive_.Switch(solver());
01863 for (int i = 0; i < size_; ++i) {
01864 if (vars_[i]->Max() == 1) {
01865 vars_[i]->SetValue(1);
01866 counter++;
01867 }
01868 }
01869 if (counter < sum_var_->Min() || counter > sum_var_->Max()) {
01870 solver()->Fail();
01871 }
01872 }
01873
01874 virtual string DebugString() const {
01875 return DebugStringInternal("SumBooleanEqualToVar");
01876 }
01877
01878 virtual void Accept(ModelVisitor* const visitor) const {
01879 visitor->BeginVisitConstraint(ModelVisitor::kSumEqual, this);
01880 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
01881 vars_.get(),
01882 size_);
01883 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
01884 sum_var_);
01885 visitor->EndVisitConstraint(ModelVisitor::kSumEqual, this);
01886 }
01887
01888 private:
01889 NumericalRev<int> num_possible_true_vars_;
01890 NumericalRev<int> num_always_true_vars_;
01891 IntVar* const sum_var_;
01892 };
01893
01894
01895
01896
01897
01898 struct Container {
01899 IntVar* var;
01900 int64 coef;
01901 Container(IntVar* v, int64 c) : var(v), coef(c) {}
01902 bool operator<(const Container& c) const { return (coef < c.coef); }
01903 };
01904
01905
01906
01907
01908
01909
01910
01911
01912 int64 SortBothChangeConstant(IntVar** const vars,
01913 int64* const coefs,
01914 int* const size,
01915 bool keep_inside) {
01916 CHECK_NOTNULL(vars);
01917 CHECK_NOTNULL(coefs);
01918 CHECK_NOTNULL(size);
01919 if (*size == 0) {
01920 return 0;
01921 }
01922 int64 cst = 0;
01923 std::vector<Container> to_sort;
01924 for (int index = 0; index < *size; ++index) {
01925 if (vars[index]->Bound()) {
01926 cst += coefs[index] * vars[index]->Min();
01927 } else if (coefs[index] != 0) {
01928 to_sort.push_back(Container(vars[index], coefs[index]));
01929 }
01930 }
01931 if (keep_inside && cst != 0) {
01932 CHECK_LT(to_sort.size(), *size);
01933 Solver* const solver = vars[0]->solver();
01934 to_sort.push_back(Container(solver->MakeIntConst(1), cst));
01935 cst = 0;
01936 }
01937 std::sort(to_sort.begin(), to_sort.end());
01938 *size = to_sort.size();
01939 for (int index = 0; index < *size; ++index) {
01940 vars[index] = to_sort[index].var;
01941 coefs[index] = to_sort[index].coef;
01942 }
01943 return cst;
01944 }
01945
01946
01947
01948 class BooleanScalProdLessConstant : public Constraint {
01949 public:
01950 BooleanScalProdLessConstant(Solver* const s,
01951 const IntVar* const * vars,
01952 int size,
01953 const int64* const coefs,
01954 int64 upper_bound)
01955 : Constraint(s),
01956 vars_(new IntVar*[size]),
01957 size_(size),
01958 coefs_(new int64[size]),
01959 upper_bound_(upper_bound),
01960 first_unbound_backward_(size_ - 1),
01961 sum_of_bound_variables_(0LL),
01962 max_coefficient_(0) {
01963 CHECK_GT(size, 0);
01964 CHECK(vars != NULL);
01965 CHECK(coefs != NULL);
01966 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
01967 memcpy(coefs_.get(), coefs, size_ * sizeof(*coefs));
01968 for (int i = 0; i < size_; ++i) {
01969 DCHECK_GE(coefs_[i], 0);
01970 }
01971 upper_bound_ -= SortBothChangeConstant(vars_.get(),
01972 coefs_.get(),
01973 &size_,
01974 false);
01975 max_coefficient_.SetValue(s, coefs_[size_ - 1]);
01976 }
01977
01978 BooleanScalProdLessConstant(Solver* const s,
01979 const IntVar* const * vars,
01980 int size,
01981 const int* const coefs,
01982 int64 upper_bound)
01983 : Constraint(s),
01984 vars_(new IntVar*[size]),
01985 size_(size),
01986 coefs_(new int64[size]),
01987 upper_bound_(upper_bound),
01988 first_unbound_backward_(size_ - 1),
01989 sum_of_bound_variables_(0LL),
01990 max_coefficient_(0) {
01991 CHECK_GT(size, 0);
01992 CHECK(vars != NULL);
01993 CHECK(coefs != NULL);
01994 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
01995 for (int i = 0; i < size_; ++i) {
01996 DCHECK_GE(coefs[i], 0);
01997 coefs_[i] = coefs[i];
01998 }
01999 upper_bound_ -= SortBothChangeConstant(vars_.get(),
02000 coefs_.get(),
02001 &size_,
02002 false);
02003 max_coefficient_.SetValue(s, coefs_[size_ - 1]);
02004 }
02005
02006 virtual ~BooleanScalProdLessConstant() {}
02007
02008 virtual void Post() {
02009 for (int var_index = 0; var_index < size_; ++var_index) {
02010 if (vars_[var_index]->Bound()) {
02011 continue;
02012 }
02013 Demon* d = MakeConstraintDemon1(
02014 solver(),
02015 this,
02016 &BooleanScalProdLessConstant::Update,
02017 "InitialPropagate",
02018 var_index);
02019 vars_[var_index]->WhenRange(d);
02020 }
02021 }
02022
02023 void PushFromTop() {
02024 const int64 slack = upper_bound_ - sum_of_bound_variables_.Value();
02025 if (slack < 0) {
02026 solver()->Fail();
02027 }
02028 if (slack < max_coefficient_.Value()) {
02029 int64 last_unbound = first_unbound_backward_.Value();
02030 for (; last_unbound >= 0; --last_unbound) {
02031 if (!vars_[last_unbound]->Bound()) {
02032 if (coefs_[last_unbound] <= slack) {
02033 max_coefficient_.SetValue(solver(), coefs_[last_unbound]);
02034 break;
02035 } else {
02036 vars_[last_unbound]->SetValue(0);
02037 }
02038 }
02039 }
02040 first_unbound_backward_.SetValue(solver(), last_unbound);
02041 }
02042 }
02043
02044 virtual void InitialPropagate() {
02045 Solver* const s = solver();
02046 int last_unbound = -1;
02047 int64 sum = 0LL;
02048 for (int index = 0; index < size_; ++index) {
02049 if (vars_[index]->Bound()) {
02050 const int64 value = vars_[index]->Min();
02051 sum += value * coefs_[index];
02052 } else {
02053 last_unbound = index;
02054 }
02055 }
02056 sum_of_bound_variables_.SetValue(s, sum);
02057 first_unbound_backward_.SetValue(s, last_unbound);
02058 PushFromTop();
02059 }
02060
02061 void Update(int var_index) {
02062 if (vars_[var_index]->Min() == 1) {
02063 sum_of_bound_variables_.SetValue(
02064 solver(), sum_of_bound_variables_.Value() + coefs_[var_index]);
02065 PushFromTop();
02066 }
02067 }
02068
02069 virtual string DebugString() const {
02070 return StringPrintf("BooleanScalProd([%s], [%s]) <= %" GG_LL_FORMAT "d)",
02071 DebugStringArray(vars_.get(), size_, ", ").c_str(),
02072 Int64ArrayToString(coefs_.get(), size_, ", ").c_str(),
02073 upper_bound_);
02074 }
02075
02076 void Accept(ModelVisitor* const visitor) const {
02077 visitor->BeginVisitConstraint(ModelVisitor::kScalProdLessOrEqual, this);
02078 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
02079 vars_.get(),
02080 size_);
02081 visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
02082 coefs_.get(),
02083 size_);
02084 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument,
02085 upper_bound_);
02086 visitor->EndVisitConstraint(ModelVisitor::kScalProdLessOrEqual, this);
02087 }
02088
02089 private:
02090 scoped_array<IntVar*> vars_;
02091 int size_;
02092 scoped_array<int64> coefs_;
02093 int64 upper_bound_;
02094 Rev<int> first_unbound_backward_;
02095 Rev<int64> sum_of_bound_variables_;
02096 Rev<int64> max_coefficient_;
02097 };
02098
02099
02100
02101 class PositiveBooleanScalProdEqVar : public CastConstraint {
02102 public:
02103 PositiveBooleanScalProdEqVar(Solver* const s,
02104 const IntVar* const * vars,
02105 int size,
02106 const int64* const coefs,
02107 IntVar* const var)
02108 : CastConstraint(s, var),
02109 size_(size),
02110 vars_(new IntVar*[size_]),
02111 coefs_(new int64[size_]),
02112 first_unbound_backward_(size_ - 1),
02113 sum_of_bound_variables_(0LL),
02114 sum_of_all_variables_(0LL),
02115 max_coefficient_(0) {
02116 CHECK_GT(size, 0);
02117 CHECK(vars != NULL);
02118 CHECK(coefs != NULL);
02119 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
02120 memcpy(coefs_.get(), coefs, size_ * sizeof(*coefs));
02121 SortBothChangeConstant(vars_.get(), coefs_.get(), &size_, true);
02122 max_coefficient_.SetValue(s, coefs_[size_ - 1]);
02123 }
02124
02125 virtual ~PositiveBooleanScalProdEqVar() {}
02126
02127 virtual void Post() {
02128 for (int var_index = 0; var_index < size_; ++var_index) {
02129 if (vars_[var_index]->Bound()) {
02130 continue;
02131 }
02132 Demon* const d =
02133 MakeConstraintDemon1(solver(),
02134 this,
02135 &PositiveBooleanScalProdEqVar::Update,
02136 "Update",
02137 var_index);
02138 vars_[var_index]->WhenRange(d);
02139 }
02140 if (!target_var_->Bound()) {
02141 Demon* const uv =
02142 MakeConstraintDemon0(solver(),
02143 this,
02144 &PositiveBooleanScalProdEqVar::Propagate,
02145 "Propagate");
02146 target_var_->WhenRange(uv);
02147 }
02148 }
02149
02150 void Propagate() {
02151 target_var_->SetRange(sum_of_bound_variables_.Value(),
02152 sum_of_all_variables_.Value());
02153 const int64 slack_up = target_var_->Max() - sum_of_bound_variables_.Value();
02154 const int64 slack_down = sum_of_all_variables_.Value() - target_var_->Min();
02155 const int64 max_coeff = max_coefficient_.Value();
02156 if (slack_down < max_coeff || slack_up < max_coeff) {
02157 int64 last_unbound = first_unbound_backward_.Value();
02158 for (; last_unbound >= 0; --last_unbound) {
02159 if (!vars_[last_unbound]->Bound()) {
02160 if (coefs_[last_unbound] > slack_up) {
02161 vars_[last_unbound]->SetValue(0);
02162 } else if (coefs_[last_unbound] > slack_down) {
02163 vars_[last_unbound]->SetValue(1);
02164 } else {
02165 max_coefficient_.SetValue(solver(), coefs_[last_unbound]);
02166 break;
02167 }
02168 }
02169 }
02170 first_unbound_backward_.SetValue(solver(), last_unbound);
02171 }
02172 }
02173
02174 virtual void InitialPropagate() {
02175 Solver* const s = solver();
02176 int last_unbound = -1;
02177 int64 sum_bound = 0;
02178 int64 sum_all = 0;
02179 for (int index = 0; index < size_; ++index) {
02180 const int64 value = vars_[index]->Max() * coefs_[index];
02181 sum_all += value;
02182 if (vars_[index]->Bound()) {
02183 sum_bound += value;
02184 } else {
02185 last_unbound = index;
02186 }
02187 }
02188 sum_of_bound_variables_.SetValue(s, sum_bound);
02189 sum_of_all_variables_.SetValue(s, sum_all);
02190 first_unbound_backward_.SetValue(s, last_unbound);
02191 Propagate();
02192 }
02193
02194 void Update(int var_index) {
02195 if (vars_[var_index]->Min() == 1) {
02196 sum_of_bound_variables_.SetValue(
02197 solver(), sum_of_bound_variables_.Value() + coefs_[var_index]);
02198 } else {
02199 sum_of_all_variables_.SetValue(
02200 solver(), sum_of_all_variables_.Value() - coefs_[var_index]);
02201 }
02202 Propagate();
02203 }
02204
02205 virtual string DebugString() const {
02206 return StringPrintf(
02207 "PositiveBooleanScal([%s], [%s]) == %s",
02208 DebugStringArray(vars_.get(), size_, ", ").c_str(),
02209 Int64ArrayToString(coefs_.get(), size_, ", ").c_str(),
02210 target_var_->DebugString().c_str());
02211 }
02212
02213 void Accept(ModelVisitor* const visitor) const {
02214 visitor->BeginVisitConstraint(ModelVisitor::kScalProdEqual, this);
02215 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
02216 vars_.get(),
02217 size_);
02218 visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
02219 coefs_.get(),
02220 size_);
02221 visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
02222 target_var_);
02223 visitor->EndVisitConstraint(ModelVisitor::kScalProdEqual, this);
02224 }
02225
02226 private:
02227 int size_;
02228 scoped_array<IntVar*> vars_;
02229 scoped_array<int64> coefs_;
02230 Rev<int> first_unbound_backward_;
02231 Rev<int64> sum_of_bound_variables_;
02232 Rev<int64> sum_of_all_variables_;
02233 Rev<int64> max_coefficient_;
02234 };
02235
02236
02237
02238 class PositiveBooleanScalProd : public BaseIntExpr {
02239 public:
02240
02241
02242 PositiveBooleanScalProd(Solver* const s,
02243 const IntVar* const* vars,
02244 int size,
02245 const int64* const coefs)
02246 : BaseIntExpr(s),
02247 size_(size),
02248 vars_(new IntVar*[size_]),
02249 coefs_(new int64[size_]) {
02250 CHECK_GT(size_, 0);
02251 CHECK(vars != NULL);
02252 CHECK(coefs != NULL);
02253 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
02254 memcpy(coefs_.get(), coefs, size_ * sizeof(*coefs));
02255 SortBothChangeConstant(vars_.get(), coefs_.get(), &size_, true);
02256 for (int i = 0; i < size_; ++i) {
02257 DCHECK_GE(coefs_[i], 0);
02258 }
02259 }
02260
02261 PositiveBooleanScalProd(Solver* const s,
02262 const IntVar* const* vars,
02263 int size,
02264 const int* const coefs)
02265 : BaseIntExpr(s),
02266 size_(size),
02267 vars_(new IntVar*[size_]),
02268 coefs_(new int64[size_]) {
02269 CHECK_GT(size_, 0);
02270 CHECK(vars != NULL);
02271 CHECK(coefs != NULL);
02272 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
02273 for (int i = 0; i < size_; ++i) {
02274 coefs_[i] = coefs[i];
02275 DCHECK_GE(coefs_[i], 0);
02276 }
02277 SortBothChangeConstant(vars_.get(), coefs_.get(), &size_, true);
02278 }
02279
02280 virtual ~PositiveBooleanScalProd() {}
02281
02282 virtual int64 Min() const {
02283 int64 min = 0;
02284 for (int i = 0; i < size_; ++i) {
02285 if (vars_[i]->Min()) {
02286 min += coefs_[i];
02287 }
02288 }
02289 return min;
02290 }
02291
02292 virtual void SetMin(int64 m) {
02293 SetRange(m, kint64max);
02294 }
02295
02296 virtual int64 Max() const {
02297 int64 max = 0;
02298 for (int i = 0; i < size_; ++i) {
02299 if (vars_[i]->Max()) {
02300 max += coefs_[i];
02301 }
02302 }
02303 return max;
02304 }
02305
02306 virtual void SetMax(int64 m) {
02307 SetRange(kint64min, m);
02308 }
02309
02310 virtual void SetRange(int64 l, int64 u) {
02311 int64 current_min = 0;
02312 int64 current_max = 0;
02313 int64 diameter = -1;
02314 for (int i = 0; i < size_; ++i) {
02315 const int64 coefficient = coefs_[i];
02316 const int64 var_min = vars_[i]->Min() * coefficient;
02317 const int64 var_max = vars_[i]->Max() * coefficient;
02318 current_min += var_min;
02319 current_max += var_max;
02320 if (var_min != var_max) {
02321 diameter = var_max - var_min;
02322 }
02323 }
02324 if (u >= current_max && l <= current_min) {
02325 return;
02326 }
02327 if (u < current_min || l > current_max) {
02328 solver()->Fail();
02329 }
02330
02331 u = std::min(current_max, u);
02332 l = std::max(l, current_min);
02333
02334 if (u - l > diameter) {
02335 return;
02336 }
02337
02338 for (int i = 0; i < size_; ++i) {
02339 const int64 coefficient = coefs_[i];
02340 IntVar* const var = vars_[i];
02341 const int64 new_min = l - current_max + var->Max() * coefficient;
02342 const int64 new_max = u - current_min + var->Min() * coefficient;
02343 if (new_max < 0 || new_min > coefficient || new_min > new_max) {
02344 solver()->Fail();
02345 }
02346 if (new_min > 0LL) {
02347 var->SetMin(1LL);
02348 } else if (new_max < coefficient) {
02349 var->SetMax(0LL);
02350 }
02351 }
02352 }
02353
02354 virtual string DebugString() const {
02355 return StringPrintf(
02356 "PositiveBooleanScalProd([%s], [%s])",
02357 DebugStringArray(vars_.get(), size_, ", ").c_str(),
02358 Int64ArrayToString(coefs_.get(), size_, ", ").c_str());
02359 }
02360
02361 virtual void WhenRange(Demon* d) {
02362 for (int i = 0; i < size_; ++i) {
02363 vars_[i]->WhenRange(d);
02364 }
02365 }
02366 virtual IntVar* CastToVar() {
02367 Solver* const s = solver();
02368 int64 vmin = 0LL;
02369 int64 vmax = 0LL;
02370 Range(&vmin, &vmax);
02371 IntVar* const var = solver()->MakeIntVar(vmin, vmax);
02372 if (size_ > 0) {
02373 CastConstraint* const ct = s->RevAlloc(
02374 new PositiveBooleanScalProdEqVar(s,
02375 vars_.get(),
02376 size_,
02377 coefs_.get(),
02378 var));
02379 s->AddCastConstraint(ct, var, this);
02380 }
02381 return var;
02382 }
02383
02384 void Accept(ModelVisitor* const visitor) const {
02385 visitor->BeginVisitIntegerExpression(ModelVisitor::kScalProd, this);
02386 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
02387 vars_.get(),
02388 size_);
02389 visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
02390 coefs_.get(),
02391 size_);
02392 visitor->EndVisitIntegerExpression(ModelVisitor::kScalProd, this);
02393 }
02394
02395 private:
02396 int size_;
02397 scoped_array<IntVar*> vars_;
02398 scoped_array<int64> coefs_;
02399 };
02400
02401
02402
02403 class PositiveBooleanScalProdEqCst : public Constraint {
02404 public:
02405 PositiveBooleanScalProdEqCst(Solver* const s,
02406 const IntVar* const * vars,
02407 int size,
02408 const int64* const coefs,
02409 int64 constant)
02410 : Constraint(s),
02411 size_(size),
02412 vars_(new IntVar*[size_]),
02413 coefs_(new int64[size_]),
02414 first_unbound_backward_(size_ - 1),
02415 sum_of_bound_variables_(0LL),
02416 sum_of_all_variables_(0LL),
02417 constant_(constant),
02418 max_coefficient_(0) {
02419 CHECK_GT(size, 0);
02420 CHECK(vars != NULL);
02421 CHECK(coefs != NULL);
02422 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
02423 memcpy(coefs_.get(), coefs, size_ * sizeof(*coefs));
02424 constant_ -= SortBothChangeConstant(vars_.get(),
02425 coefs_.get(),
02426 &size_,
02427 false);
02428 max_coefficient_.SetValue(s, coefs_[size_ - 1]);
02429 }
02430
02431 PositiveBooleanScalProdEqCst(Solver* const s,
02432 const IntVar* const * vars,
02433 int size,
02434 const int* const coefs,
02435 int64 constant)
02436 : Constraint(s),
02437 size_(size),
02438 vars_(new IntVar*[size_]),
02439 coefs_(new int64[size_]),
02440 first_unbound_backward_(size_ - 1),
02441 sum_of_bound_variables_(0LL),
02442 sum_of_all_variables_(0LL),
02443 constant_(constant),
02444 max_coefficient_(0) {
02445 CHECK_GT(size, 0);
02446 CHECK(vars != NULL);
02447 CHECK(coefs != NULL);
02448 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
02449 for (int i = 0; i < size; ++i) {
02450 coefs_[i] = coefs[i];
02451 }
02452 constant_ -= SortBothChangeConstant(vars_.get(),
02453 coefs_.get(),
02454 &size_,
02455 false);
02456 max_coefficient_.SetValue(s, coefs_[size_ - 1]);
02457 }
02458
02459 virtual ~PositiveBooleanScalProdEqCst() {}
02460
02461 virtual void Post() {
02462 for (int var_index = 0; var_index < size_; ++var_index) {
02463 if (!vars_[var_index]->Bound()) {
02464 Demon* const d =
02465 MakeConstraintDemon1(solver(),
02466 this,
02467 &PositiveBooleanScalProdEqCst::Update,
02468 "Update",
02469 var_index);
02470 vars_[var_index]->WhenRange(d);
02471 }
02472 }
02473 }
02474
02475 void Propagate() {
02476 if (sum_of_bound_variables_.Value() > constant_ ||
02477 sum_of_all_variables_.Value() < constant_) {
02478 solver()->Fail();
02479 }
02480 const int64 slack_up = constant_ - sum_of_bound_variables_.Value();
02481 const int64 slack_down = sum_of_all_variables_.Value() - constant_;
02482 const int64 max_coeff = max_coefficient_.Value();
02483 if (slack_down < max_coeff || slack_up < max_coeff) {
02484 int64 last_unbound = first_unbound_backward_.Value();
02485 for (; last_unbound >= 0; --last_unbound) {
02486 if (!vars_[last_unbound]->Bound()) {
02487 if (coefs_[last_unbound] > slack_up) {
02488 vars_[last_unbound]->SetValue(0);
02489 } else if (coefs_[last_unbound] > slack_down) {
02490 vars_[last_unbound]->SetValue(1);
02491 } else {
02492 max_coefficient_.SetValue(solver(), coefs_[last_unbound]);
02493 break;
02494 }
02495 }
02496 }
02497 first_unbound_backward_.SetValue(solver(), last_unbound);
02498 }
02499 }
02500
02501 virtual void InitialPropagate() {
02502 Solver* const s = solver();
02503 int last_unbound = -1;
02504 int64 sum_bound = 0LL;
02505 int64 sum_all = 0LL;
02506 for (int index = 0; index < size_; ++index) {
02507 const int64 value = vars_[index]->Max() * coefs_[index];
02508 sum_all += value;
02509 if (vars_[index]->Bound()) {
02510 sum_bound += value;
02511 } else {
02512 last_unbound = index;
02513 }
02514 }
02515 sum_of_bound_variables_.SetValue(s, sum_bound);
02516 sum_of_all_variables_.SetValue(s, sum_all);
02517 first_unbound_backward_.SetValue(s, last_unbound);
02518 Propagate();
02519 }
02520
02521 void Update(int var_index) {
02522 if (vars_[var_index]->Min() == 1) {
02523 sum_of_bound_variables_.SetValue(
02524 solver(), sum_of_bound_variables_.Value() + coefs_[var_index]);
02525 } else {
02526 sum_of_all_variables_.SetValue(
02527 solver(), sum_of_all_variables_.Value() - coefs_[var_index]);
02528 }
02529 Propagate();
02530 }
02531
02532 virtual string DebugString() const {
02533 return StringPrintf(
02534 "PositiveBooleanScalProd([%s], [%s]) == %" GG_LL_FORMAT "d",
02535 DebugStringArray(vars_.get(), size_, ", ").c_str(),
02536 Int64ArrayToString(coefs_.get(), size_, ", ").c_str(),
02537 constant_);
02538 }
02539
02540 void Accept(ModelVisitor* const visitor) const {
02541 visitor->BeginVisitConstraint(ModelVisitor::kScalProdEqual, this);
02542 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
02543 vars_.get(),
02544 size_);
02545 visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
02546 coefs_.get(),
02547 size_);
02548 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument,
02549 constant_);
02550 visitor->EndVisitConstraint(ModelVisitor::kScalProdEqual, this);
02551 }
02552
02553 private:
02554 int size_;
02555 scoped_array<IntVar*> vars_;
02556 scoped_array<int64> coefs_;
02557 Rev<int> first_unbound_backward_;
02558 Rev<int64> sum_of_bound_variables_;
02559 Rev<int64> sum_of_all_variables_;
02560 int64 constant_;
02561 Rev<int64> max_coefficient_;
02562 };
02563
02564
02565
02566 }
02567 Constraint* Solver::MakeSumLessOrEqual(const std::vector<IntVar*>& vars, int64 cst) {
02568 return MakeSumLessOrEqual(vars.data(), vars.size(), cst);
02569 }
02570
02571 Constraint* Solver::MakeSumLessOrEqual(IntVar* const* vars,
02572 int size,
02573 int64 cst) {
02574 if (cst == 1LL && AreAllBooleans(vars, size) && size > 2) {
02575 return RevAlloc(new SumBooleanLessOrEqualToOne(this, vars, size));
02576 } else {
02577 return MakeLessOrEqual(MakeSum(vars, size), cst);
02578 }
02579 }
02580
02581 Constraint* Solver::MakeSumGreaterOrEqual(const std::vector<IntVar*>& vars,
02582 int64 cst) {
02583 return MakeSumGreaterOrEqual(vars.data(), vars.size(), cst);
02584 }
02585
02586 Constraint* Solver::MakeSumGreaterOrEqual(IntVar* const* vars,
02587 int size,
02588 int64 cst) {
02589 if (cst == 1LL && AreAllBooleans(vars, size) && size > 2) {
02590 return RevAlloc(new SumBooleanGreaterOrEqualToOne(this, vars, size));
02591 } else {
02592 return MakeGreaterOrEqual(MakeSum(vars, size), cst);
02593 }
02594 }
02595
02596 Constraint* Solver::MakeSumEquality(const std::vector<IntVar*>& vars, int64 cst) {
02597 return MakeSumEquality(vars.data(), vars.size(), cst);
02598 }
02599
02600 Constraint* Solver::MakeSumEquality(IntVar* const* vars,
02601 int size,
02602 int64 cst) {
02603 if (AreAllBooleans(vars, size) && size > 2) {
02604 if (cst == 1) {
02605 return RevAlloc(new SumBooleanEqualToOne(this, vars, size));
02606 } else if (cst < 0 || cst > size) {
02607 return MakeFalseConstraint();
02608 } else {
02609 return RevAlloc(new SumBooleanEqualToVar(this,
02610 vars,
02611 size,
02612 MakeIntConst(cst)));
02613 }
02614 } else {
02615 return RevAlloc(new SumConstraint(this, vars, size, MakeIntConst(cst)));
02616 }
02617 }
02618
02619 Constraint* Solver::MakeSumEquality(const std::vector<IntVar*>& vars,
02620 IntVar* const var) {
02621 return MakeSumEquality(vars.data(), vars.size(), var);
02622 }
02623
02624 Constraint* Solver::MakeSumEquality(IntVar* const* vars,
02625 int size,
02626 IntVar* const var) {
02627 if (AreAllBooleans(vars, size) && size > 2) {
02628 return RevAlloc(new SumBooleanEqualToVar(this, vars, size, var));
02629 } else {
02630 return RevAlloc(new SumConstraint(this, vars, size, var));
02631 }
02632 }
02633
02634 Constraint* Solver::MakeScalProdEquality(const std::vector<IntVar*>& vars,
02635 const std::vector<int64>& coefficients,
02636 int64 cst) {
02637 DCHECK_EQ(vars.size(), coefficients.size());
02638 return MakeScalProdEquality(vars.data(),
02639 vars.size(),
02640 coefficients.data(),
02641 cst);
02642 }
02643
02644 Constraint* Solver::MakeScalProdEquality(const std::vector<IntVar*>& vars,
02645 const std::vector<int>& coefficients,
02646 int64 cst) {
02647 DCHECK_EQ(vars.size(), coefficients.size());
02648 return MakeScalProdEquality(vars.data(),
02649 vars.size(),
02650 coefficients.data(),
02651 cst);
02652 }
02653
02654 namespace {
02655 template<class T> Constraint* MakeScalProdEqualityFct(Solver* const solver,
02656 IntVar* const * vars,
02657 int size,
02658 T const * coefficients,
02659 int64 cst) {
02660 if (size == 0 || AreAllNull<T>(coefficients, size)) {
02661 return cst == 0 ? solver->MakeTrueConstraint()
02662 : solver->MakeFalseConstraint();
02663 }
02664 if (AreAllBooleans(vars, size) && AreAllPositive<T>(coefficients, size)) {
02665
02666 return solver->RevAlloc(new PositiveBooleanScalProdEqCst(solver,
02667 vars,
02668 size,
02669 coefficients,
02670 cst));
02671 }
02672 std::vector<IntVar*> terms;
02673 for (int i = 0; i < size; ++i) {
02674 terms.push_back(solver->MakeProd(vars[i], coefficients[i])->Var());
02675 }
02676 return solver->MakeEquality(solver->MakeSum(terms), cst);
02677 }
02678 }
02679
02680 Constraint* Solver::MakeScalProdEquality(IntVar* const * vars,
02681 int size,
02682 int64 const * coefficients,
02683 int64 cst) {
02684 return MakeScalProdEqualityFct<int64>(this, vars, size, coefficients, cst);
02685 }
02686
02687 Constraint* Solver::MakeScalProdEquality(IntVar* const * vars,
02688 int size,
02689 int const * coefficients,
02690 int64 cst) {
02691 return MakeScalProdEqualityFct<int>(this, vars, size, coefficients, cst);
02692 }
02693
02694 Constraint* Solver::MakeScalProdGreaterOrEqual(const std::vector<IntVar*>& vars,
02695 const std::vector<int64>& coeffs,
02696 int64 cst) {
02697 DCHECK_EQ(vars.size(), coeffs.size());
02698 return MakeScalProdGreaterOrEqual(vars.data(),
02699 vars.size(),
02700 coeffs.data(),
02701 cst);
02702 }
02703
02704 Constraint* Solver::MakeScalProdGreaterOrEqual(const std::vector<IntVar*>& vars,
02705 const std::vector<int>& coeffs,
02706 int64 cst) {
02707 DCHECK_EQ(vars.size(), coeffs.size());
02708 return MakeScalProdGreaterOrEqual(vars.data(),
02709 vars.size(),
02710 coeffs.data(),
02711 cst);
02712 }
02713
02714 namespace {
02715 template<class T>
02716 Constraint* MakeScalProdGreaterOrEqualFct(Solver* solver,
02717 IntVar* const * vars,
02718 int size,
02719 T const * coefficients,
02720 int64 cst) {
02721 if (size == 0 || AreAllNull<T>(coefficients, size)) {
02722 return cst <= 0 ? solver->MakeTrueConstraint()
02723 : solver->MakeFalseConstraint();
02724 }
02725 std::vector<IntVar*> terms;
02726 for (int i = 0; i < size; ++i) {
02727 terms.push_back(solver->MakeProd(vars[i], coefficients[i])->Var());
02728 }
02729 return solver->MakeGreaterOrEqual(solver->MakeSum(terms), cst);
02730 }
02731 }
02732
02733 Constraint* Solver::MakeScalProdGreaterOrEqual(IntVar* const * vars,
02734 int size,
02735 int64 const * coefficients,
02736 int64 cst) {
02737 return MakeScalProdGreaterOrEqualFct<int64>(this,
02738 vars, size, coefficients, cst);
02739 }
02740
02741 Constraint* Solver::MakeScalProdGreaterOrEqual(IntVar* const * vars,
02742 int size,
02743 int const * coefficients,
02744 int64 cst) {
02745 return MakeScalProdGreaterOrEqualFct<int>(this,
02746 vars, size, coefficients, cst);
02747 }
02748
02749 Constraint* Solver::MakeScalProdLessOrEqual(const std::vector<IntVar*>& vars,
02750 const std::vector<int64>& coefficients,
02751 int64 cst) {
02752 DCHECK_EQ(vars.size(), coefficients.size());
02753 return MakeScalProdLessOrEqual(vars.data(),
02754 vars.size(),
02755 coefficients.data(),
02756 cst);
02757 }
02758
02759 Constraint* Solver::MakeScalProdLessOrEqual(const std::vector<IntVar*>& vars,
02760 const std::vector<int>& coefficients,
02761 int64 cst) {
02762 DCHECK_EQ(vars.size(), coefficients.size());
02763 return MakeScalProdLessOrEqual(vars.data(),
02764 vars.size(),
02765 coefficients.data(),
02766 cst);
02767 }
02768
02769 namespace {
02770 template<class T> Constraint* MakeScalProdLessOrEqualFct(Solver* solver,
02771 IntVar* const * vars,
02772 int size,
02773 T const * coefficients,
02774 int64 upper_bound) {
02775 if (size == 0 || AreAllNull<T>(coefficients, size)) {
02776 return upper_bound >= 0 ? solver->MakeTrueConstraint()
02777 : solver->MakeFalseConstraint();
02778 }
02779
02780 if (AreAllBoundOrNull(vars, coefficients, size)) {
02781 int64 cst = 0;
02782 for (int i = 0; i < size; ++i) {
02783 cst += vars[i]->Min() * coefficients[i];
02784 }
02785 return cst <= upper_bound ?
02786 solver->MakeTrueConstraint() :
02787 solver->MakeFalseConstraint();
02788 }
02789 if (AreAllBooleans(vars, size) && AreAllPositive<T>(coefficients, size)) {
02790 return solver->RevAlloc(new BooleanScalProdLessConstant(solver,
02791 vars,
02792 size,
02793 coefficients,
02794 upper_bound));
02795 }
02796 std::vector<IntVar*> terms;
02797 for (int i = 0; i < size; ++i) {
02798 terms.push_back(solver->MakeProd(vars[i], coefficients[i])->Var());
02799 }
02800 return solver->MakeLessOrEqual(solver->MakeSum(terms), upper_bound);
02801 }
02802 }
02803
02804 Constraint* Solver::MakeScalProdLessOrEqual(IntVar* const * vars,
02805 int size,
02806 int64 const * coefficients,
02807 int64 cst) {
02808 return MakeScalProdLessOrEqualFct<int64>(this, vars, size, coefficients, cst);
02809 }
02810
02811 Constraint* Solver::MakeScalProdLessOrEqual(IntVar* const * vars,
02812 int size,
02813 int const * coefficients,
02814 int64 cst) {
02815 return MakeScalProdLessOrEqualFct<int>(this, vars, size, coefficients, cst);
02816 }
02817
02818 IntExpr* Solver::MakeScalProd(const std::vector<IntVar*>& vars,
02819 const std::vector<int64>& coefs) {
02820 DCHECK_EQ(vars.size(), coefs.size());
02821 return MakeScalProd(vars.data(), coefs.data(), vars.size());
02822 }
02823
02824 IntExpr* Solver::MakeScalProd(const std::vector<IntVar*>& vars,
02825 const std::vector<int>& coefs) {
02826 DCHECK_EQ(vars.size(), coefs.size());
02827 return MakeScalProd(vars.data(), coefs.data(), vars.size());
02828 }
02829
02830 namespace {
02831 template<class T> IntExpr* MakeScalProdFct(Solver* solver,
02832 IntVar* const * vars,
02833 const T* const coefs,
02834 int size) {
02835 if (size == 0 || AreAllNull<T>(coefs, size)) {
02836 return solver->MakeIntConst(0LL);
02837 }
02838 if (AreAllBoundOrNull(vars, coefs, size)) {
02839 int64 cst = 0;
02840 for (int i = 0; i < size; ++i) {
02841 cst += vars[i]->Min() * coefs[i];
02842 }
02843 return solver->MakeIntConst(cst);
02844 }
02845 if (AreAllBooleans(vars, size)) {
02846 if (AreAllPositive<T>(coefs, size)) {
02847 return solver->RegisterIntExpr(solver->RevAlloc(
02848 new PositiveBooleanScalProd(solver, vars, size, coefs)));
02849 } else {
02850
02851
02852
02853
02854
02855
02856
02857 std::vector<T> positive_coefs;
02858 std::vector<T> negative_coefs;
02859 std::vector<IntVar*> positive_coef_vars;
02860 std::vector<IntVar*> negative_coef_vars;
02861 for (int i = 0; i < size; ++i) {
02862 const T coef = coefs[i];
02863 if (coef > 0) {
02864 positive_coefs.push_back(coef);
02865 positive_coef_vars.push_back(vars[i]);
02866 } else if (coef < 0) {
02867 negative_coefs.push_back(-coef);
02868 negative_coef_vars.push_back(vars[i]);
02869 }
02870 }
02871 CHECK_GT(negative_coef_vars.size(), 0);
02872 IntExpr* const negatives =
02873 solver->RegisterIntExpr(solver->RevAlloc(
02874 new PositiveBooleanScalProd(solver,
02875 negative_coef_vars.data(),
02876 negative_coef_vars.size(),
02877 negative_coefs.data())));
02878 if (!positive_coefs.empty()) {
02879 IntExpr* const positives =
02880 solver->RegisterIntExpr(solver->RevAlloc(
02881 new PositiveBooleanScalProd(solver,
02882 positive_coef_vars.data(),
02883 positive_coef_vars.size(),
02884 positive_coefs.data())));
02885
02886
02887 return solver->MakeDifference(positives->Var(), negatives->Var());
02888 } else {
02889 return solver->MakeOpposite(negatives);
02890 }
02891 }
02892 }
02893 std::vector<IntVar*> terms;
02894 for (int i = 0; i < size; ++i) {
02895 terms.push_back(solver->MakeProd(vars[i], coefs[i])->Var());
02896 }
02897 return solver->MakeSum(terms);
02898 }
02899 }
02900
02901 IntExpr* Solver::MakeScalProd(IntVar* const * vars,
02902 const int64* const coefs,
02903 int size) {
02904 return MakeScalProdFct<int64>(this, vars, coefs, size);
02905 }
02906
02907 IntExpr* Solver::MakeScalProd(IntVar* const * vars,
02908 const int* const coefs,
02909 int size) {
02910 return MakeScalProdFct<int>(this, vars, coefs, size);
02911 }
02912
02913
02914 }