update samples, fix SAT backend overflow in hints
This commit is contained in:
@@ -157,6 +157,8 @@
|
||||
#include "ortools/linear_solver/linear_solver_callback.h"
|
||||
#include "ortools/port/proto_utils.h"
|
||||
|
||||
ABSL_DECLARE_FLAG(bool, linear_solver_enable_verbose_output);
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
constexpr double kDefaultPrimalTolerance = 1e-07;
|
||||
|
||||
@@ -40,7 +40,7 @@ void BinPackingMip() {
|
||||
// [END program_part1]
|
||||
|
||||
// [START solver]
|
||||
// Create the mip solver with the CBC backend.
|
||||
// Create the mip solver with the SCIP backend.
|
||||
MPSolver solver("bin_packing_mip", MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING);
|
||||
// [END solver]
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# [START program]
|
||||
# [START import]
|
||||
from ortools.linear_solver import pywraplp
|
||||
|
||||
# [END import]
|
||||
|
||||
|
||||
@@ -30,7 +29,6 @@ def create_data_model():
|
||||
data['bin_capacity'] = 100
|
||||
return data
|
||||
|
||||
|
||||
# [END data_model]
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# [START program]
|
||||
# [START import]
|
||||
from ortools.linear_solver import pywraplp
|
||||
|
||||
# [END import]
|
||||
|
||||
|
||||
@@ -35,7 +34,6 @@ def create_data_model():
|
||||
data['num_constraints'] = 4
|
||||
return data
|
||||
|
||||
|
||||
# [END data_model]
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void MultipleKnapsackMip() {
|
||||
// [END program_part1]
|
||||
|
||||
// [START solver]
|
||||
// Create the mip solver with the CBC backend.
|
||||
// Create the mip solver with the SCIP backend.
|
||||
MPSolver solver("multiple_knapsack_mip",
|
||||
MPSolver::SCIP_MIXED_INTEGER_PROGRAMMING);
|
||||
// [END solver]
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# [START program]
|
||||
# [START import]
|
||||
from ortools.linear_solver import pywraplp
|
||||
|
||||
# [END import]
|
||||
|
||||
|
||||
@@ -34,7 +33,6 @@ def create_data_model():
|
||||
data['bin_capacities'] = [100, 100, 100, 100, 100]
|
||||
return data
|
||||
|
||||
|
||||
# [END data_model]
|
||||
|
||||
|
||||
|
||||
@@ -136,15 +136,8 @@ MPSolver::ResultStatus SatInterface::Solve(const MPSolverParameters& param) {
|
||||
|
||||
MPModelRequest request;
|
||||
solver_->ExportModelToProto(request.mutable_model());
|
||||
// If sat::SatParameters is compiled with proto-lite (go/mobile-cpp-protos),
|
||||
// then serialize as non-human readable string. This is because proto-lite
|
||||
// does not support reflection mechanism, which is a prerequisite for method
|
||||
// like `ShortDebugString`.
|
||||
if (!std::is_base_of<Message, sat::SatParameters>::value) {
|
||||
request.set_solver_specific_parameters(parameters_.SerializeAsString());
|
||||
} else {
|
||||
request.set_solver_specific_parameters(parameters_.ShortDebugString());
|
||||
}
|
||||
request.set_solver_specific_parameters(
|
||||
EncodeSatParametersAsString(parameters_));
|
||||
request.set_enable_internal_solver_output(!quiet_);
|
||||
const absl::StatusOr<MPSolutionResponse> status_or =
|
||||
SatSolveProto(std::move(request), &interrupt_solve_);
|
||||
|
||||
@@ -36,6 +36,13 @@ using google::protobuf::Message;
|
||||
using google::protobuf::Message;
|
||||
#endif
|
||||
|
||||
// Proto-lite disables some features of protos (see
|
||||
// go/abp-libraries/proto2-lite) and messages inherit from MessageLite directly
|
||||
// instead of inheriting from Message (which is itself a specialization of
|
||||
// MessageLite).
|
||||
constexpr bool kProtoLiteSatParameters =
|
||||
!std::is_base_of<Message, sat::SatParameters>::value;
|
||||
|
||||
MPSolverResponseStatus ToMPSolverResponseStatus(sat::CpSolverStatus status,
|
||||
bool has_objective) {
|
||||
switch (status) {
|
||||
@@ -64,13 +71,20 @@ absl::StatusOr<MPSolutionResponse> SatSolveProto(
|
||||
params.set_num_search_workers(8);
|
||||
params.set_log_search_progress(request.enable_internal_solver_output());
|
||||
if (request.has_solver_specific_parameters()) {
|
||||
// If code is compiled with proto-lite runtime, `solver_specific_parameters`
|
||||
// should be encoded as non-human readable string from `SerializeAsString`.
|
||||
if (!std::is_base_of<Message, sat::SatParameters>::value) {
|
||||
CHECK(params.MergeFromString(request.solver_specific_parameters()));
|
||||
// See EncodeSatParametersAsString() documentation.
|
||||
if (kProtoLiteSatParameters) {
|
||||
if (!params.MergeFromString(request.solver_specific_parameters())) {
|
||||
return absl::InvalidArgumentError(
|
||||
"solver_specific_parameters is not a valid binary stream of the "
|
||||
"SatParameters proto");
|
||||
}
|
||||
} else {
|
||||
ProtobufTextFormatMergeFromString(request.solver_specific_parameters(),
|
||||
¶ms);
|
||||
if (!ProtobufTextFormatMergeFromString(
|
||||
request.solver_specific_parameters(), ¶ms)) {
|
||||
return absl::InvalidArgumentError(
|
||||
"solver_specific_parameters is not a valid textual representation "
|
||||
"of the SatParameters proto");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (request.has_solver_time_limit_seconds()) {
|
||||
@@ -148,9 +162,18 @@ absl::StatusOr<MPSolutionResponse> SatSolveProto(
|
||||
for (int i = 0; i < size; ++i) {
|
||||
const int var = request.model().solution_hint().var_index(i);
|
||||
if (var >= var_scaling.size()) continue;
|
||||
|
||||
// To handle weird hint input values, we cap any large value to +/-
|
||||
// mip_max_bound() which is also the min/max value of any variable once
|
||||
// scaled.
|
||||
double value =
|
||||
request.model().solution_hint().var_value(i) * var_scaling[var];
|
||||
if (std::abs(value) > params.mip_max_bound()) {
|
||||
value = value > 0 ? params.mip_max_bound() : -params.mip_max_bound();
|
||||
}
|
||||
|
||||
cp_model_hint->add_vars(var);
|
||||
cp_model_hint->add_values(static_cast<int64>(std::round(
|
||||
(request.model().solution_hint().var_value(i)) * var_scaling[var])));
|
||||
cp_model_hint->add_values(static_cast<int64>(std::round(value)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,4 +219,18 @@ absl::StatusOr<MPSolutionResponse> SatSolveProto(
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
std::string EncodeSatParametersAsString(const sat::SatParameters& parameters) {
|
||||
if (kProtoLiteSatParameters) {
|
||||
// Here we use SerializeToString() instead of SerializeAsString() since the
|
||||
// later ignores errors and returns an empty string instead (which can be a
|
||||
// valid value when no fields are set).
|
||||
std::string bytes;
|
||||
CHECK(parameters.SerializeToString(&bytes));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
return parameters.ShortDebugString();
|
||||
}
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -16,13 +16,36 @@
|
||||
|
||||
#include "absl/status/statusor.h"
|
||||
#include "ortools/linear_solver/linear_solver.pb.h"
|
||||
#include "ortools/sat/sat_parameters.pb.h"
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
// Solve the input MIP model with the SAT solver.
|
||||
//
|
||||
// If possible, std::move the request into this function call to avoid a copy.
|
||||
//
|
||||
// If you need to change the solver parameters, please use the
|
||||
// EncodeSatParametersAsString() function below to set the request's
|
||||
// solver_specific_parameters field.
|
||||
absl::StatusOr<MPSolutionResponse> SatSolveProto(
|
||||
MPModelRequest request, std::atomic<bool>* interrupt_solve = nullptr);
|
||||
|
||||
// Returns a string that should be used in MPModelRequest's
|
||||
// solver_specific_parameters field to encode the SAT parameters.
|
||||
//
|
||||
// The returned string's content depends on the version of the proto library
|
||||
// that is linked in the binary.
|
||||
//
|
||||
// By default it will contain the textual representation of the input proto.
|
||||
// But when the proto-lite is used, it will contain the binary stream of the
|
||||
// proto instead since it is not possible to build the textual representation in
|
||||
// that case.
|
||||
//
|
||||
// The SatSolveProto() function will test if the proto-lite is used and expect a
|
||||
// binary stream when it is the case. So in order for your code to be portable,
|
||||
// you should always use this function to set the specific parameters.
|
||||
std::string EncodeSatParametersAsString(const sat::SatParameters& parameters);
|
||||
|
||||
} // namespace operations_research
|
||||
|
||||
#endif // OR_TOOLS_LINEAR_SOLVER_SAT_PROTO_SOLVER_H_
|
||||
|
||||
Reference in New Issue
Block a user