OR-Tools  9.6
restart.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 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 
14 #include "ortools/sat/restart.h"
15 
16 #include <string>
17 #include <vector>
18 
19 #include "absl/strings/str_format.h"
20 #include "absl/strings/str_split.h"
21 #include "ortools/base/logging.h"
24 #include "ortools/sat/sat_parameters.pb.h"
26 
27 namespace operations_research {
28 namespace sat {
29 
31  num_restarts_ = 0;
32  strategy_counter_ = 0;
33  strategy_change_conflicts_ =
34  parameters_.num_conflicts_before_strategy_changes();
35  conflicts_until_next_strategy_change_ = strategy_change_conflicts_;
36 
37  luby_count_ = 0;
38  conflicts_until_next_restart_ = parameters_.restart_period();
39 
40  dl_running_average_.Reset(parameters_.restart_running_window_size());
41  lbd_running_average_.Reset(parameters_.restart_running_window_size());
42  trail_size_running_average_.Reset(parameters_.blocking_restart_window_size());
43 
44  // Compute the list of restart algorithms to cycle through.
45  //
46  // TODO(user): for some reason, strategies_.assign() does not work as the
47  // returned type of the proto enum iterator is int ?!
48  strategies_.clear();
49  for (int i = 0; i < parameters_.restart_algorithms_size(); ++i) {
50  strategies_.push_back(parameters_.restart_algorithms(i));
51  }
52  if (strategies_.empty()) {
53  const std::vector<std::string> string_values = absl::StrSplit(
54  parameters_.default_restart_algorithms(), ',', absl::SkipEmpty());
55  for (const std::string& string_value : string_values) {
56  SatParameters::RestartAlgorithm tmp;
57 #if defined(__PORTABLE_PLATFORM__)
58  if (string_value == "NO_RESTART") {
59  tmp = SatParameters::NO_RESTART;
60  } else if (string_value == "LUBY_RESTART") {
61  tmp = SatParameters::LUBY_RESTART;
62  } else if (string_value == "DL_MOVING_AVERAGE_RESTART") {
63  tmp = SatParameters::DL_MOVING_AVERAGE_RESTART;
64  } else if (string_value == "LBD_MOVING_AVERAGE_RESTART") {
65  tmp = SatParameters::LBD_MOVING_AVERAGE_RESTART;
66  } else if (string_value == "FIXED_RESTART") {
67  tmp = SatParameters::FIXED_RESTART;
68  } else {
69  LOG(WARNING) << "Couldn't parse the RestartAlgorithm name: '"
70  << string_value << "'.";
71  continue;
72  }
73 #else // __PORTABLE_PLATFORM__
74  if (!SatParameters::RestartAlgorithm_Parse(string_value, &tmp)) {
75  LOG(WARNING) << "Couldn't parse the RestartAlgorithm name: '"
76  << string_value << "'.";
77  continue;
78  }
79 #endif // !__PORTABLE_PLATFORM__
80  strategies_.push_back(tmp);
81  }
82  }
83  if (strategies_.empty()) {
84  strategies_.push_back(SatParameters::NO_RESTART);
85  }
86 }
87 
89  bool should_restart = false;
90  switch (strategies_[strategy_counter_ % strategies_.size()]) {
91  case SatParameters::NO_RESTART:
92  break;
93  case SatParameters::LUBY_RESTART:
94  if (conflicts_until_next_restart_ == 0) {
95  luby_count_++;
96  should_restart = true;
97  }
98  break;
99  case SatParameters::DL_MOVING_AVERAGE_RESTART:
100  if (dl_running_average_.IsWindowFull() &&
101  dl_running_average_.GlobalAverage() <
102  parameters_.restart_dl_average_ratio() *
103  dl_running_average_.WindowAverage()) {
104  should_restart = true;
105  }
106  break;
107  case SatParameters::LBD_MOVING_AVERAGE_RESTART:
108  if (lbd_running_average_.IsWindowFull() &&
109  lbd_running_average_.GlobalAverage() <
110  parameters_.restart_lbd_average_ratio() *
111  lbd_running_average_.WindowAverage()) {
112  should_restart = true;
113  }
114  break;
115  case SatParameters::FIXED_RESTART:
116  if (conflicts_until_next_restart_ == 0) {
117  should_restart = true;
118  }
119  break;
120  }
121  if (should_restart) {
122  num_restarts_++;
123 
124  // Strategy switch?
125  if (conflicts_until_next_strategy_change_ == 0) {
126  strategy_counter_++;
127  strategy_change_conflicts_ +=
128  static_cast<int>(parameters_.strategy_change_increase_ratio() *
129  strategy_change_conflicts_);
130  conflicts_until_next_strategy_change_ = strategy_change_conflicts_;
131 
132  // The LUBY_RESTART strategy is considered the "stable" mode and we change
133  // the polariy heuristic while under it.
134  decision_policy_->SetStablePhase(
135  strategies_[strategy_counter_ % strategies_.size()] ==
136  SatParameters::LUBY_RESTART);
137  }
138 
139  // Reset the various restart strategies.
140  dl_running_average_.ClearWindow();
141  lbd_running_average_.ClearWindow();
142  conflicts_until_next_restart_ = parameters_.restart_period();
143  if (strategies_[strategy_counter_ % strategies_.size()] ==
144  SatParameters::LUBY_RESTART) {
145  conflicts_until_next_restart_ *= SUniv(luby_count_ + 1);
146  }
147  }
148  return should_restart;
149 }
150 
151 void RestartPolicy::OnConflict(int conflict_trail_index,
152  int conflict_decision_level, int conflict_lbd) {
153  // Decrement the restart counter if needed.
154  if (conflicts_until_next_restart_ > 0) {
155  --conflicts_until_next_restart_;
156  }
157  if (conflicts_until_next_strategy_change_ > 0) {
158  --conflicts_until_next_strategy_change_;
159  }
160 
161  trail_size_running_average_.Add(conflict_trail_index);
162  dl_running_average_.Add(conflict_decision_level);
163  lbd_running_average_.Add(conflict_lbd);
164 
165  // Block the restart.
166  // Note(user): glucose only activate this after 10000 conflicts.
167  if (parameters_.use_blocking_restart()) {
168  if (lbd_running_average_.IsWindowFull() &&
169  dl_running_average_.IsWindowFull() &&
170  trail_size_running_average_.IsWindowFull() &&
171  conflict_trail_index >
172  parameters_.blocking_restart_multiplier() *
173  trail_size_running_average_.WindowAverage()) {
174  dl_running_average_.ClearWindow();
175  lbd_running_average_.ClearWindow();
176  }
177  }
178 }
179 
180 std::string RestartPolicy::InfoString() const {
181  std::string result =
182  absl::StrFormat(" num restarts: %d\n", num_restarts_) +
183  absl::StrFormat(
184  " current_strategy: %s\n",
185  ProtoEnumToString<SatParameters::RestartAlgorithm>(
186  strategies_[strategy_counter_ % strategies_.size()])) +
187  absl::StrFormat(" conflict decision level avg: %f window: %f\n",
188  dl_running_average_.GlobalAverage(),
189  dl_running_average_.WindowAverage()) +
190  absl::StrFormat(" conflict lbd avg: %f window: %f\n",
191  lbd_running_average_.GlobalAverage(),
192  lbd_running_average_.WindowAverage()) +
193  absl::StrFormat(" conflict trail size avg: %f window: %f\n",
194  trail_size_running_average_.GlobalAverage(),
195  trail_size_running_average_.WindowAverage());
196  return result;
197 }
198 
199 } // namespace sat
200 } // namespace operations_research
void OnConflict(int conflict_trail_index, int conflict_decision_level, int conflict_lbd)
Definition: restart.cc:151
Collection of objects used to extend the Constraint Solver library.