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 "constraint_solver/constraint_solver.h"
00025 #include "constraint_solver/constraint_solveri.h"
00026 #include "util/string_array.h"
00027
00028 namespace operations_research {
00029 namespace {
00030
00031 class BaseAllDifferent : public Constraint {
00032 public:
00033 BaseAllDifferent(Solver* const s, const IntVar* const* vars, int size);
00034 ~BaseAllDifferent() {}
00035 string DebugStringInternal(const string& name) const;
00036 protected:
00037 scoped_array<IntVar*> vars_;
00038 int size_;
00039 };
00040
00041 BaseAllDifferent::BaseAllDifferent(Solver* const s,
00042 const IntVar* const* vars,
00043 int size)
00044 : Constraint(s), vars_(NULL), size_(size) {
00045 CHECK_GE(size_, 0);
00046 if (size_ > 0) {
00047 vars_.reset(new IntVar*[size_]);
00048 memcpy(vars_.get(), vars, size_ * sizeof(*vars));
00049 }
00050 }
00051
00052 string BaseAllDifferent::DebugStringInternal(const string& name) const {
00053 string out = name + "(";
00054 out.append(DebugStringArray(vars_.get(), size_, ", "));
00055 out.append(")");
00056 return out;
00057 }
00058
00059
00060
00061
00062
00063 class ValueAllDifferent : public BaseAllDifferent {
00064 public:
00065 ValueAllDifferent(Solver* const s, const IntVar* const* vars, int size);
00066 virtual ~ValueAllDifferent() {}
00067
00068 virtual void Post();
00069 virtual void InitialPropagate();
00070 void OneMove(int index);
00071 bool AllMoves();
00072
00073 virtual string DebugString() const;
00074 virtual void Accept(ModelVisitor* const visitor) const {
00075 visitor->BeginVisitConstraint(ModelVisitor::kAllDifferent, this);
00076 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00077 vars_.get(),
00078 size_);
00079 visitor->VisitIntegerArgument(ModelVisitor::kRangeArgument, 0);
00080 visitor->EndVisitConstraint(ModelVisitor::kAllDifferent, this);
00081 }
00082
00083 private:
00084 RevSwitch all_instantiated_;
00085 };
00086
00087 ValueAllDifferent::ValueAllDifferent(Solver* const s,
00088 const IntVar* const* vars,
00089 int size)
00090 : BaseAllDifferent(s, vars, size) {}
00091
00092 string ValueAllDifferent::DebugString() const {
00093 return DebugStringInternal("ValueAllDifferent");
00094 }
00095
00096 void ValueAllDifferent::Post() {
00097 for (int i = 0; i < size_; ++i) {
00098 IntVar* var = vars_[i];
00099 Demon* d = MakeConstraintDemon1(solver(),
00100 this,
00101 &ValueAllDifferent::OneMove,
00102 "OneMove",
00103 i);
00104 var->WhenBound(d);
00105 }
00106 }
00107
00108 void ValueAllDifferent::InitialPropagate() {
00109 for (int i = 0; i < size_; ++i) {
00110 if (vars_[i]->Bound()) {
00111 OneMove(i);
00112 }
00113 }
00114 }
00115
00116 void ValueAllDifferent::OneMove(int index) {
00117 if (!AllMoves()) {
00118 const int64 val = vars_[index]->Value();
00119 for (int j = 0; j < size_; ++j) {
00120 if (index != j) {
00121 vars_[j]->RemoveValue(val);
00122 }
00123 }
00124 }
00125 }
00126
00127 bool ValueAllDifferent::AllMoves() {
00128 if (all_instantiated_.Switched() || size_ == 0) {
00129 return true;
00130 }
00131 for (int i = 0; i < size_; ++i) {
00132 if (!vars_[i]->Bound()) {
00133 return false;
00134 }
00135 }
00136 scoped_array<int64> values(new int64[size_]);
00137 for (int i = 0; i < size_; ++i) {
00138 values[i] = vars_[i]->Value();
00139 }
00140 std::sort(values.get(), values.get() + size_);
00141 for (int i = 0; i < size_ - 1; ++i) {
00142 if (values[i] == values[i + 1]) {
00143 values.reset(NULL);
00144 solver()->Fail();
00145 }
00146 }
00147 all_instantiated_.Switch(solver());
00148 return true;
00149 }
00150
00151
00152
00153
00154 struct Interval {
00155 int64 min;
00156 int64 max;
00157 int min_rank;
00158 int max_rank;
00159 };
00160
00161
00162
00163
00164
00165 struct CompareIntervalMin {
00166 bool operator()(const Interval* i1, const Interval* i2) {
00167 return (i1->min < i2->min);
00168 }
00169 };
00170
00171
00172 struct CompareIntervalMax {
00173 bool operator()(const Interval* i1, const Interval* i2) {
00174 return (i1->max < i2->max);
00175 }
00176 };
00177
00178 void PathSet(int start, int end, int to, int* const tree) {
00179 int k = start;
00180 int l = start;
00181 while (l != end) {
00182 k = l;
00183 l = tree[k];
00184 tree[k] = to;
00185 }
00186 }
00187
00188 int PathMin(const int* const tree, int index) {
00189 int i = index;
00190 while (tree[i] < i) {
00191 i = tree[i];
00192 }
00193 return i;
00194 }
00195
00196 int PathMax(const int* const tree, int index) {
00197 int i = index;
00198 while (tree[i] > i) {
00199 i = tree[i];
00200 }
00201 return i;
00202 }
00203
00204 class BoundsAllDifferent : public BaseAllDifferent {
00205 public:
00206 BoundsAllDifferent(Solver* const s, const IntVar* const * vars, int size)
00207 : BaseAllDifferent(s, vars, size),
00208 intervals_(new Interval[size + 1]),
00209 min_sorted_(new Interval*[size]),
00210 max_sorted_(new Interval*[size]),
00211 bounds_(new int64[2 * size + 2]),
00212 tree_(new int[2 * size + 2]),
00213 diff_(new int64[2 * size + 2]),
00214 hall_(new int[2 * size + 2]),
00215 active_size_(0) {
00216 for (int i = 0; i < size; ++i) {
00217 max_sorted_[i] = &intervals_[i];
00218 min_sorted_[i] = max_sorted_[i];
00219 }
00220 }
00221 virtual ~BoundsAllDifferent() {}
00222 virtual void Post() {
00223 Demon* range = MakeDelayedConstraintDemon0(
00224 solver(),
00225 this,
00226 &BoundsAllDifferent::IncrementalPropagate,
00227 "IncrementalPropagate");
00228
00229 for (int i = 0; i < size_; ++i) {
00230 vars_[i]->WhenRange(range);
00231 Demon* bound = MakeConstraintDemon1(solver(),
00232 this,
00233 &BoundsAllDifferent::PropagateValue,
00234 "PropagateValue",
00235 i);
00236 vars_[i]->WhenBound(bound);
00237 }
00238 }
00239
00240 virtual void InitialPropagate() {
00241 IncrementalPropagate();
00242 for (int i = 0; i < size_; ++i) {
00243 if (vars_[i]->Bound()) {
00244 PropagateValue(i);
00245 }
00246 }
00247 }
00248
00249 virtual void IncrementalPropagate() {
00250 for (int i = 0; i < size_; ++i) {
00251 intervals_[i].min = vars_[i]->Min();
00252 intervals_[i].max = vars_[i]->Max();
00253 }
00254
00255 SortArray();
00256
00257 bool modified = PropagateMin();
00258 modified |= PropagateMax();
00259
00260 if (modified) {
00261 for (int i = 0; i < size_; ++i) {
00262 vars_[i]->SetRange(intervals_[i].min, intervals_[i].max);
00263 }
00264 }
00265 }
00266
00267 void PropagateValue(int index) {
00268 const int64 to_remove = vars_[index]->Value();
00269 for (int j = 0; j < index; j++) {
00270 vars_[j]->RemoveValue(to_remove);
00271 }
00272 for (int j = index + 1; j < size_; j++) {
00273 vars_[j]->RemoveValue(to_remove);
00274 }
00275 }
00276
00277 virtual string DebugString() const {
00278 return DebugStringInternal("BoundsAllDifferent");
00279 }
00280
00281 virtual void Accept(ModelVisitor* const visitor) const {
00282 visitor->BeginVisitConstraint(ModelVisitor::kAllDifferent, this);
00283 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
00284 vars_.get(),
00285 size_);
00286 visitor->VisitIntegerArgument(ModelVisitor::kRangeArgument, 1);
00287 visitor->EndVisitConstraint(ModelVisitor::kAllDifferent, this);
00288 }
00289
00290 private:
00291
00292
00293 void SortArray();
00294
00295
00296 bool PropagateMin();
00297 bool PropagateMax();
00298
00299 int64 stamp_;
00300 scoped_array<Interval> intervals_;
00301 scoped_array<Interval*> min_sorted_;
00302 scoped_array<Interval*> max_sorted_;
00303
00304
00305 scoped_array<int64> bounds_;
00306 scoped_array<int> tree_;
00307 scoped_array<int64> diff_;
00308 scoped_array<int> hall_;
00309 int active_size_;
00310 };
00311
00312 void BoundsAllDifferent::SortArray() {
00313 std::sort(min_sorted_.get(), min_sorted_.get() + size_, CompareIntervalMin());
00314 std::sort(max_sorted_.get(), max_sorted_.get() + size_, CompareIntervalMax());
00315
00316 int64 min = min_sorted_[0]->min;
00317 int64 max = max_sorted_[0]->max + 1;
00318 int64 last = min - 2;
00319 bounds_[0] = last;
00320
00321 int i = 0;
00322 int j = 0;
00323 int nb = 0;
00324 for (;;) {
00325 if (i < size_ && min <= max) {
00326 if (min != last) {
00327 last = min;
00328 bounds_[++nb] = last;
00329 }
00330 min_sorted_[i]->min_rank = nb;
00331 if (++i < size_) {
00332 min = min_sorted_[i]->min;
00333 }
00334 } else {
00335 if (max != last) {
00336 last = max;
00337 bounds_[++nb] = last;
00338 }
00339 max_sorted_[j]->max_rank = nb;
00340 if (++j == size_) {
00341 break;
00342 }
00343 max = max_sorted_[j]->max + 1;
00344 }
00345 }
00346 active_size_ = nb;
00347 bounds_[nb + 1] = bounds_[nb] + 2;
00348 }
00349
00350 bool BoundsAllDifferent::PropagateMin() {
00351 bool modified = false;
00352
00353 for (int i = 1; i <= active_size_ + 1; ++i) {
00354 hall_[i] = i - 1;
00355 tree_[i] = i - 1;
00356 diff_[i] = bounds_[i] - bounds_[i - 1];
00357 }
00358 for (int i = 0; i < size_; ++i) {
00359 const int x = max_sorted_[i]->min_rank;
00360 const int y = max_sorted_[i]->max_rank;
00361 int z = PathMax(tree_.get(), x + 1);
00362 int j = tree_[z];
00363 if (--diff_[z] == 0) {
00364 tree_[z] = z + 1;
00365 z = PathMax(tree_.get(), z + 1);
00366 tree_[z] = j;
00367 }
00368 PathSet(x + 1, z, z, tree_.get());
00369 if (diff_[z] < bounds_[z] - bounds_[y]) {
00370 solver()->Fail();
00371 }
00372 if (hall_[x] > x) {
00373 int w = PathMax(hall_.get(), hall_[x]);
00374 max_sorted_[i]->min = bounds_[w];
00375 PathSet(x, w, w, hall_.get());
00376 modified = true;
00377 }
00378 if (diff_[z] == bounds_[z] - bounds_[y]) {
00379 PathSet(hall_[y], j - 1, y, hall_.get());
00380 hall_[y] = j - 1;
00381 }
00382 }
00383 return modified;
00384 }
00385
00386
00387 bool BoundsAllDifferent::PropagateMax() {
00388 bool modified = false;
00389
00390 for (int i = 0; i<= active_size_; i++) {
00391 tree_[i] = i + 1;
00392 hall_[i] = i + 1;
00393 diff_[i] = bounds_[i + 1] - bounds_[i];
00394 }
00395
00396 for (int i = size_ - 1; i >= 0; --i) {
00397 const int x = min_sorted_[i]->max_rank;
00398 const int y = min_sorted_[i]->min_rank;
00399 int z = PathMin(tree_.get(), x - 1);
00400 int j = tree_[z];
00401 if (--diff_[z] == 0) {
00402 tree_[z] = z - 1;
00403 z = PathMin(tree_.get(), z - 1);
00404 tree_[z] = j;
00405 }
00406 PathSet(x - 1, z, z, tree_.get());
00407 if (diff_[z] < bounds_[y] - bounds_[z]) {
00408 solver()->Fail();
00409
00410 }
00411 if (hall_[x] < x) {
00412 int w = PathMin(hall_.get(), hall_[x]);
00413 min_sorted_[i]->max = bounds_[w] - 1;
00414 PathSet(x, w, w, hall_.get());
00415 modified = true;
00416 }
00417 if (diff_[z] == bounds_[y] - bounds_[z]) {
00418 PathSet(hall_[y], j + 1, y, hall_.get());
00419 hall_[y] = j + 1;
00420 }
00421 }
00422 return modified;
00423 }
00424 }
00425
00426 Constraint* Solver::MakeAllDifferent(const std::vector<IntVar*>& vars) {
00427 return MakeAllDifferent(vars.data(), vars.size(), true);
00428 }
00429
00430 Constraint* Solver::MakeAllDifferent(const std::vector<IntVar*>& vars,
00431 bool stronger_propagation) {
00432 return MakeAllDifferent(vars.data(), vars.size(), stronger_propagation);
00433 }
00434
00435 Constraint* Solver::MakeAllDifferent(const IntVar* const* vars,
00436 int size,
00437 bool stronger_propagation) {
00438 for (int i = 0; i < size; ++i) {
00439 CHECK_EQ(this, vars[i]->solver());
00440 }
00441 if (size < 2) {
00442 return MakeTrueConstraint();
00443 } else if (size == 2) {
00444 return MakeNonEquality(const_cast<IntVar* const>(vars[0]),
00445 const_cast<IntVar* const>(vars[1]));
00446 } else {
00447 if (stronger_propagation) {
00448 return RevAlloc(new BoundsAllDifferent(this, vars, size));
00449 } else {
00450 return RevAlloc(new ValueAllDifferent(this, vars, size));
00451 }
00452 }
00453 }
00454 }