minor sync with internal code
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
# define ARCH_K8
|
||||
#elif defined(__APPLE__) && defined(__GNUC__)
|
||||
# define ARCH_K8 // We only support 64 bit on Mac OS X.
|
||||
#elif defined(__GNUC__) && defined(__LP64__) // Linux
|
||||
#elif defined(__GNUC__) && defined(__LP64__) // Linux
|
||||
# define ARCH_K8
|
||||
#endif
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ void StrAppend(std::string* s, const AlphaNum& a, const AlphaNum& b,
|
||||
StrAppend(s, a, b, c, d);
|
||||
StrAppend(s, e, f, g, h, i, j, k);
|
||||
}
|
||||
|
||||
void StrAppend(std::string* s, const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
|
||||
const AlphaNum& f, const AlphaNum& g, const AlphaNum& h,
|
||||
@@ -169,3 +170,22 @@ std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
|
||||
StrAppend(&out, a, b, c, d, e, f, g, h, i, j, k);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
|
||||
const AlphaNum& d, const AlphaNum& e, const AlphaNum& f,
|
||||
const AlphaNum& g, const AlphaNum& h, const AlphaNum& i,
|
||||
const AlphaNum& j, const AlphaNum& k, const AlphaNum& l) {
|
||||
std::string out;
|
||||
StrAppend(&out, a, b, c, d, e, f, g, h, i, j, k, l);
|
||||
return out;
|
||||
}
|
||||
std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
|
||||
const AlphaNum& d, const AlphaNum& e, const AlphaNum& f,
|
||||
const AlphaNum& g, const AlphaNum& h, const AlphaNum& i,
|
||||
const AlphaNum& j, const AlphaNum& k, const AlphaNum& l,
|
||||
const AlphaNum& m) {
|
||||
std::string out;
|
||||
StrAppend(&out, a, b, c, d, e, f, g, h, i, j, k, l, m);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,11 @@ struct AlphaNum {
|
||||
|
||||
extern AlphaNum gEmptyAlphaNum;
|
||||
|
||||
template <typename T>
|
||||
const T& LegacyPrecision(const T& t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
std::string StrCat(const AlphaNum& a);
|
||||
std::string StrCat(const AlphaNum& a, const AlphaNum& b);
|
||||
std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c);
|
||||
@@ -143,6 +148,16 @@ void StrAppend(std::string* s, const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
|
||||
const AlphaNum& f, const AlphaNum& g, const AlphaNum& h,
|
||||
const AlphaNum& i, const AlphaNum& j, const AlphaNum& k);
|
||||
void StrAppend(std::string* s, const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
|
||||
const AlphaNum& f, const AlphaNum& g, const AlphaNum& h,
|
||||
const AlphaNum& i, const AlphaNum& j, const AlphaNum& k,
|
||||
const AlphaNum& l);
|
||||
void StrAppend(std::string* s, const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d, const AlphaNum& e,
|
||||
const AlphaNum& f, const AlphaNum& g, const AlphaNum& h,
|
||||
const AlphaNum& i, const AlphaNum& j, const AlphaNum& k,
|
||||
const AlphaNum& l, const AlphaNum& m);
|
||||
|
||||
namespace strings {
|
||||
template <class Iterable>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "ortools/base/timer.h"
|
||||
#include "google/protobuf/text_format.h"
|
||||
#include "ortools/base/split.h"
|
||||
#include "ortools/base/stringpiece_utils.h"
|
||||
#include "ortools/base/join.h"
|
||||
|
||||
@@ -37,9 +37,9 @@ template <typename CostType, typename ArcIndex = int64,
|
||||
class ChristofidesPathSolver {
|
||||
public:
|
||||
enum class MatchingAlgorithm {
|
||||
#if defined(USE_CBC) || defined(USE_SCIP)
|
||||
#if defined(USE_CBC) || defined(USE_SCIP)
|
||||
MINIMUM_WEIGHT_MATCHING,
|
||||
#endif // defined(USE_CBC) || defined(USE_SCIP)
|
||||
#endif // defined(USE_CBC) || defined(USE_SCIP)
|
||||
MINIMAL_WEIGHT_MATCHING,
|
||||
};
|
||||
ChristofidesPathSolver(NodeIndex num_nodes, CostFunction costs);
|
||||
@@ -135,20 +135,18 @@ std::vector<typename GraphType::ArcIndex> ComputeMinimumWeightMatchingWithMIP(
|
||||
}
|
||||
}
|
||||
#if defined(USE_SCIP)
|
||||
MPSolver scip_solver("MatchingWithSCIP",
|
||||
MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING);
|
||||
MPSolver mp_solver("MatchingWithSCIP",
|
||||
MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING);
|
||||
#elif defined(USE_CBC)
|
||||
MPSolver scip_solver("MatchingWithCBC",
|
||||
MPSolver::CBC_MIXED_INTEGER_PROGRAMMING);
|
||||
MPSolver mp_solver("MatchingWithCBC",
|
||||
MPSolver::CBC_MIXED_INTEGER_PROGRAMMING);
|
||||
#endif
|
||||
// TODO(user): Glip performs significantly faster on very small problems;
|
||||
// investigate the necessity of switching solvers depending on model size.
|
||||
std::string error;
|
||||
scip_solver.LoadModelFromProto(model, &error);
|
||||
MPSolver::ResultStatus status = scip_solver.Solve();
|
||||
mp_solver.LoadModelFromProto(model, &error);
|
||||
MPSolver::ResultStatus status = mp_solver.Solve();
|
||||
CHECK_EQ(status, MPSolver::OPTIMAL);
|
||||
MPSolutionResponse response;
|
||||
scip_solver.FillSolutionResponseProto(&response);
|
||||
mp_solver.FillSolutionResponseProto(&response);
|
||||
std::vector<ArcIndex> matching;
|
||||
for (auto arc : variable_indices) {
|
||||
if (response.variable_value(arc.second) > .9) {
|
||||
@@ -227,7 +225,7 @@ void ChristofidesPathSolver<CostType, ArcIndex, NodeIndex,
|
||||
CompleteGraph<NodeIndex, ArcIndex> reduced_graph(reduced_size);
|
||||
std::vector<ArcIndex> closure_arcs;
|
||||
switch (matching_) {
|
||||
#if defined(USE_CBC) || defined(USE_SCIP)
|
||||
#if defined(USE_CBC) || defined(USE_SCIP)
|
||||
case MatchingAlgorithm::MINIMUM_WEIGHT_MATCHING: {
|
||||
closure_arcs = ComputeMinimumWeightMatchingWithMIP(
|
||||
reduced_graph, [this, &reduced_graph,
|
||||
@@ -237,7 +235,7 @@ void ChristofidesPathSolver<CostType, ArcIndex, NodeIndex,
|
||||
});
|
||||
break;
|
||||
}
|
||||
#endif // defined(USE_CBC) || defined(USE_SCIP)
|
||||
#endif // defined(USE_CBC) || defined(USE_SCIP)
|
||||
case MatchingAlgorithm::MINIMAL_WEIGHT_MATCHING: {
|
||||
// TODO(user): Cost caching was added and can gain up to 20% but
|
||||
// increases memory usage; see if we can avoid caching.
|
||||
|
||||
@@ -41,18 +41,20 @@ std::string FindErrorInMPVariable(const MPVariableProto& variable) {
|
||||
variable.lower_bound() == kInfinity ||
|
||||
variable.upper_bound() == -kInfinity ||
|
||||
variable.lower_bound() > variable.upper_bound()) {
|
||||
return StrCat("Infeasible bounds: [", variable.lower_bound(), ", ",
|
||||
variable.upper_bound(), "]");
|
||||
return StrCat("Infeasible bounds: [",
|
||||
LegacyPrecision(variable.lower_bound()), ", ",
|
||||
LegacyPrecision(variable.upper_bound()), "]");
|
||||
}
|
||||
if (variable.is_integer() &&
|
||||
ceil(variable.lower_bound()) > floor(variable.upper_bound())) {
|
||||
return StrCat("Infeasible bounds for integer variable: [",
|
||||
variable.lower_bound(), ", ", variable.upper_bound(), "]",
|
||||
LegacyPrecision(variable.lower_bound()), ", ",
|
||||
LegacyPrecision(variable.upper_bound()), "]",
|
||||
" translate to the empty set");
|
||||
}
|
||||
if (!std::isfinite(variable.objective_coefficient())) {
|
||||
return StrCat("Invalid objective_coefficient: ",
|
||||
variable.objective_coefficient());
|
||||
LegacyPrecision(variable.objective_coefficient()));
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
@@ -67,8 +69,9 @@ std::string FindErrorInMPConstraint(const MPConstraintProto& constraint,
|
||||
constraint.lower_bound() == kInfinity ||
|
||||
constraint.upper_bound() == -kInfinity ||
|
||||
constraint.lower_bound() > constraint.upper_bound()) {
|
||||
return StrCat("Infeasible bounds: [", constraint.lower_bound(), ", ",
|
||||
constraint.upper_bound(), "]");
|
||||
return StrCat("Infeasible bounds: [",
|
||||
LegacyPrecision(constraint.lower_bound()), ", ",
|
||||
LegacyPrecision(constraint.upper_bound()), "]");
|
||||
}
|
||||
|
||||
// TODO(user): clarify explicitly, at least in a comment, whether we want
|
||||
@@ -88,7 +91,8 @@ std::string FindErrorInMPConstraint(const MPConstraintProto& constraint,
|
||||
}
|
||||
const double coeff = constraint.coefficient(i);
|
||||
if (!std::isfinite(coeff)) {
|
||||
return StrCat("coefficient(", i, ")=", coeff, " is invalid");
|
||||
return StrCat("coefficient(", i, ")=", LegacyPrecision(coeff),
|
||||
" is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +133,8 @@ std::string FindErrorInSolutionHint(const PartialVariableAssignment& solution_hi
|
||||
}
|
||||
var_in_hint[var_index] = true;
|
||||
if (!std::isfinite(solution_hint.var_value(i))) {
|
||||
return StrCat("var_value(", i, ")=", solution_hint.var_value(i),
|
||||
return StrCat("var_value(", i,
|
||||
")=", LegacyPrecision(solution_hint.var_value(i)),
|
||||
" is not a finite number");
|
||||
}
|
||||
}
|
||||
@@ -146,7 +151,8 @@ std::string FindErrorInMPModelProto(const MPModelProto& model) {
|
||||
// accept models without variables and/or constraints.
|
||||
|
||||
if (!std::isfinite(model.objective_offset())) {
|
||||
return StrCat("Invalid objective_offset: ", model.objective_offset());
|
||||
return StrCat("Invalid objective_offset: ",
|
||||
LegacyPrecision(model.objective_offset()));
|
||||
}
|
||||
const int num_vars = model.variable_size();
|
||||
const int num_cts = model.constraint_size();
|
||||
@@ -230,9 +236,11 @@ std::string FindFeasibilityErrorInSolutionHint(const MPModelProto& model,
|
||||
if (!IsSmallerWithinTolerance(value, ub, tolerance) ||
|
||||
!IsSmallerWithinTolerance(lb, value, tolerance)) {
|
||||
return StrCat("Variable '", model.variable(var_index).name(),
|
||||
"' is set to ", value,
|
||||
" which is not in the variable bounds [", lb, ", ", ub,
|
||||
"] modulo a tolerance of ", tolerance, ".");
|
||||
"' is set to ", LegacyPrecision(value),
|
||||
" which is not in the variable bounds [",
|
||||
LegacyPrecision(lb), ", ", LegacyPrecision(ub),
|
||||
"] modulo a tolerance of ",
|
||||
LegacyPrecision(tolerance), ".");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,9 +257,11 @@ std::string FindFeasibilityErrorInSolutionHint(const MPModelProto& model,
|
||||
if (!IsSmallerWithinTolerance(activity.Value(), ub, tolerance) ||
|
||||
!IsSmallerWithinTolerance(lb, activity.Value(), tolerance)) {
|
||||
return StrCat("Constraint '", model.constraint(cst_index).name(),
|
||||
"' has activity ", activity.Value(),
|
||||
" which is not in the constraint bounds [", lb, ", ", ub,
|
||||
"] modulo a tolerance of ", tolerance, ".");
|
||||
"' has activity ", LegacyPrecision(activity.Value()),
|
||||
" which is not in the constraint bounds [",
|
||||
LegacyPrecision(lb), ", ", LegacyPrecision(ub),
|
||||
"] modulo a tolerance of ",
|
||||
LegacyPrecision(tolerance), ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -590,7 +590,8 @@ std::string LinearProgram::DumpSolution(const DenseRow& variable_values) const {
|
||||
std::string output;
|
||||
for (ColIndex col(0); col < variable_values.size(); ++col) {
|
||||
if (!output.empty()) StrAppend(&output, ", ");
|
||||
StrAppend(&output, GetVariableName(col), " = ", variable_values[col]);
|
||||
StrAppend(&output, GetVariableName(col), " = ",
|
||||
LegacyPrecision(variable_values[col]));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
// Proto describing a general Constraint Programming (CP) problem.
|
||||
|
||||
syntax = "proto3";
|
||||
option csharp_namespace = "Google.OrTools.Sat";
|
||||
|
||||
option csharp_namespace = "Google.OrTools.Sat";
|
||||
|
||||
package operations_research.sat;
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ int64 PiecewiseSegment::Value(int64 x) const {
|
||||
|
||||
int64 PiecewiseSegment::SafeValuePostReference(int64 x) const {
|
||||
DCHECK_GE(x, reference_x_);
|
||||
const uint64 span_x = x - reference_x_;
|
||||
const uint64 span_x = static_cast<uint64>(x) - reference_x_;
|
||||
if (span_x == 0) {
|
||||
return reference_y_;
|
||||
}
|
||||
@@ -173,7 +173,7 @@ int64 PiecewiseSegment::SafeValuePostReference(int64 x) const {
|
||||
|
||||
int64 PiecewiseSegment::SafeValuePreReference(int64 x) const {
|
||||
DCHECK_LE(x, reference_x_);
|
||||
const uint64 span_x = reference_x_ - x;
|
||||
const uint64 span_x = static_cast<uint64>(reference_x_) - x;
|
||||
if (slope_ == 0) {
|
||||
// Zero slope segment.
|
||||
return reference_y_;
|
||||
@@ -190,14 +190,14 @@ int64 PiecewiseSegment::SafeValuePreReference(int64 x) const {
|
||||
} else {
|
||||
return span_y - reference_y_ > static_cast<uint64>(kint64max) + 1
|
||||
? kint64min
|
||||
: -static_cast<int64>(span_y - reference_y_);
|
||||
: -static_cast<uint64>(span_y - reference_y_);
|
||||
}
|
||||
} else {
|
||||
const uint64 opp_reference_y = static_cast<uint64>(-reference_y_);
|
||||
const uint64 opp_unsigned_sum = UnsignedCapAdd(opp_reference_y, span_y);
|
||||
return opp_unsigned_sum > kint64max
|
||||
? kint64min
|
||||
: -static_cast<int64>(opp_unsigned_sum);
|
||||
: -static_cast<uint64>(opp_unsigned_sum);
|
||||
}
|
||||
} else {
|
||||
// Negative slope segment.
|
||||
@@ -213,7 +213,7 @@ int64 PiecewiseSegment::SafeValuePreReference(int64 x) const {
|
||||
} else {
|
||||
return opp_reference_y - span_y > static_cast<uint64>(kint64max) + 1
|
||||
? kint64min
|
||||
: -static_cast<int64>(opp_reference_y - span_y);
|
||||
: -static_cast<uint64>(opp_reference_y - span_y);
|
||||
}
|
||||
} else {
|
||||
const uint64 unsigned_sum = UnsignedCapAdd(reference_y_, span_y);
|
||||
|
||||
@@ -25,16 +25,19 @@ const double TimeLimit::kSafetyBufferSeconds = 1e-4;
|
||||
const int TimeLimit::kHistorySize = 100;
|
||||
|
||||
std::string TimeLimit::DebugString() const {
|
||||
std::string buffer = StrCat(
|
||||
"Time left: ", GetTimeLeft(),
|
||||
"\nDeterministic time left: ", GetDeterministicTimeLeft(),
|
||||
"\nElapsed time: ", GetElapsedTime(),
|
||||
"\nElapsed deterministic time: ", GetElapsedDeterministicTime());
|
||||
std::string buffer =
|
||||
StrCat("Time left: ", LegacyPrecision(GetTimeLeft()),
|
||||
"\nDeterministic time left: ",
|
||||
LegacyPrecision(GetDeterministicTimeLeft()),
|
||||
"\nElapsed time: ", LegacyPrecision(GetElapsedTime()),
|
||||
"\nElapsed deterministic time: ",
|
||||
LegacyPrecision(GetElapsedDeterministicTime()));
|
||||
#ifndef NDEBUG
|
||||
for (const auto& counter : deterministic_counters_) {
|
||||
const std::string& counter_name = counter.first;
|
||||
const double counter_value = counter.second;
|
||||
StrAppend(&buffer, "\n", counter_name, ": ", counter_value);
|
||||
StrAppend(&buffer, "\n", counter_name, ": ",
|
||||
LegacyPrecision(counter_value));
|
||||
}
|
||||
#endif
|
||||
return buffer;
|
||||
|
||||
Reference in New Issue
Block a user