00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <string>
00015 #include <vector>
00016
00017 #include "base/integral_types.h"
00018 #include "base/logging.h"
00019 #include "base/macros.h"
00020 #include "base/stringprintf.h"
00021 #include "base/stl_util.h"
00022 #include "constraint_solver/constraint_solver.h"
00023 #include "util/string_array.h"
00024
00025 namespace operations_research {
00026
00027
00028
00029 void NoGoodManager::EnterSearch() {
00030 Init();
00031 }
00032
00033 void NoGoodManager::BeginNextDecision(DecisionBuilder* const db) {
00034 Apply();
00035 }
00036
00037 bool NoGoodManager::AcceptSolution() {
00038 Apply();
00039 return true;
00040 }
00041
00042 NoGood* NoGoodManager::MakeNoGood() {
00043 return new NoGood();
00044 }
00045
00046
00047
00048 class NoGoodTerm {
00049 public:
00050 enum TermStatus {
00051 ALWAYS_TRUE,
00052 ALWAYS_FALSE,
00053 UNDECIDED
00054 };
00055 NoGoodTerm() {}
00056 virtual ~NoGoodTerm() {}
00057
00058 virtual TermStatus Evaluate() const = 0;
00059 virtual void Refute() = 0;
00060 virtual string DebugString() const = 0;
00061 private:
00062 DISALLOW_COPY_AND_ASSIGN(NoGoodTerm);
00063 };
00064
00065 namespace {
00066
00067
00068
00069 class IntegerVariableNoGoodTerm : public NoGoodTerm {
00070 public:
00071 IntegerVariableNoGoodTerm(IntVar* const var, int64 value, bool assign)
00072 : integer_variable_(var), value_(value), assign_(assign) {
00073 CHECK_NOTNULL(integer_variable_);
00074 }
00075
00076 virtual TermStatus Evaluate() const {
00077 if (!integer_variable_->Contains(value_)) {
00078 return assign_ ? ALWAYS_FALSE : ALWAYS_TRUE;
00079 } else if (integer_variable_->Bound()) {
00080 return assign_ ? ALWAYS_TRUE : ALWAYS_FALSE;
00081 } else {
00082 return UNDECIDED;
00083 }
00084 }
00085
00086 virtual void Refute() {
00087 if (assign_) {
00088 integer_variable_->RemoveValue(value_);
00089 } else {
00090 integer_variable_->SetValue(value_);
00091 }
00092 }
00093
00094 virtual string DebugString() const {
00095 return StringPrintf("(var_%s %s %lld)",
00096 integer_variable_->name().c_str(),
00097 assign_ ? "==" : "!=",
00098 value_);
00099 }
00100
00101 IntVar* integer_variable() const { return integer_variable_; }
00102 int64 value() const { return value_; }
00103 bool assign() const { return assign_; }
00104
00105 private:
00106 IntVar* const integer_variable_;
00107 const int64 value_;
00108 const bool assign_;
00109 DISALLOW_COPY_AND_ASSIGN(IntegerVariableNoGoodTerm);
00110 };
00111 }
00112
00113
00114
00115 NoGood::~NoGood() {
00116 STLDeleteElements(&terms_);
00117 }
00118
00119 void NoGood::AddIntegerVariableEqualValueTerm(IntVar* const var, int64 value) {
00120 terms_.push_back(new IntegerVariableNoGoodTerm(var, value, true));
00121 }
00122
00123 void NoGood::AddIntegerVariableNotEqualValueTerm(IntVar* const var,
00124 int64 value) {
00125 terms_.push_back(new IntegerVariableNoGoodTerm(var, value, false));
00126 }
00127
00128 bool NoGood::Apply(Solver* const solver) {
00129 NoGoodTerm* first_undecided = NULL;
00130 for (int i = 0; i < terms_.size(); ++i) {
00131 switch (terms_[i]->Evaluate()) {
00132 case NoGoodTerm::ALWAYS_TRUE: {
00133 break;
00134 }
00135 case NoGoodTerm::ALWAYS_FALSE: {
00136 return false;
00137 }
00138 case NoGoodTerm::UNDECIDED: {
00139 if (first_undecided == NULL) {
00140 first_undecided = terms_[i];
00141 } else {
00142
00143 return true;
00144 }
00145 break;
00146 }
00147 }
00148 }
00149 if (first_undecided == NULL && terms_.size() > 0) {
00150 solver->Fail();
00151 }
00152 if (first_undecided != NULL) {
00153 first_undecided->Refute();
00154 return false;
00155 }
00156 return false;
00157 }
00158
00159 string NoGood::DebugString() const {
00160 return StringPrintf("(%s)", DebugStringVector(terms_, " && ").c_str());
00161 }
00162
00163 namespace {
00164
00165
00166
00167
00168
00169 class NaiveNoGoodManager : public NoGoodManager {
00170 public:
00171 explicit NaiveNoGoodManager(Solver* const solver) : NoGoodManager(solver) {}
00172 virtual ~NaiveNoGoodManager() {
00173 Clear();
00174 }
00175
00176 virtual void Clear() {
00177 STLDeleteElements(&nogoods_);
00178 }
00179
00180 virtual void Init() {}
00181
00182 virtual void AddNoGood(NoGood* const nogood) {
00183 nogoods_.push_back(nogood);
00184 }
00185
00186 virtual int NoGoodCount() const {
00187 return nogoods_.size();
00188 }
00189
00190 virtual void Apply() {
00191 Solver* const s = solver();
00192 for (int i = 0; i < nogoods_.size(); ++i) {
00193 nogoods_[i]->Apply(s);
00194 }
00195 }
00196
00197 string DebugString() const {
00198 return StringPrintf("NaiveNoGoodManager(%d)", NoGoodCount());
00199 }
00200
00201 private:
00202 std::vector<NoGood*> nogoods_;
00203 };
00204 }
00205
00206
00207
00208 NoGoodManager* Solver::MakeNoGoodManager() {
00209 return RevAlloc(new NaiveNoGoodManager(this));
00210 }
00211
00212 }