Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
restart.cc
Go to the documentation of this file.
1// Copyright 2010-2024 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"
24#include "ortools/sat/sat_parameters.pb.h"
26
27namespace operations_research {
28namespace 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
151void 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
180std::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",
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 ClearWindow()
Clears the current window.
void Add(int value)
Adds the next integer of the stream.
void Reset()
Resets the policy using the current model parameters.
Definition restart.cc:30
std::string InfoString() const
Returns a string with the current restart statistics.
Definition restart.cc:180
void OnConflict(int conflict_trail_index, int conflict_decision_level, int conflict_lbd)
Definition restart.cc:151
In SWIG mode, we don't want anything besides these top-level includes.
std::string ProtoEnumToString(ProtoEnumType enum_value)
Definition proto_utils.h:50