sync gscip
This commit is contained in:
@@ -171,6 +171,29 @@ SCIP_PARAMSETTING ConvertMetaParamValue(
|
||||
}
|
||||
}
|
||||
|
||||
absl::Status CheckSolutionsInOrder(const GScipResult& result,
|
||||
const bool is_maximize) {
|
||||
auto objective_as_good_as = [is_maximize](double left, double right) {
|
||||
if (is_maximize) {
|
||||
return left >= right;
|
||||
}
|
||||
return left <= right;
|
||||
};
|
||||
for (int i = 1; i < result.objective_values.size(); ++i) {
|
||||
const double previous = result.objective_values[i - 1];
|
||||
const double current = result.objective_values[i];
|
||||
if (!objective_as_good_as(previous, current)) {
|
||||
return util::InternalErrorBuilder()
|
||||
<< "Expected SCIP solutions to be in best objective order "
|
||||
"first, but for "
|
||||
<< (is_maximize ? "maximization" : "minimization")
|
||||
<< " problem, the " << i - 1 << " objective is " << previous
|
||||
<< " and the " << i << " objective is " << current;
|
||||
}
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const GScipVariableOptions& DefaultGScipVariableOptions() {
|
||||
@@ -779,6 +802,10 @@ absl::StatusOr<GScipResult> GScip::Solve(
|
||||
RETURN_IF_SCIP_ERROR(SCIPwriteOrigProblem(
|
||||
scip_, params.scip_model_filename().c_str(), "cip", FALSE));
|
||||
}
|
||||
if (params.has_objective_limit()) {
|
||||
RETURN_IF_SCIP_ERROR(
|
||||
SCIPsetObjlimit(scip_, ScipInfClamp(params.objective_limit())));
|
||||
}
|
||||
|
||||
// Install the message handler if necessary. We do this after setting the
|
||||
// parameters so that parameters that applies to the default message handler
|
||||
@@ -855,6 +882,7 @@ absl::StatusOr<GScipResult> GScip::Solve(
|
||||
result.solutions.push_back(solution);
|
||||
result.objective_values.push_back(obj_value);
|
||||
}
|
||||
RETURN_IF_ERROR(CheckSolutionsInOrder(result, ObjectiveIsMaximize()));
|
||||
// Can only check for primal ray if we made it past presolve.
|
||||
if (stage != SCIP_STAGE_PRESOLVING && SCIPhasPrimalRay(scip_)) {
|
||||
for (SCIP_VAR* v : variables_) {
|
||||
@@ -889,6 +917,9 @@ absl::StatusOr<GScipResult> GScip::Solve(
|
||||
// the remainder of the buffer content would be lost.
|
||||
new_handler.reset();
|
||||
}
|
||||
if (params.has_objective_limit()) {
|
||||
RETURN_IF_SCIP_ERROR(SCIPsetObjlimit(scip_, SCIP_INVALID));
|
||||
}
|
||||
|
||||
RETURN_IF_SCIP_ERROR(SCIPresetParams(scip_));
|
||||
// The `silence_output` and `search_logs_filename` parameters are special
|
||||
|
||||
@@ -111,6 +111,13 @@ message GScipParameters {
|
||||
// How many solutions to retrieve from the solution pool (if this many exist).
|
||||
// At least one solution will always be returned, even if num_solutions < 1.
|
||||
optional int32 num_solutions = 17;
|
||||
|
||||
// If set, ignore all solutions worse than objective_limit, for details see
|
||||
// SCIPsetObjlimit(). Note that the solution pool will still contain solutions
|
||||
// worse than the limit as SCIP uses these to run improvement heuristics, and
|
||||
// if you query all solutions at the end of the solve they will be present,
|
||||
// even if you found no solution that met the limit and returned infeasible.
|
||||
optional double objective_limit = 18;
|
||||
}
|
||||
|
||||
// TODO(user): this should be machine generated by script and contain all of
|
||||
|
||||
Reference in New Issue
Block a user