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_;
81 void 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;
150 void 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;
180 void SatDecisionPolicy::UseLongestAssignmentAsInitialPolarity() {
184 for (
const Literal l : best_partial_assignment_) {
185 var_polarity_[l.Variable()] = l.IsPositive();
187 best_partial_assignment_.
clear();
190 void 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];
197 void 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_);
204 void 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);
314 void 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]) {
386 void 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();
static constexpr Polarity POLARITY_FALSE
::operations_research::sat::SatParameters_Polarity initial_polarity() const
static constexpr Polarity POLARITY_TRUE
std::vector< std::pair< Literal, double > > AllPreferences() const
::PROTOBUF_NAMESPACE_ID::int32 polarity_rephase_increment() const
Class that owns everything related to a particular optimization model.
#define VLOG(verboselevel)
void UpdateVariableActivityIncrement()
double initial_variables_activity() const
bool use_optimization_hints() const
Element QueueElement(int i) const
#define DCHECK_GT(val1, val2)
void UpdateWeightedSign(const std::vector< LiteralWithCoeff > &terms, Coefficient rhs)
static constexpr VariableOrder IN_REVERSE_ORDER
static constexpr Polarity POLARITY_RANDOM
void ClearAndResize(int size)
void BeforeConflict(int trail_index)
bool Contains(int index) const
::operations_research::sat::SatParameters_VariableOrder preferred_variable_order() const
void resize(size_type new_size)
BooleanVariable Variable() const
void Add(Element element)
bool VariableIsAssigned(BooleanVariable var) const
void ResetDecisionHeuristic()
static constexpr VariableOrder IN_ORDER
SatDecisionPolicy(Model *model)
void SetAssignmentPreference(Literal literal, double weight)
#define DCHECK_GE(val1, val2)
double variable_activity_decay() const
#define CHECK_EQ(val1, val2)
bool use_phase_saving() const
void IncreasePriority(Element element)
#define DCHECK(condition)
double random_branches_ratio() const
std::tuple< int64_t, int64_t, const double > Coefficient
void BumpVariableActivities(const std::vector< Literal > &literals)
void IncreaseNumVariables(int num_variables)
#define DCHECK_LE(val1, val2)
void Untrail(int target_trail_index)
Element GetElement(int index) const
Collection of objects used to extend the Constraint Solver library.
void IncreaseSize(int size)
static constexpr Polarity POLARITY_REVERSE_WEIGHTED_SIGN
void assign(size_type n, const value_type &val)
static constexpr VariableOrder IN_RANDOM_ORDER
const VariablesAssignment & Assignment() const
static constexpr Polarity POLARITY_WEIGHTED_SIGN
double random_polarity_ratio() const
double max_variable_activity_value() const
const AssignmentInfo & Info(BooleanVariable var) const
bool use_erwa_heuristic() const
#define DCHECK_LT(val1, val2)