29 const int old_num_variables = activities_.size();
30 DCHECK_GE(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) {
271 const double value = var_ordering_.GetElement(
var.value()).tie_breaker;
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);
356 var = var_ordering_.QueueElement(index_dist(*random_)).var;
359 var_ordering_.Remove(
var.value());
363 DCHECK(!var_ordering_.IsEmpty());
364 var = var_ordering_.Top().var;
368 DCHECK(!var_ordering_.IsEmpty());
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]};
389 if (var_ordering_.Contains(
var.value())) {
391 var_ordering_.IncreasePriority(element);
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();
469 CHECK(var_ordering_.Contains(
var.value()));
470 CHECK_EQ(activities_[
var], var_ordering_.GetElement(
var.value()).weight);
#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 IncreaseSize(int size)
void ClearAndResize(int size)
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
::PROTOBUF_NAMESPACE_ID::int32 polarity_rephase_increment() 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
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.