Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
bop_util.cc
Go to the documentation of this file.
1// Copyright 2010-2024 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 <stdint.h>
17
18#include <algorithm>
19#include <limits>
20#include <vector>
21
22#include "absl/log/check.h"
28#include "ortools/sat/boolean_problem.pb.h"
30#include "ortools/sat/restart.h"
33#include "ortools/util/bitset.h"
35
36namespace operations_research {
37namespace bop {
38namespace {
39static const int kMaxLubyIndex = 30;
40static const int kMaxBoost = 30;
41
42// Loads the problem state into the SAT solver. If the problem has already been
43// loaded in the sat_solver, fixed variables and objective bounds are updated.
44// Returns false when the problem is proved UNSAT.
45bool InternalLoadStateProblemToSatSolver(const ProblemState& problem_state,
46 sat::SatSolver* sat_solver) {
47 const bool first_time = (sat_solver->NumVariables() == 0);
48 if (first_time) {
49 sat_solver->SetNumVariables(
50 problem_state.original_problem().num_variables());
51 } else {
52 // Backtrack the solver to be able to add new constraints.
53 sat_solver->Backtrack(0);
54 }
55
56 // Set the fixed variables first so that loading the problem will be faster.
57 for (VariableIndex var(0); var < problem_state.is_fixed().size(); ++var) {
58 if (problem_state.is_fixed()[var]) {
59 if (!sat_solver->AddUnitClause(
60 sat::Literal(sat::BooleanVariable(var.value()),
61 problem_state.fixed_values()[var]))) {
62 return false;
63 }
64 }
65 }
66
67 // Load the problem if not done yet.
68 if (first_time &&
69 !LoadBooleanProblem(problem_state.original_problem(), sat_solver)) {
70 return false;
71 }
72
73 // Constrain the objective cost to be greater or equal to the lower bound,
74 // and to be smaller than the upper bound. If enforcing the strictier upper
75 // bound constraint leads to an UNSAT problem, it means the current solution
76 // is proved optimal (if the solution is feasible, else the problem is proved
77 // infeasible).
79 problem_state.original_problem(),
80 problem_state.lower_bound() != std::numeric_limits<int64_t>::min(),
81 sat::Coefficient(problem_state.lower_bound()),
82 problem_state.upper_bound() != std::numeric_limits<int64_t>::max(),
83 sat::Coefficient(problem_state.upper_bound() - 1), sat_solver)) {
84 return false;
85 }
86
87 // Adds the new binary clauses.
88 sat_solver->TrackBinaryClauses(true);
89 if (!sat_solver->AddBinaryClauses(problem_state.NewlyAddedBinaryClauses())) {
90 return false;
91 }
92 sat_solver->ClearNewlyAddedBinaryClauses();
93
94 return true;
95}
96} // anonymous namespace
97
99 const ProblemState& problem_state, sat::SatSolver* sat_solver) {
100 if (InternalLoadStateProblemToSatSolver(problem_state, sat_solver)) {
102 }
103
104 return problem_state.solution().IsFeasible()
107}
108
110 LearnedInfo* info) {
111 CHECK(nullptr != solver);
112 CHECK(nullptr != info);
113
114 // This should never be called if the problem is UNSAT.
115 CHECK(!solver->IsModelUnsat());
116
117 // Fixed variables.
118 info->fixed_literals.clear();
119 const sat::Trail& propagation_trail = solver->LiteralTrail();
120 const int root_size = solver->CurrentDecisionLevel() == 0
121 ? propagation_trail.Index()
122 : solver->Decisions().front().trail_index;
123 for (int trail_index = 0; trail_index < root_size; ++trail_index) {
124 info->fixed_literals.push_back(propagation_trail[trail_index]);
125 }
126
127 // Binary clauses.
128 info->binary_clauses = solver->NewlyAddedBinaryClauses();
130}
131
134 CHECK(solution != nullptr);
135
136 // Only extract the variables of the initial problem.
137 CHECK_LE(solution->Size(), assignment.NumberOfVariables());
138 for (sat::BooleanVariable var(0); var < solution->Size(); ++var) {
139 CHECK(assignment.VariableIsAssigned(var));
140 const bool value = assignment.LiteralIsTrue(sat::Literal(var, true));
141 const VariableIndex bop_var_id(var.value());
142 solution->SetValue(bop_var_id, value);
143 }
144}
145
146//------------------------------------------------------------------------------
147// AdaptiveParameterValue
148//------------------------------------------------------------------------------
150 : value_(initial_value), num_changes_(0) {}
152void AdaptiveParameterValue::Reset() { num_changes_ = 0; }
153
155 ++num_changes_;
156 const double factor = 1.0 + 1.0 / (num_changes_ / 2.0 + 1);
157 value_ = std::min(1.0 - (1.0 - value_) / factor, value_ * factor);
158}
159
161 ++num_changes_;
162 const double factor = 1.0 + 1.0 / (num_changes_ / 2.0 + 1);
163 value_ = std::max(value_ / factor, 1.0 - (1.0 - value_) * factor);
164}
165
166//------------------------------------------------------------------------------
167// LubyAdaptiveParameterValue
168//------------------------------------------------------------------------------
169LubyAdaptiveParameterValue::LubyAdaptiveParameterValue(double initial_value)
170 : luby_id_(0),
171 luby_boost_(0),
172 luby_value_(0),
173 difficulties_(kMaxLubyIndex, AdaptiveParameterValue(initial_value)) {
174 Reset();
175}
176
177void LubyAdaptiveParameterValue::Reset() {
178 luby_id_ = 0;
179 luby_boost_ = 0;
180 luby_value_ = 0;
181 for (int i = 0; i < difficulties_.size(); ++i) {
182 difficulties_[i].Reset();
183 }
184}
185
186void LubyAdaptiveParameterValue::IncreaseParameter() {
187 const int luby_msb = MostSignificantBitPosition64(luby_value_);
188 difficulties_[luby_msb].Increase();
189}
191void LubyAdaptiveParameterValue::DecreaseParameter() {
192 const int luby_msb = MostSignificantBitPosition64(luby_value_);
193 difficulties_[luby_msb].Decrease();
194}
196double LubyAdaptiveParameterValue::GetParameterValue() const {
197 const int luby_msb = MostSignificantBitPosition64(luby_value_);
198 return difficulties_[luby_msb].value();
199}
201bool LubyAdaptiveParameterValue::BoostLuby() {
202 ++luby_boost_;
203 return luby_boost_ >= kMaxBoost;
204}
206void LubyAdaptiveParameterValue::UpdateLuby() {
207 ++luby_id_;
208 luby_value_ = sat::SUniv(luby_id_) << luby_boost_;
209}
210} // namespace bop
211} // namespace operations_research
IntegerValue size
AdaptiveParameterValue(double initial_value)
Initial value is in [0..1].
Definition bop_util.cc:151
const BopSolution & solution() const
Definition bop_base.h:205
const std::vector< BinaryClause > & NewlyAddedBinaryClauses()
const std::vector< Decision > & Decisions() const
Definition sat_solver.h:385
const Trail & LiteralTrail() const
Definition sat_solver.h:387
bool VariableIsAssigned(BooleanVariable var) const
Returns true iff the given variable is assigned.
Definition sat_base.h:196
bool LiteralIsTrue(Literal literal) const
Definition sat_base.h:188
int64_t value
IntVar * var
double solution
BopOptimizerBase::Status LoadStateProblemToSatSolver(const ProblemState &problem_state, sat::SatSolver *sat_solver)
Definition bop_util.cc:98
void SatAssignmentToBopSolution(const sat::VariablesAssignment &assignment, BopSolution *solution)
Definition bop_util.cc:132
void ExtractLearnedInfoFromSatSolver(sat::SatSolver *solver, LearnedInfo *info)
Definition bop_util.cc:109
bool AddObjectiveConstraint(const LinearBooleanProblem &problem, bool use_lower_bound, Coefficient lower_bound, bool use_upper_bound, Coefficient upper_bound, SatSolver *solver)
bool LoadBooleanProblem(const LinearBooleanProblem &problem, SatSolver *solver)
Loads a BooleanProblem into a given SatSolver instance.
In SWIG mode, we don't want anything besides these top-level includes.
int MostSignificantBitPosition64(uint64_t n)
Definition bitset.h:235
std::vector< sat::BinaryClause > binary_clauses
New binary clauses.
Definition bop_base.h:288
std::vector< sat::Literal > fixed_literals
Vector of all literals that have been fixed.
Definition bop_base.h:273