24 : parameters_(*(
model->GetOrCreate<SatParameters>())),
29 const int old_num_variables = activities_.
size();
32 activities_.
resize(num_variables, parameters_.initial_variables_activity());
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]});
58 if (parameters_.use_erwa_heuristic()) {
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() {
82 if (parameters_.polarity_rephase_increment() <= 0)
return;
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_ =
91 parameters_.polarity_rephase_increment() * (polarity_phase_ + 1);
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;
131 activities_.
assign(num_variables, parameters_.initial_variables_activity());
132 tie_breakers_.
assign(num_variables, 0.0);
133 num_bumps_.
assign(num_variables, 0);
134 var_ordering_.
Clear();
137 num_conflicts_until_rephase_ = parameters_.polarity_rephase_increment();
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) {
160 switch (parameters_.initial_polarity()) {
161 case SatParameters::POLARITY_TRUE:
162 var_polarity_[
var] = inverted ? false :
true;
164 case SatParameters::POLARITY_FALSE:
165 var_polarity_[
var] = inverted ? true :
false;
167 case SatParameters::POLARITY_RANDOM:
168 var_polarity_[
var] = std::uniform_int_distribution<int>(0, 1)(*random_);
170 case SatParameters::POLARITY_WEIGHTED_SIGN:
171 var_polarity_[
var] = weighted_sign_[
var] > 0;
173 case SatParameters::POLARITY_REVERSE_WEIGHTED_SIGN:
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);
228 switch (parameters_.preferred_variable_order()) {
229 case SatParameters::IN_ORDER:
231 case SatParameters::IN_REVERSE_ORDER:
232 std::reverse(tmp_variables_.begin(), tmp_variables_.end());
234 case SatParameters::IN_RANDOM_ORDER:
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;
252 if (!parameters_.use_optimization_hints())
return;
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) {
291 if (parameters_.use_erwa_heuristic()) {
296 ++num_bumps_[
literal.Variable()];
301 const double max_activity_value = parameters_.max_variable_activity_value();
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;
335 variable_activity_increment_ *= 1.0 / parameters_.variable_activity_decay();
340 if (!var_ordering_is_initialized_) {
341 InitializeVariableOrdering();
346 const double ratio = parameters_.random_branches_ratio();
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;
374 const double random_ratio = parameters_.random_polarity_ratio();
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);
399 if (maybe_enable_phase_saving_ && parameters_.use_phase_saving()) {
400 for (
int i = target_trail_index; i < trail_.
Index(); ++i) {
407 if (parameters_.use_erwa_heuristic()) {
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)
const AssignmentInfo & Info(BooleanVariable var) const
const VariablesAssignment & Assignment() const
bool VariableIsAssigned(BooleanVariable var) const
Collection of objects used to extend the Constraint Solver library.