minor sync with internal code

This commit is contained in:
Laurent Perron
2017-08-02 10:41:27 -07:00
parent 2fb2c6cd1b
commit 12234acc02
10 changed files with 90 additions and 42 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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"

View File

@@ -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.

View File

@@ -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), ".");
}
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;