29 const int old_num_variables = activities_.
size();
33 tie_breakers_.
resize(num_variables, 0.0);
34 num_bumps_.
resize(num_variables, 0);
35 pq_need_update_for_var_at_trail_index_.
IncreaseSize(num_variables);
37 weighted_sign_.
resize(num_variables, 0.0);
39 has_forced_polarity_.
resize(num_variables,
false);
40 forced_polarity_.
resize(num_variables);
41 has_target_polarity_.
resize(num_variables,
false);
42 target_polarity_.
resize(num_variables);
43 var_polarity_.
resize(num_variables);
45 ResetInitialPolarity(old_num_variables);
49 var_ordering_.
Reserve(num_variables);
50 if (var_ordering_is_initialized_) {
51 for (BooleanVariable
var(old_num_variables);
var < num_variables; ++
var) {
52 var_ordering_.
Add({
var, 0.0, activities_[
var]});
60 num_conflicts_stack_.push_back({trail_.
Index(), 1});
63 if (trail_index > target_length_) {
64 target_length_ = trail_index;
65 has_target_polarity_.
assign(has_target_polarity_.
size(),
false);
66 for (
int i = 0; i < trail_index; ++i) {
68 has_target_polarity_[l.
Variable()] =
true;
73 if (trail_index > best_partial_assignment_.size()) {
74 best_partial_assignment_.assign(&trail_[0], &trail_[trail_index]);
77 --num_conflicts_until_rephase_;
81void SatDecisionPolicy::RephaseIfNeeded() {
83 if (num_conflicts_until_rephase_ > 0)
return;
85 VLOG(1) <<
"End of polarity phase " << polarity_phase_
86 <<
" target_length: " << target_length_
87 <<
" best_length: " << best_partial_assignment_.size();
90 num_conflicts_until_rephase_ =
95 has_target_polarity_.
assign(has_target_polarity_.
size(),
false);
100 switch (polarity_phase_ % 8) {
102 ResetInitialPolarity(0);
105 UseLongestAssignmentAsInitialPolarity();
108 ResetInitialPolarity(0,
true);
111 UseLongestAssignmentAsInitialPolarity();
114 RandomizeCurrentPolarity();
117 UseLongestAssignmentAsInitialPolarity();
120 FlipCurrentPolarity();
123 UseLongestAssignmentAsInitialPolarity();
129 const int num_variables = activities_.
size();
130 variable_activity_increment_ = 1.0;
132 tie_breakers_.
assign(num_variables, 0.0);
133 num_bumps_.
assign(num_variables, 0);
134 var_ordering_.
Clear();
139 ResetInitialPolarity(0);
140 has_target_polarity_.
assign(num_variables,
false);
141 has_forced_polarity_.
assign(num_variables,
false);
142 best_partial_assignment_.clear();
145 num_conflicts_stack_.clear();
147 var_ordering_is_initialized_ =
false;
150void SatDecisionPolicy::ResetInitialPolarity(
int from,
bool inverted) {
158 const int num_variables = activities_.
size();
159 for (BooleanVariable
var(from);
var < num_variables; ++
var) {
162 var_polarity_[
var] = inverted ? false :
true;
165 var_polarity_[
var] = inverted ? true :
false;
168 var_polarity_[
var] = std::uniform_int_distribution<int>(0, 1)(*random_);
171 var_polarity_[
var] = weighted_sign_[
var] > 0;
174 var_polarity_[
var] = weighted_sign_[
var] < 0;
180void SatDecisionPolicy::UseLongestAssignmentAsInitialPolarity() {
184 for (
const Literal l : best_partial_assignment_) {
185 var_polarity_[l.Variable()] = l.IsPositive();
187 best_partial_assignment_.
clear();
190void SatDecisionPolicy::FlipCurrentPolarity() {
191 const int num_variables = var_polarity_.
size();
192 for (BooleanVariable
var;
var < num_variables; ++
var) {
193 var_polarity_[
var] = !var_polarity_[
var];
197void SatDecisionPolicy::RandomizeCurrentPolarity() {
198 const int num_variables = var_polarity_.
size();
199 for (BooleanVariable
var;
var < num_variables; ++
var) {
200 var_polarity_[
var] = std::uniform_int_distribution<int>(0, 1)(*random_);
204void SatDecisionPolicy::InitializeVariableOrdering() {
205 const int num_variables = activities_.
size();
209 var_ordering_.
Clear();
210 tmp_variables_.clear();
211 for (BooleanVariable
var(0);
var < num_variables; ++
var) {
213 if (activities_[
var] > 0.0) {
215 {
var,
static_cast<float>(tie_breakers_[
var]), activities_[
var]});
217 tmp_variables_.push_back(
var);
232 std::reverse(tmp_variables_.begin(), tmp_variables_.end());
235 std::shuffle(tmp_variables_.begin(), tmp_variables_.end(), *random_);
240 for (
const BooleanVariable
var : tmp_variables_) {
241 var_ordering_.
Add({
var,
static_cast<float>(tie_breakers_[
var]), 0.0});
245 pq_need_update_for_var_at_trail_index_.
ClearAndResize(num_variables);
247 var_ordering_is_initialized_ =
true;
256 has_forced_polarity_[
literal.Variable()] =
true;
262 var_ordering_is_initialized_ =
false;
267 std::vector<std::pair<Literal, double>> prefs;
268 for (BooleanVariable
var(0);
var < var_polarity_.
size(); ++
var) {
280 const std::vector<LiteralWithCoeff>& terms,
Coefficient rhs) {
282 const double weight =
static_cast<double>(term.coefficient.value()) /
283 static_cast<double>(rhs.value());
284 weighted_sign_[term.literal.Variable()] +=
290 const std::vector<Literal>& literals) {
296 ++num_bumps_[
literal.Variable()];
303 const BooleanVariable
var =
literal.Variable();
305 if (level == 0)
continue;
306 activities_[
var] += variable_activity_increment_;
308 if (activities_[
var] > max_activity_value) {
309 RescaleVariableActivities(1.0 / max_activity_value);
314void SatDecisionPolicy::RescaleVariableActivities(
double scaling_factor) {
315 variable_activity_increment_ *= scaling_factor;
316 for (BooleanVariable
var(0);
var < activities_.
size(); ++
var) {
317 activities_[
var] *= scaling_factor;
331 var_ordering_is_initialized_ =
false;
340 if (!var_ordering_is_initialized_) {
341 InitializeVariableOrdering();
347 auto zero_to_one = [
this]() {
348 return std::uniform_real_distribution<double>()(*random_);
354 std::uniform_int_distribution<int> index_dist(0,
355 var_ordering_.
Size() - 1);
364 var = var_ordering_.
Top().var;
369 var = var_ordering_.
Top().var;
375 if (random_ratio != 0.0 && zero_to_one() < random_ratio) {
376 return Literal(
var, std::uniform_int_distribution<int>(0, 1)(*random_));
380 if (in_stable_phase_ && has_target_polarity_[
var]) {
386void SatDecisionPolicy::PqInsertOrUpdate(BooleanVariable
var) {
387 const WeightedVarQueueElement element{
388 var,
static_cast<float>(tie_breakers_[
var]), activities_[
var]};
393 var_ordering_.
Add(element);
400 for (
int i = target_trail_index; i < trail_.
Index(); ++i) {
410 const double alpha =
std::max(0.06, 0.4 - 1e-6 * num_conflicts_);
414 int num_conflicts = 0;
415 int next_num_conflicts_update =
416 num_conflicts_stack_.empty() ? -1
417 : num_conflicts_stack_.back().trail_index;
419 int trail_index = trail_.
Index();
420 while (trail_index > target_trail_index) {
421 if (next_num_conflicts_update == trail_index) {
422 num_conflicts += num_conflicts_stack_.back().count;
423 num_conflicts_stack_.pop_back();
424 next_num_conflicts_update =
425 num_conflicts_stack_.empty()
427 : num_conflicts_stack_.back().trail_index;
429 const BooleanVariable
var = trail_[--trail_index].Variable();
433 const int64_t num_bumps = num_bumps_[
var];
434 double new_rate = 0.0;
438 new_rate =
static_cast<double>(num_bumps) / num_conflicts;
440 activities_[
var] = alpha * new_rate + (1 - alpha) * activities_[
var];
441 if (var_ordering_is_initialized_) PqInsertOrUpdate(
var);
443 if (num_conflicts > 0) {
444 if (!num_conflicts_stack_.empty() &&
445 num_conflicts_stack_.back().trail_index == trail_.
Index()) {
446 num_conflicts_stack_.back().count += num_conflicts;
448 num_conflicts_stack_.push_back({trail_.
Index(), num_conflicts});
452 if (!var_ordering_is_initialized_)
return;
455 int to_update = pq_need_update_for_var_at_trail_index_.
Top();
456 while (to_update >= target_trail_index) {
458 PqInsertOrUpdate(trail_[to_update].Variable());
459 pq_need_update_for_var_at_trail_index_.
ClearTop();
460 to_update = pq_need_update_for_var_at_trail_index_.
Top();
465 if (
DEBUG_MODE && var_ordering_is_initialized_) {
466 for (
int trail_index = trail_.
Index() - 1; trail_index > target_trail_index;
468 const BooleanVariable
var = trail_[trail_index].Variable();
#define DCHECK_LE(val1, val2)
#define CHECK_EQ(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define VLOG(verboselevel)
void assign(size_type n, const value_type &val)
void resize(size_type new_size)
void IncreaseSize(int size)
void ClearAndResize(int size)
bool Contains(int index) const
Element QueueElement(int i) const
void Add(Element element)
void IncreasePriority(Element element)
Element GetElement(int index) const
BooleanVariable Variable() const
Class that owns everything related to a particular optimization model.
std::vector< std::pair< Literal, double > > AllPreferences() const
void IncreaseNumVariables(int num_variables)
void ResetDecisionHeuristic()
void UpdateVariableActivityIncrement()
void SetAssignmentPreference(Literal literal, double weight)
void Untrail(int target_trail_index)
void BumpVariableActivities(const std::vector< Literal > &literals)
void BeforeConflict(int trail_index)
void UpdateWeightedSign(const std::vector< LiteralWithCoeff > &terms, Coefficient rhs)
SatDecisionPolicy(Model *model)
static constexpr Polarity POLARITY_FALSE
bool use_optimization_hints() const
static constexpr Polarity POLARITY_TRUE
bool use_erwa_heuristic() const
double max_variable_activity_value() const
static constexpr Polarity POLARITY_REVERSE_WEIGHTED_SIGN
static constexpr Polarity POLARITY_RANDOM
static constexpr VariableOrder IN_ORDER
double variable_activity_decay() const
bool use_phase_saving() const
static constexpr VariableOrder IN_REVERSE_ORDER
::operations_research::sat::SatParameters_VariableOrder preferred_variable_order() const
double initial_variables_activity() const
double random_branches_ratio() const
::operations_research::sat::SatParameters_Polarity initial_polarity() const
double random_polarity_ratio() const
static constexpr VariableOrder IN_RANDOM_ORDER
int32_t polarity_rephase_increment() const
static constexpr Polarity POLARITY_WEIGHTED_SIGN
const VariablesAssignment & Assignment() const
const AssignmentInfo & Info(BooleanVariable var) const
bool VariableIsAssigned(BooleanVariable var) const
std::tuple< int64_t, int64_t, const double > Coefficient
Collection of objects used to extend the Constraint Solver library.