Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
sat_solver_utils.cc
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <memory>
17#include <string>
18#include <utility>
19#include <vector>
20
21#include "absl/log/check.h"
30
31namespace operations_research {
32
33#define ADD_LP_PREPROCESSOR(name, ...) \
34 names.push_back(#name); \
35 lp_preprocessors.push_back( \
36 std::make_unique<name>(&glop_params __VA_OPT__(, ) __VA_ARGS__));
37
39 const glop::GlopParameters& glop_params, MPModelProto* model,
40 std::vector<std::unique_ptr<glop::Preprocessor>>* for_postsolve,
41 SolverLogger* logger) {
42 CHECK(model != nullptr);
43
44 // TODO(user): General constraints are currently not supported.
45 if (!model->general_constraint().empty()) {
47 }
48
49 // We need to copy the hint because LinearProgramToMPModelProto() loose it.
50 const bool hint_is_present = model->has_solution_hint();
51 const auto copy_of_hint = model->solution_hint();
52
53 std::unique_ptr<TimeLimit> time_limit =
54 TimeLimit::FromParameters(glop_params);
55
56 // TODO(user): Remove this back and forth conversion. We could convert
57 // the LinearProgram directly to a CpModelProto, or we could have a custom
58 // implementation of these presolve steps.
61
62 // These presolve might change the problem size.
63 //
64 // TODO(user): transform the hint instead of disabling presolve.
65 std::vector<std::string> names;
66 std::vector<std::unique_ptr<glop::Preprocessor>> lp_preprocessors;
67 const std::string header =
68 "Running basic LP presolve, initial problem dimensions: ";
69 if (!hint_is_present) {
70 SOLVER_LOG(logger, "");
71 SOLVER_LOG(logger, header, lp.GetDimensionString());
76
77 // TODO(user): Usually it is good to run the ImpliedFreePreprocessor before
78 // this one. However this seems to cause problem on atm20-100.mps. Moreover,
79 // for the conversion, it is better to have tight bounds even if the bound
80 // propagator is supposed to undo what this presolve would have done.
82 }
83
84 // These preprocessors do not need postsolve.
88
89 // We need to re-run this after the ImpliedIntegerPreprocessor because the
90 // latter does not round the bounds of the constraints involving only
91 // integer variables and coefficients.
94
95 for (int i = 0; i < lp_preprocessors.size(); ++i) {
96 if (time_limit->LimitReached()) break;
97 auto& preprocessor = lp_preprocessors[i];
98 preprocessor->SetTimeLimit(time_limit.get());
99 preprocessor->UseInMipContext();
100 const bool need_postsolve = preprocessor->Run(&lp);
101 names[i].resize(header.size(), ' '); // padding.
102 SOLVER_LOG(logger, names[i], lp.GetDimensionString());
103 const glop::ProblemStatus status = preprocessor->status();
104 if (status != glop::ProblemStatus::INIT) return status;
105 if (need_postsolve) for_postsolve->push_back(std::move(preprocessor));
106 }
107
108 // Finally, we make sure all domains contain zero.
109 if (!hint_is_present) {
110 auto shift_bounds =
111 std::make_unique<glop::ShiftVariableBoundsPreprocessor>(&glop_params);
112 shift_bounds->UseInMipContext();
113 const bool need_postsolve = shift_bounds->Run(&lp);
114 if (shift_bounds->status() != glop::ProblemStatus::INIT) {
115 return shift_bounds->status();
116 }
117 if (need_postsolve) {
118 for_postsolve->push_back(std::move(shift_bounds));
119 }
120 }
121
123
124 // Restore the hint, note that none of the presolve steps we run here change
125 // the number of variables in the model.
126 if (hint_is_present) {
127 *model->mutable_solution_hint() = copy_of_hint;
128 }
129
131}
132
133#undef ADD_LP_PREPROCESSOR
134
135} // namespace operations_research
const ::operations_research::MPGeneralConstraintProto & general_constraint(int index) const
::operations_research::PartialVariableAssignment *PROTOBUF_NONNULL mutable_solution_hint()
const ::operations_research::PartialVariableAssignment & solution_hint() const
static std::unique_ptr< TimeLimit > FromParameters(const Parameters &parameters)
Definition time_limit.h:143
void LinearProgramToMPModelProto(const LinearProgram &input, MPModelProto *output)
void MPModelProtoToLinearProgram(const MPModelProto &input, LinearProgram *output)
OR-Tools root namespace.
glop::ProblemStatus ApplyMipPresolveSteps(const glop::GlopParameters &glop_params, MPModelProto *model, std::vector< std::unique_ptr< glop::Preprocessor > > *for_postsolve, SolverLogger *logger)
#define ADD_LP_PREPROCESSOR(name,...)
#define SOLVER_LOG(logger,...)
Definition logging.h:114