14 #ifndef OR_TOOLS_SAT_SYNCHRONIZATION_H_
15 #define OR_TOOLS_SAT_SYNCHRONIZATION_H_
21 #include "absl/random/random.h"
22 #include "absl/synchronization/mutex.h"
42 template <
typename ValueType>
98 void Add(
const Solution& solution);
111 ABSL_EXCLUSIVE_LOCKS_REQUIRED(
mutex_);
160 std::vector<std::vector<double>> solutions_;
161 mutable absl::Mutex mutex_;
193 std::function<
void(
const CpSolverResponse&)>
callback);
230 IntegerValue lb, IntegerValue ub);
285 dump_prefix_ = dump_prefix;
289 void TestGapLimitsIfNeeded() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
290 void FillObjectiveValuesInBestResponse()
291 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
293 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
295 const
bool log_updates_;
296 const
bool enumerate_all_solutions_;
297 const CpModelProto& model_proto_;
301 mutable
absl::Mutex mutex_;
304 double absolute_gap_limit_ ABSL_GUARDED_BY(mutex_) = 0.0;
305 double relative_gap_limit_ ABSL_GUARDED_BY(mutex_) = 0.0;
307 CpSolverResponse best_response_ ABSL_GUARDED_BY(mutex_);
310 int num_solutions_ ABSL_GUARDED_BY(mutex_) = 0;
311 int64 inner_objective_lower_bound_ ABSL_GUARDED_BY(mutex_) =
kint64min;
312 int64 inner_objective_upper_bound_ ABSL_GUARDED_BY(mutex_) =
kint64max;
313 int64 best_solution_objective_value_ ABSL_GUARDED_BY(mutex_) =
kint64max;
315 IntegerValue synchronized_inner_objective_lower_bound_
316 ABSL_GUARDED_BY(mutex_) = IntegerValue(
kint64min);
317 IntegerValue synchronized_inner_objective_upper_bound_
318 ABSL_GUARDED_BY(mutex_) = IntegerValue(
kint64max);
320 double primal_integral_ ABSL_GUARDED_BY(mutex_) = 0.0;
321 double last_primal_integral_time_stamp_ ABSL_GUARDED_BY(mutex_) = 0.0;
323 int next_callback_id_ ABSL_GUARDED_BY(mutex_) = 0;
324 std::vector<std::pair<
int, std::function<
void(const CpSolverResponse&)>>>
325 callbacks_ ABSL_GUARDED_BY(mutex_);
328 std::
string dump_prefix_;
340 void ReportPotentialNewBounds(
const CpModelProto&
model_proto,
341 const std::string& worker_name,
342 const std::vector<int>& variables,
343 const std::vector<int64>& new_lower_bounds,
344 const std::vector<int64>& new_upper_bounds);
353 void GetChangedBounds(
int id, std::vector<int>* variables,
354 std::vector<int64>* new_lower_bounds,
355 std::vector<int64>* new_upper_bounds);
362 const int num_variables_;
363 const CpModelProto& model_proto_;
368 std::vector<int64> lower_bounds_ ABSL_GUARDED_BY(mutex_);
369 std::vector<int64> upper_bounds_ ABSL_GUARDED_BY(mutex_);
371 ABSL_GUARDED_BY(mutex_);
374 std::vector<int64> synchronized_lower_bounds_ ABSL_GUARDED_BY(mutex_);
375 std::vector<int64> synchronized_upper_bounds_ ABSL_GUARDED_BY(mutex_);
376 std::deque<SparseBitset<int64>> id_to_changed_variables_
377 ABSL_GUARDED_BY(mutex_);
380 template <
typename ValueType>
382 absl::MutexLock mutex_lock(&mutex_);
383 return solutions_.size();
386 template <
typename ValueType>
389 absl::MutexLock mutex_lock(&mutex_);
390 return solutions_[i];
393 template <
typename ValueType>
395 int var_index,
int solution_index)
const {
396 absl::MutexLock mutex_lock(&mutex_);
397 return solutions_[solution_index].variable_values[var_index];
401 template <
typename ValueType>
405 absl::MutexLock mutex_lock(&mutex_);
406 const int64 best_rank = solutions_[0].rank;
415 const int kExplorationThreshold = 100;
418 tmp_indices_.clear();
419 for (
int i = 0; i < solutions_.size(); ++i) {
420 const auto& solution = solutions_[i];
421 if (solution.rank == best_rank &&
422 solution.num_selected <= kExplorationThreshold) {
423 tmp_indices_.push_back(i);
428 if (tmp_indices_.empty()) {
429 index = absl::Uniform<int>(*random, 0, solutions_.size());
431 index = tmp_indices_[absl::Uniform<int>(*random, 0, tmp_indices_.size())];
433 solutions_[
index].num_selected++;
434 return solutions_[
index];
437 template <
typename ValueType>
439 absl::MutexLock mutex_lock(&mutex_);
440 AddInternal(solution);
443 template <
typename ValueType>
446 int worse_solution_index = 0;
447 for (
int i = 0; i < new_solutions_.size(); ++i) {
449 if (new_solutions_[i] == solution)
return;
450 if (new_solutions_[worse_solution_index] < new_solutions_[i]) {
451 worse_solution_index = i;
454 if (new_solutions_.size() < num_solutions_to_keep_) {
455 new_solutions_.push_back(solution);
456 }
else if (solution < new_solutions_[worse_solution_index]) {
457 new_solutions_[worse_solution_index] = solution;
461 template <
typename ValueType>
463 absl::MutexLock mutex_lock(&mutex_);
464 solutions_.insert(solutions_.end(), new_solutions_.begin(),
465 new_solutions_.end());
466 new_solutions_.clear();
473 if (solutions_.size() > num_solutions_to_keep_) {
474 solutions_.resize(num_solutions_to_keep_);
476 num_synchronization_++;
482 #endif // OR_TOOLS_SAT_SYNCHRONIZATION_H_