From a8082e47eb67baad25cb0b238eb2d88ebb4e39f5 Mon Sep 17 00:00:00 2001 From: "lperron@google.com" Date: Fri, 15 Aug 2014 16:56:56 +0000 Subject: [PATCH] small sync --- src/base/base.swig | 319 ++++++++++++++-------------- src/constraint_solver/element.cc | 23 +- src/constraint_solver/expr_array.cc | 62 +++--- src/graph/hamiltonian_path.h | 124 +++++------ 4 files changed, 270 insertions(+), 258 deletions(-) diff --git a/src/base/base.swig b/src/base/base.swig index f2a797af65..d86a388095 100644 --- a/src/base/base.swig +++ b/src/base/base.swig @@ -28,18 +28,18 @@ // Add a char* cast to the SWIG 1.3.21 typemaps to remove a compiler warning. %typemap(constcode) long long { -PyObject *object = PyLong_FromLongLong($value); -if (object) { -int rc = PyDict_SetItemString(d, (char*) "$symname", object); -Py_DECREF(object); -} + PyObject *object = PyLong_FromLongLong($value); + if (object) { + int rc = PyDict_SetItemString(d, (char*) "$symname", object); + Py_DECREF(object); + } } %typemap(constcode) unsigned long long { -PyObject *object = PyLong_FromUnsignedLongLong($value); -if (object) { -int rc = PyDict_SetItemString(d, (char*) "$symname", object); -Py_DECREF(object); -} + PyObject *object = PyLong_FromUnsignedLongLong($value); + if (object) { + int rc = PyDict_SetItemString(d, (char*) "$symname", object); + Py_DECREF(object); + } } %{ @@ -70,49 +70,52 @@ Py_DECREF(object); // std::string -class std::string; +namespace std { + class std::string; -%typemap(typecheck) std::string = char *; -%typemap(typecheck) const std::string & = char *; + %typemap(typecheck) std::string = char *; + %typemap(typecheck) const std::string & = char *; -%typemap(in) std::string { -char * buf; -Py_ssize_t len; -if (PyString_AsStringAndSize($input, &buf, &len) == -1) -return NULL; -$1 = std::string(buf, len); -} + %typemap(in) std::string { + char * buf; + Py_ssize_t len; + if (PyString_AsStringAndSize($input, &buf, &len) == -1) + return NULL; + $1 = std::string(buf, len); + } -%typemap(in) const std::string & (std::string temp) { -char * buf; -Py_ssize_t len; -if (PyString_AsStringAndSize($input, &buf, &len) == -1) -return NULL; -temp = std::string(buf, len); -$1 = &temp; -} + %typemap(in) const std::string & (std::string temp) { + char * buf; + Py_ssize_t len; + if (PyString_AsStringAndSize($input, &buf, &len) == -1) + return NULL; + temp = std::string(buf, len); + $1 = &temp; + } -%typemap(out) std::string { -$result = PyString_FromStringAndSize($1.data(), $1.size()); -} + %typemap(out) std::string { + $result = PyString_FromStringAndSize($1.data(), $1.size()); + } -%typemap(out) const std::string & { -$result = PyString_FromStringAndSize($1->data(), $1->size()); -} + %typemap(out) const std::string & { + $result = PyString_FromStringAndSize($1->data(), $1->size()); + } -%typemap(in, numinputs = 0) std::string * OUTPUT (std::string temp) { -temp = std::string(); -$1 = &temp; -} + %typemap(in, numinputs = 0) std::string * OUTPUT (std::string temp) { + temp = std::string(); + $1 = &temp; + } -%typemap(argout, fragment = "t_output_helper") std::string * OUTPUT { -$result = t_output_helper( -$result, -PyString_FromStringAndSize($1->data(), $1->length())); -} + %typemap(argout, fragment = "t_output_helper") std::string * OUTPUT { + $result = t_output_helper( + $result, + PyString_FromStringAndSize($1->data(), $1->length())); + } + + %typemap(varout) std::string { + $result = PyString_FromStringAndSize($1.data(), $1.size()); + } -%typemap(varout) std::string { -$result = PyString_FromStringAndSize($1.data(), $1.size()); } %apply const std::string & {std::string &}; @@ -126,9 +129,9 @@ class std::string; // Swig2 no longer protects char* from being NULL, so we must use explicit check // like %apply Pointer NONNULL {const char *}; %typemap(check) Pointer NONNULL { -if ($1 == NULL) { -SWIG_exception(SWIG_TypeError, "'$1_name' must not be None"); -} + if ($1 == NULL) { + SWIG_exception(SWIG_TypeError, "'$1_name' must not be None"); + } } // We no longer provide typemaps for std:: namespace. @@ -138,43 +141,43 @@ SWIG_exception(SWIG_TypeError, "'$1_name' must not be None"); %typemap(typecheck) const std::string & = char *; %typemap(in) std::string { -char * buf; -Py_ssize_t len; -if (PyString_AsStringAndSize($input, &buf, &len) == -1) -return NULL; -$1 = std::string(buf, len); + char * buf; + Py_ssize_t len; + if (PyString_AsStringAndSize($input, &buf, &len) == -1) + return NULL; + $1 = std::string(buf, len); } %typemap(in) const std::string & (std::string temp) { -char * buf; -Py_ssize_t len; -if (PyString_AsStringAndSize($input, &buf, &len) == -1) -return NULL; -temp = std::string(buf, len); -$1 = &temp; + char * buf; + Py_ssize_t len; + if (PyString_AsStringAndSize($input, &buf, &len) == -1) + return NULL; + temp = std::string(buf, len); + $1 = &temp; } %typemap(out) std::string { -$result = PyString_FromStringAndSize($1.data(), $1.size()); + $result = PyString_FromStringAndSize($1.data(), $1.size()); } %typemap(out) const std::string & { -$result = PyString_FromStringAndSize($1->data(), $1->size()); + $result = PyString_FromStringAndSize($1->data(), $1->size()); } %typemap(in, numinputs = 0) std::string * OUTPUT (std::string temp) { -temp = std::string(); -$1 = &temp; + temp = std::string(); + $1 = &temp; } %typemap(argout, fragment = "t_output_helper") std::string * OUTPUT { -$result = t_output_helper( -$result, -PyString_FromStringAndSize($1->data(), $1->length())); + $result = t_output_helper( + $result, + PyString_FromStringAndSize($1->data(), $1->length())); } %typemap(varout) std::string { -$result = PyString_FromStringAndSize($1.data(), $1.size()); + $result = PyString_FromStringAndSize($1.data(), $1.size()); } %apply const std::string & {std::string &}; @@ -182,18 +185,18 @@ $result = PyString_FromStringAndSize($1.data(), $1.size()); // Support for those popular buffer-pointer/length input pairs %typemap(in) (void *INPUT, unsigned int LENGTH) (Py_ssize_t len) { -if (PyObject_AsReadBuffer($input, (const void**) &$1, &len) != 0) -return NULL; -if (((Py_ssize_t)($2_type)len) != len) { -SWIG_exception(SWIG_ValueError, "input data too large"); -} -$2 = ($2_type)len; + if (PyObject_AsReadBuffer($input, (const void**) &$1, &len) != 0) + return NULL; + if (((Py_ssize_t)($2_type)len) != len) { + SWIG_exception(SWIG_ValueError, "input data too large"); + } + $2 = ($2_type)len; } %typemap(in) (void *INPUT, uint64 LENGTH) (Py_ssize_t len) { -if (PyObject_AsReadBuffer($input, (const void**) &$1, &len) != 0) -return NULL; -$2 = len; + if (PyObject_AsReadBuffer($input, (const void**) &$1, &len) != 0) + return NULL; + $2 = len; } // char ** @@ -201,9 +204,9 @@ $2 = len; %typemap(in, numinputs=0) char ** OUTPUT { } %typemap(argout, fragment="t_output_helper") char ** OUTPUT { -char* tmpstr = NULL; -if ($1 != NULL) tmpstr = *$1; -$result = t_output_helper($result, PyString_FromString(tmpstr)); + char* tmpstr = NULL; + if ($1 != NULL) tmpstr = *$1; + $result = t_output_helper($result, PyString_FromString(tmpstr)); } @@ -217,36 +220,36 @@ $result = t_output_helper($result, PyString_FromString(tmpstr)); %define LIST_OUTPUT_TYPEMAP(type, py_converter) %typemap(in) std::vector(std::vector temp) { -if (!vector_input_helper($input, &temp, PyObjAs)) { -if (!PyErr_Occurred()) -SWIG_Error(SWIG_TypeError, "sequence(type) expected"); -return NULL; -} -$1 = temp; + if (!vector_input_helper($input, &temp, PyObjAs)) { + if (!PyErr_Occurred()) + SWIG_Error(SWIG_TypeError, "sequence(type) expected"); + return NULL; + } + $1 = temp; } %typemap(in) const std::vector& (std::vector temp), -const std::vector* (std::vector temp) { -if (!vector_input_helper($input, &temp, PyObjAs)) { -if (!PyErr_Occurred()) -SWIG_Error(SWIG_TypeError, "sequence(type) expected"); -return NULL; -} -$1 = &temp; + const std::vector* (std::vector temp) { + if (!vector_input_helper($input, &temp, PyObjAs)) { + if (!PyErr_Occurred()) + SWIG_Error(SWIG_TypeError, "sequence(type) expected"); + return NULL; + } + $1 = &temp; } %typemap(in,numinputs=0) -std::vector* OUTPUT (std::vector temp), -hash_set* OUTPUT (hash_set temp), -std::set* OUTPUT (std::set temp) { -$1 = &temp; + std::vector* OUTPUT (std::vector temp), + hash_set* OUTPUT (hash_set temp), + std::set* OUTPUT (std::set temp) { + $1 = &temp; } %typemap(argout) std::vector* OUTPUT, std::set* OUTPUT, hash_set* OUTPUT { -%append_output(list_output_helper($1, &py_converter)); + %append_output(list_output_helper($1, &py_converter)); } %typemap(out) std::vector { -$result = vector_output_helper(&$1, &py_converter); + $result = vector_output_helper(&$1, &py_converter); } %typemap(out) std::vector*, const std::vector& { -$result = vector_output_helper($1, &py_converter); + $result = vector_output_helper($1, &py_converter); } %enddef @@ -309,34 +312,34 @@ COPY_TYPEMAPS(uint64, Fprint); #undef COPY_TYPEMAPS %apply (void * INPUT, unsigned int LENGTH) -{ (void * INPUT, uint32 LENGTH) } + { (void * INPUT, uint32 LENGTH) } %apply (void * INPUT, uint64 LENGTH) -{ (void * INPUT, size_t LENGTH) }; + { (void * INPUT, size_t LENGTH) }; %apply (void * INPUT, unsigned int LENGTH) -{ (const void * INPUT, unsigned int LENGTH) }; + { (const void * INPUT, unsigned int LENGTH) }; %apply (void * INPUT, unsigned int LENGTH) -{ (const void * INPUT, uint32 LENGTH) }; + { (const void * INPUT, uint32 LENGTH) }; %apply (void * INPUT, uint64 LENGTH) -{ (const void * INPUT, size_t LENGTH) }; + { (const void * INPUT, size_t LENGTH) }; %apply (void * INPUT, unsigned int LENGTH) -{ (const char * INPUT, unsigned int LENGTH) }; + { (const char * INPUT, unsigned int LENGTH) }; %apply (void * INPUT, unsigned int LENGTH) -{ (const char * INPUT, uint32 LENGTH) }; + { (const char * INPUT, uint32 LENGTH) }; %apply (void * INPUT, uint64 LENGTH) -{ (const char * INPUT, size_t LENGTH) }; + { (const char * INPUT, size_t LENGTH) }; // We accept either python ints or longs for uint64 arguments. %typemap(in) uint64 { -if (PyInt_Check($input)) { -$1 = static_cast(PyInt_AsLong($input)); -} else if (PyLong_Check($input)) { -$1 = static_cast(PyLong_AsUnsignedLongLong($input)); -} else { -SWIG_exception(SWIG_TypeError, -"int or long value expected for argument \"$1_name\"") -} + if (PyInt_Check($input)) { + $1 = static_cast(PyInt_AsLong($input)); + } else if (PyLong_Check($input)) { + $1 = static_cast(PyLong_AsUnsignedLongLong($input)); + } else { + SWIG_exception(SWIG_TypeError, + "int or long value expected for argument \"$1_name\"") + } } // When a method returns a pointer or reference to a subobject of the @@ -345,11 +348,11 @@ SWIG_exception(SWIG_TypeError, // the parent object alive, which indirectly keeps the subobject alive. %define SWIG_RETURN_POINTER_TO_SUBOBJECT(cpp_method, py_method) %feature("shadow") cpp_method %{ -def py_method(*args): -result = $action(*args) -if result is not None: -result.keepalive = args[0] -return result + def py_method(*args): + result = $action(*args) + if result is not None: + result.keepalive = args[0] + return result %} %enddef @@ -385,23 +388,23 @@ return result %typemap(in) std::string %{ if(!$input) { -SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::string"); -return $null; -} -const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); -if (!$1_pstr) return $null; -$1.assign($1_pstr); -jenv->ReleaseStringUTFChars($input, $1_pstr); %} + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::string"); + return $null; + } + const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); + if (!$1_pstr) return $null; + $1.assign($1_pstr); + jenv->ReleaseStringUTFChars($input, $1_pstr); %} %typemap(directorout) std::string %{ if(!$input) { -SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::string"); -return $null; -} -const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); -if (!$1_pstr) return $null; -$result.assign($1_pstr); -jenv->ReleaseStringUTFChars($input, $1_pstr); %} + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::string"); + return $null; + } + const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); + if (!$1_pstr) return $null; + $result.assign($1_pstr); + jenv->ReleaseStringUTFChars($input, $1_pstr); %} %typemap(directorin,descriptor="Ljava/lang/String;") std::string %{ $input = jenv->NewStringUTF($1.c_str()); %} @@ -412,14 +415,14 @@ jenv->ReleaseStringUTFChars($input, $1_pstr); %} %typemap(javain) std::string "$javainput" %typemap(javaout) std::string { -return $jnicall; -} + return $jnicall; + } %typemap(typecheck) std::string = char *; %typemap(throws) std::string %{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.c_str()); -return $null; %} + return $null; %} // const std::string & %typemap(jni) const std::string & "jstring" @@ -430,27 +433,27 @@ return $null; %} %typemap(in) const std::string & %{ if(!$input) { -SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::string"); -return $null; -} -const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); -if (!$1_pstr) return $null; -std::string $1_str($1_pstr); -$1 = &$1_str; -jenv->ReleaseStringUTFChars($input, $1_pstr); %} + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::string"); + return $null; + } + const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); + if (!$1_pstr) return $null; + std::string $1_str($1_pstr); + $1 = &$1_str; + jenv->ReleaseStringUTFChars($input, $1_pstr); %} %typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const std::string & %{ if(!$input) { -SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::string"); -return $null; -} -const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); -if (!$1_pstr) return $null; -/* possible thread - reentrant code problem */ -static std::string $1_str; -$1_str = $1_pstr; -$result = &$1_str; -jenv->ReleaseStringUTFChars($input, $1_pstr); %} + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::string"); + return $null; + } + const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); + if (!$1_pstr) return $null; + /* possible thread - reentrant code problem */ + static std::string $1_str; + $1_str = $1_pstr; + $result = &$1_str; + jenv->ReleaseStringUTFChars($input, $1_pstr); %} %typemap(directorin,descriptor="Ljava/lang/String;") const std::string & %{ $input = jenv->NewStringUTF($1.c_str()); %} @@ -461,14 +464,14 @@ jenv->ReleaseStringUTFChars($input, $1_pstr); %} %typemap(javain) const std::string & "$javainput" %typemap(javaout) const std::string & { -return $jnicall; -} + return $jnicall; + } %typemap(typecheck) const std::string & = char *; %typemap(throws) const std::string & %{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.c_str()); -return $null; + return $null; %} %define COPY_TYPEMAPS(oldtype, newtype) diff --git a/src/constraint_solver/element.cc b/src/constraint_solver/element.cc index 22782d94fa..3a44837c7a 100644 --- a/src/constraint_solver/element.cc +++ b/src/constraint_solver/element.cc @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. + #include #include "base/unique_ptr.h" #include @@ -260,8 +261,7 @@ IntVar* BuildDomainIntVar(Solver* const solver, std::vector* values); class IntExprElement : public BaseIntExprElement { public: - IntExprElement(Solver* const s, const std::vector& vals, - IntVar* const expr) + IntExprElement(Solver* const s, const std::vector& vals, IntVar* const expr) : BaseIntExprElement(s, expr), values_(vals) {} virtual ~IntExprElement() {} @@ -369,8 +369,9 @@ class IncreasingIntExprElement : public BaseIntExpr { IntVar* const index_; }; -IncreasingIntExprElement::IncreasingIntExprElement( - Solver* const s, const std::vector& values, IntVar* const index) +IncreasingIntExprElement::IncreasingIntExprElement(Solver* const s, + const std::vector& values, + IntVar* const index) : BaseIntExpr(s), values_(values), index_(index) { DCHECK(index); DCHECK(s); @@ -517,8 +518,7 @@ IntExpr* BuildElement(Solver* const solver, const std::vector& values, } } // namespace -IntExpr* Solver::MakeElement(const std::vector& values, - IntVar* const index) { +IntExpr* Solver::MakeElement(const std::vector& values, IntVar* const index) { DCHECK(index); DCHECK_EQ(this, index->solver()); if (index->Bound()) { @@ -527,8 +527,7 @@ IntExpr* Solver::MakeElement(const std::vector& values, return BuildElement(this, values, index); } -IntExpr* Solver::MakeElement(const std::vector& values, - IntVar* const index) { +IntExpr* Solver::MakeElement(const std::vector& values, IntVar* const index) { DCHECK(index); DCHECK_EQ(this, index->solver()); if (index->Bound()) { @@ -1505,16 +1504,14 @@ Constraint* Solver::MakeIndexOfConstraint(const std::vector& vars, } } -IntExpr* Solver::MakeIndexExpression(const std::vector& vars, - int64 value) { +IntExpr* Solver::MakeIndexExpression(const std::vector& vars, int64 value) { IntExpr* const cache = model_cache_->FindVarArrayConstantExpression( vars, value, ModelCache::VAR_ARRAY_CONSTANT_INDEX); if (cache != nullptr) { return cache->Var(); } else { - const std::string name = - StringPrintf("Index(%s, %" GG_LL_FORMAT "d)", - JoinNamePtr(vars, ", ").c_str(), value); + const std::string name = StringPrintf("Index(%s, %" GG_LL_FORMAT "d)", + JoinNamePtr(vars, ", ").c_str(), value); IntVar* const index = MakeIntVar(0, vars.size() - 1, name); AddConstraint(MakeIndexOfConstraint(vars, index, value)); model_cache_->InsertVarArrayConstantExpression( diff --git a/src/constraint_solver/expr_array.cc b/src/constraint_solver/expr_array.cc index c802f563a1..3d07e5ae7f 100644 --- a/src/constraint_solver/expr_array.cc +++ b/src/constraint_solver/expr_array.cc @@ -288,21 +288,27 @@ class SumConstraint : public TreeArrayConstraint { Demon* sum_demon_; }; -// This constraint implements sum(vars) == sum_var. +// This constraint implements sum(vars) == target_var. class SmallSumConstraint : public Constraint { public: SmallSumConstraint(Solver* const solver, const std::vector& vars, IntVar* const target_var) - : Constraint(solver), vars_(vars), target_var_(target_var), - computed_min_(0), computed_max_(0), sum_demon_(nullptr) {} + : Constraint(solver), + vars_(vars), + target_var_(target_var), + computed_min_(0), + computed_max_(0), + sum_demon_(nullptr) {} virtual ~SmallSumConstraint() {} virtual void Post() { for (int i = 0; i < vars_.size(); ++i) { - Demon* const demon = MakeConstraintDemon1( - solver(), this, &SmallSumConstraint::VarChanged, "VarChanged", i); - vars_[i]->WhenRange(demon); + if (!vars_[i]->Bound()) { + Demon* const demon = MakeConstraintDemon1( + solver(), this, &SmallSumConstraint::VarChanged, "VarChanged", i); + vars_[i]->WhenRange(demon); + } } sum_demon_ = solver()->RegisterDemon(MakeDelayedConstraintDemon0( solver(), this, &SmallSumConstraint::SumChanged, "SumChanged")); @@ -775,16 +781,21 @@ class SmallMinConstraint : public Constraint { public: SmallMinConstraint(Solver* const solver, const std::vector& vars, IntVar* const target_var) - : Constraint(solver), vars_(vars), target_var_(target_var), - computed_min_(0), computed_max_(0) {} + : Constraint(solver), + vars_(vars), + target_var_(target_var), + computed_min_(0), + computed_max_(0) {} virtual ~SmallMinConstraint() {} virtual void Post() { for (int i = 0; i < vars_.size(); ++i) { - Demon* const demon = MakeConstraintDemon1( - solver(), this, &SmallMinConstraint::VarChanged, "VarChanged", i); - vars_[i]->WhenRange(demon); + if (!vars_[i]->Bound()) { + Demon* const demon = MakeConstraintDemon1( + solver(), this, &SmallMinConstraint::VarChanged, "VarChanged", i); + vars_[i]->WhenRange(demon); + } } Demon* const mdemon = solver()->RegisterDemon(MakeDelayedConstraintDemon0( solver(), this, &SmallMinConstraint::MinVarChanged, "MinVarChanged")); @@ -837,8 +848,7 @@ class SmallMinConstraint : public Constraint { min_min = std::min(min_min, var->Min()); min_max = std::min(min_max, var->Max()); } - if (min_min > computed_min_.Value() || - min_max < computed_max_.Value()) { + if (min_min > computed_min_.Value() || min_max < computed_max_.Value()) { computed_min_.SetValue(solver(), min_min); computed_max_.SetValue(solver(), min_max); target_var_->SetRange(computed_min_.Value(), computed_max_.Value()); @@ -851,8 +861,7 @@ class SmallMinConstraint : public Constraint { const int64 new_min = target_var_->Min(); const int64 new_max = target_var_->Max(); // Nothing to do? - if (new_min <= computed_min_.Value() && - new_max >= computed_max_.Value()) { + if (new_min <= computed_min_.Value() && new_max >= computed_max_.Value()) { return; } @@ -1050,16 +1059,21 @@ class SmallMaxConstraint : public Constraint { public: SmallMaxConstraint(Solver* const solver, const std::vector& vars, IntVar* const target_var) - : Constraint(solver), vars_(vars), target_var_(target_var), - computed_min_(0), computed_max_(0) {} + : Constraint(solver), + vars_(vars), + target_var_(target_var), + computed_min_(0), + computed_max_(0) {} virtual ~SmallMaxConstraint() {} virtual void Post() { for (int i = 0; i < vars_.size(); ++i) { - Demon* const demon = MakeConstraintDemon1( - solver(), this, &SmallMaxConstraint::VarChanged, "VarChanged", i); - vars_[i]->WhenRange(demon); + if (!vars_[i]->Bound()) { + Demon* const demon = MakeConstraintDemon1( + solver(), this, &SmallMaxConstraint::VarChanged, "VarChanged", i); + vars_[i]->WhenRange(demon); + } } Demon* const mdemon = solver()->RegisterDemon(MakeDelayedConstraintDemon0( solver(), this, &SmallMaxConstraint::MaxVarChanged, "MinVarChanged")); @@ -1112,8 +1126,7 @@ class SmallMaxConstraint : public Constraint { max_min = std::max(max_min, var->Min()); max_max = std::max(max_max, var->Max()); } - if (max_min > computed_min_.Value() || - max_max < computed_max_.Value()) { + if (max_min > computed_min_.Value() || max_max < computed_max_.Value()) { computed_min_.SetValue(solver(), max_min); computed_max_.SetValue(solver(), max_max); target_var_->SetRange(computed_min_.Value(), computed_max_.Value()); @@ -1126,8 +1139,7 @@ class SmallMaxConstraint : public Constraint { const int64 new_min = target_var_->Min(); const int64 new_max = target_var_->Max(); // Nothing to do? - if (new_min <= computed_min_.Value() && - new_max >= computed_max_.Value()) { + if (new_min <= computed_min_.Value() && new_max >= computed_max_.Value()) { return; } @@ -3413,7 +3425,7 @@ Constraint* Solver::MakeSumEquality(const std::vector& vars, return MakeEquality(vars[0], var); } else if (size == 2) { return MakeEquality(MakeSum(vars[0], vars[1]), var); - } else { + } else { if (DetectSumOverflow(vars)) { return RevAlloc(new SafeSumConstraint(this, vars, var)); } else if (size <= parameters_.array_split_size) { diff --git a/src/graph/hamiltonian_path.h b/src/graph/hamiltonian_path.h index aa198036f1..9f00399aae 100644 --- a/src/graph/hamiltonian_path.h +++ b/src/graph/hamiltonian_path.h @@ -91,15 +91,14 @@ namespace operations_research { typedef int PathNodeIndex; -template -class HamiltonianPathSolver { +template class HamiltonianPathSolver { // HamiltonianPathSolver computes a minimum Hamiltonian path over a graph // defined by a cost matrix. The cost matrix need not be symmetric. // The Hamiltonian path can be closed, in this case it's a Hamiltonian cycle, // i.e. the algorithm solves the Travelling Salesman Problem. // Example: - // std::vector > cost_mat; + // std::vector> cost_mat; // ... fill in cost matrix // HamiltonianPathSolver mhp(cost_mat); // no computation done // printf("%d\n", mhp.TravelingSalesmanCost()); // computation done and @@ -114,20 +113,20 @@ class HamiltonianPathSolver { // This is why we define the type NodeSet to be 32-bit wide. typedef uint32 NodeSet; - explicit HamiltonianPathSolver(const std::vector >& cost); + explicit HamiltonianPathSolver(const std::vector>& cost); ~HamiltonianPathSolver(); // Replaces the cost matrix while avoiding re-allocating memory. - void ChangeCostMatrix(const std::vector >& cost); + void ChangeCostMatrix(const std::vector>& cost); // Returns the Hamiltonian path cost. - T HamiltonianCost(); + CostType HamiltonianCost(); // Returns the Hamiltonian path in the vector pointed to by the argument. void HamiltonianPath(std::vector* path); // Returns the cost of the TSP tour. - T TravelingSalesmanCost(); + CostType TravelingSalesmanCost(); // Returns the TSP tour in the vector pointed to by the argument. void TravelingSalesmanPath(std::vector* path); @@ -150,10 +149,10 @@ class HamiltonianPathSolver { void ComputeShortestPath(NodeSet s, PathNodeIndex dest); // Copies the cost matrix passed as argument to the internal data structure. - void CopyCostMatrix(const std::vector >& cost); + void CopyCostMatrix(const std::vector>& cost); // Reserves memory. Used in constructor and ChangeCostMatrix. - void Init(const std::vector >& cost); + void Init(const std::vector>& cost); // Frees memory. Used in destructor and ChangeCostMatrix. void Free(); @@ -170,15 +169,16 @@ class HamiltonianPathSolver { bool triangle_inequality_checked_; bool solved_; PathNodeIndex num_nodes_; - T** cost_; + CostType **cost_; NodeSet two_power_num_nodes_; - T** memory_; + CostType **memory_; }; static const int kHamiltonianPathSolverPadValue = 1557; -template -HamiltonianPathSolver::HamiltonianPathSolver(const std::vector >& cost) +template +HamiltonianPathSolver::HamiltonianPathSolver( + const std::vector>& cost) : robust_(true), triangle_inequality_ok_(true), robustness_checked_(false), @@ -191,13 +191,12 @@ HamiltonianPathSolver::HamiltonianPathSolver(const std::vector Init(cost); } -template -HamiltonianPathSolver::~HamiltonianPathSolver() { +template +HamiltonianPathSolver::~HamiltonianPathSolver() { Free(); } -template -void HamiltonianPathSolver::Free() { +template void HamiltonianPathSolver::Free() { if (num_nodes_ > 0) { delete[] memory_[0]; delete[] memory_; @@ -208,9 +207,9 @@ void HamiltonianPathSolver::Free() { } } -template -void HamiltonianPathSolver::ChangeCostMatrix( - const std::vector >& cost) { +template +void HamiltonianPathSolver::ChangeCostMatrix( + const std::vector>& cost) { robustness_checked_ = false; triangle_inequality_checked_ = false; solved_ = false; @@ -222,8 +221,9 @@ void HamiltonianPathSolver::ChangeCostMatrix( } } -template -void HamiltonianPathSolver::CopyCostMatrix(const std::vector >& cost) { +template +void HamiltonianPathSolver::CopyCostMatrix( + const std::vector>& cost) { for (int i = 0; i < num_nodes_; ++i) { CHECK_EQ(num_nodes_, cost[i].size()) << "Cost matrix must be square"; for (int j = 0; j < num_nodes_; ++j) { @@ -232,26 +232,25 @@ void HamiltonianPathSolver::CopyCostMatrix(const std::vector > } } -template -bool HamiltonianPathSolver::IsRobust() { +template bool HamiltonianPathSolver::IsRobust() { if (!robustness_checked_) { CheckRobustness(); } return robust_; } -template -bool HamiltonianPathSolver::VerifiesTriangleInequality() { +template +bool HamiltonianPathSolver::VerifiesTriangleInequality() { if (!triangle_inequality_checked_) { CheckTriangleInequality(); } return triangle_inequality_ok_; } -template -void HamiltonianPathSolver::CheckRobustness() { - T min_cost = std::numeric_limits::max(); - T max_cost = std::numeric_limits::min(); +template +void HamiltonianPathSolver::CheckRobustness() { + CostType min_cost = std::numeric_limits::max(); + CostType max_cost = std::numeric_limits::min(); // We compute the min and max for the cost matrix. for (int i = 0; i < num_nodes_; ++i) { @@ -266,20 +265,20 @@ void HamiltonianPathSolver::CheckRobustness() { if (min_cost < 0) { robust_ = false; } else { - robust_ = - (min_cost > num_nodes_ * max_cost * std::numeric_limits::epsilon()); + robust_ = (min_cost > num_nodes_ * max_cost * + std::numeric_limits::epsilon()); } robustness_checked_ = true; } -template -void HamiltonianPathSolver::CheckTriangleInequality() { +template +void HamiltonianPathSolver::CheckTriangleInequality() { triangle_inequality_ok_ = true; triangle_inequality_checked_ = true; for (int k = 0; k < num_nodes_; ++k) { for (int i = 0; i < num_nodes_; ++i) { for (int j = 0; j < num_nodes_; ++j) { - T detour_cost = cost_[i][k] + cost_[k][j]; + CostType detour_cost = cost_[i][k] + cost_[k][j]; if (detour_cost < cost_[i][j]) { triangle_inequality_ok_ = false; return; @@ -289,13 +288,14 @@ void HamiltonianPathSolver::CheckTriangleInequality() { } } -template -void HamiltonianPathSolver::Init(const std::vector >& cost) { +template +void HamiltonianPathSolver::Init( + const std::vector>& cost) { num_nodes_ = cost.size(); if (num_nodes_ > 0) { - cost_ = new T* [num_nodes_]; + cost_ = new CostType* [num_nodes_]; for (int i = 0; i < num_nodes_; ++i) { - cost_[i] = new T[num_nodes_]; + cost_[i] = new CostType[num_nodes_]; } CopyCostMatrix(cost); @@ -312,17 +312,17 @@ void HamiltonianPathSolver::Init(const std::vector >& cost) { const int padded_size = two_power_num_nodes_ + kHamiltonianPathSolverPadValue; - memory_ = new T* [num_nodes_]; - memory_[0] = new T[num_nodes_ * padded_size]; + memory_ = new CostType* [num_nodes_]; + memory_[0] = new CostType[num_nodes_ * padded_size]; for (int i = 1; i < num_nodes_; ++i) { memory_[i] = memory_[i - 1] + padded_size; } } } -template -void HamiltonianPathSolver::ComputeShortestPath(NodeSet subset, - PathNodeIndex dest) { +template +void HamiltonianPathSolver::ComputeShortestPath(NodeSet subset, + PathNodeIndex dest) { // We iterate on the set bits in the NodeSet subset, instead of checking // which bits are set as in the loop: // for (int src = 0; src < num_nodes_; ++src) { @@ -334,13 +334,13 @@ void HamiltonianPathSolver::ComputeShortestPath(NodeSet subset, const PathNodeIndex first_src = LeastSignificantBitPosition32(first_singleton); NodeSet start_subset = subset - first_singleton; - T min_cost = memory_[first_src][start_subset] + cost_[first_src][dest]; + CostType min_cost = memory_[first_src][start_subset] + cost_[first_src][dest]; NodeSet copy = start_subset; while (copy != 0) { const NodeSet singleton = LeastSignificantBitWord32(copy); const PathNodeIndex src = LeastSignificantBitPosition32(singleton); const NodeSet new_subset = subset - singleton; - const T cost = memory_[src][new_subset] + cost_[src][dest]; + const CostType cost = memory_[src][new_subset] + cost_[src][dest]; if (cost < min_cost) { min_cost = cost; } @@ -349,8 +349,7 @@ void HamiltonianPathSolver::ComputeShortestPath(NodeSet subset, memory_[dest][subset] = min_cost; } -template -void HamiltonianPathSolver::Solve() { +template void HamiltonianPathSolver::Solve() { if (solved_) return; for (PathNodeIndex dest = 0; dest < num_nodes_; ++dest) { memory_[dest][0] = cost_[0][dest]; @@ -363,8 +362,8 @@ void HamiltonianPathSolver::Solve() { solved_ = true; } -template -T HamiltonianPathSolver::HamiltonianCost() { +template +CostType HamiltonianPathSolver::HamiltonianCost() { if (num_nodes_ <= 1) { return 0; } @@ -372,8 +371,9 @@ T HamiltonianPathSolver::HamiltonianCost() { return memory_[num_nodes_ - 1][two_power_num_nodes_ - 1]; } -template -void HamiltonianPathSolver::HamiltonianPath(std::vector* path) { +template +void HamiltonianPathSolver::HamiltonianPath( + std::vector* path) { if (num_nodes_ <= 1) { path->resize(1); (*path)[0] = 0; @@ -412,9 +412,9 @@ void HamiltonianPathSolver::HamiltonianPath(std::vector* path) // that there are also less cache misses, there is a factor 2.5x in speed // when using this trick. -template -void HamiltonianPathSolver::Path(PathNodeIndex end, - std::vector* path) { +template +void HamiltonianPathSolver::Path(PathNodeIndex end, + std::vector* path) { PathNodeIndex dest = end; NodeSet current_set = two_power_num_nodes_ - 1; // It may happen that node 0 be on a segment (node i, node j), in which case @@ -431,10 +431,10 @@ void HamiltonianPathSolver::Path(PathNodeIndex end, const double current_cost = memory_[dest][current_set]; const double incumbent_cost = memory_[src][incumbent_set] + cost_[src][dest]; - // We take precision into account in case T is float or double. - // There is no visible penalty in the case T is an integer type. + // We take precision into account in case CostType is float or double. + // There is no visible penalty in the case CostType is an integer type. if (fabs(current_cost - incumbent_cost) <= - std::numeric_limits::epsilon() * current_cost) { + std::numeric_limits::epsilon() * current_cost) { current_set = incumbent_set; dest = src; (*path)[i] = dest; @@ -446,8 +446,8 @@ void HamiltonianPathSolver::Path(PathNodeIndex end, } } -template -T HamiltonianPathSolver::TravelingSalesmanCost() { +template +CostType HamiltonianPathSolver::TravelingSalesmanCost() { if (num_nodes_ <= 1) { return 0; } @@ -455,8 +455,8 @@ T HamiltonianPathSolver::TravelingSalesmanCost() { return memory_[0][two_power_num_nodes_ - 1]; } -template -void HamiltonianPathSolver::TravelingSalesmanPath( +template +void HamiltonianPathSolver::TravelingSalesmanPath( std::vector* path) { if (num_nodes_ <= 1) { path->resize(1);