14#ifndef OR_TOOLS_SAT_SYNCHRONIZATION_H_
15#define OR_TOOLS_SAT_SYNCHRONIZATION_H_
23#include "absl/random/bit_gen_ref.h"
24#include "absl/random/random.h"
25#include "absl/synchronization/mutex.h"
46template <
typename ValueType>
102 void Add(
const Solution& solution);
115 ABSL_EXCLUSIVE_LOCKS_REQUIRED(
mutex_);
164 std::vector<std::vector<double>> solutions_;
165 mutable absl::Mutex mutex_;
203 std::function<
void(std::vector<int64_t>*)> postprocessor);
270 IntegerValue lb, IntegerValue ub);
324 dump_prefix_ = dump_prefix;
337 absl::MutexLock mutex_lock(&mutex_);
338 return &best_response_;
342 void TestGapLimitsIfNeeded() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
343 void FillObjectiveValuesInBestResponse()
344 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
346 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
347 void UpdateGapIntegralInternal() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
349 void RegisterSolutionFound(const
std::
string& improvement_info)
350 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
351 void RegisterObjectiveBoundImprovement(const
std::
string& improvement_info)
352 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
355 CpSolverResponse GetResponseInternal() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
362 mutable
absl::Mutex mutex_;
365 double absolute_gap_limit_ ABSL_GUARDED_BY(mutex_) = 0.0;
366 double relative_gap_limit_ ABSL_GUARDED_BY(mutex_) = 0.0;
371 int num_solutions_ ABSL_GUARDED_BY(mutex_) = 0;
372 int64_t inner_objective_lower_bound_ ABSL_GUARDED_BY(mutex_) =
373 std::numeric_limits<int64_t>::
min();
374 int64_t inner_objective_upper_bound_ ABSL_GUARDED_BY(mutex_) =
375 std::numeric_limits<int64_t>::
max();
376 int64_t best_solution_objective_value_ ABSL_GUARDED_BY(mutex_) =
377 std::numeric_limits<int64_t>::
max();
379 IntegerValue synchronized_inner_objective_lower_bound_ ABSL_GUARDED_BY(
380 mutex_) = IntegerValue(
std::numeric_limits<int64_t>::
min());
381 IntegerValue synchronized_inner_objective_upper_bound_ ABSL_GUARDED_BY(
382 mutex_) = IntegerValue(
std::numeric_limits<int64_t>::
max());
384 bool update_integral_on_each_change_ ABSL_GUARDED_BY(mutex_) = false;
385 double gap_integral_ ABSL_GUARDED_BY(mutex_) = 0.0;
386 double last_absolute_gap_ ABSL_GUARDED_BY(mutex_) = 0.0;
387 double last_gap_integral_time_stamp_ ABSL_GUARDED_BY(mutex_) = 0.0;
389 int next_callback_id_ ABSL_GUARDED_BY(mutex_) = 0;
391 callbacks_ ABSL_GUARDED_BY(mutex_);
393 std::vector<
std::function<
void(
std::vector<int64_t>*)>>
394 solution_postprocessors_ ABSL_GUARDED_BY(mutex_);
396 ABSL_GUARDED_BY(mutex_);
398 ABSL_GUARDED_BY(mutex_);
401 std::
string dump_prefix_;
404 std::map<
std::
string,
int> primal_improvements_count_ ABSL_GUARDED_BY(mutex_);
405 std::map<
std::
string,
int> dual_improvements_count_ ABSL_GUARDED_BY(mutex_);
420 const std::string& worker_name,
421 const std::vector<int>& variables,
422 const std::vector<int64_t>& new_lower_bounds,
423 const std::vector<int64_t>& new_upper_bounds);
431 void FixVariablesFromPartialSolution(
432 const std::vector<int64_t>& solution,
433 const std::vector<int>& variables_to_fix);
442 void GetChangedBounds(
int id, std::vector<int>* variables,
443 std::vector<int64_t>* new_lower_bounds,
444 std::vector<int64_t>* new_upper_bounds);
451 const int num_variables_;
457 std::vector<int64_t> lower_bounds_ ABSL_GUARDED_BY(mutex_);
458 std::vector<int64_t> upper_bounds_ ABSL_GUARDED_BY(mutex_);
460 ABSL_GUARDED_BY(mutex_);
463 std::vector<int64_t> synchronized_lower_bounds_ ABSL_GUARDED_BY(mutex_);
464 std::vector<int64_t> synchronized_upper_bounds_ ABSL_GUARDED_BY(mutex_);
465 std::deque<SparseBitset<int64_t>> id_to_changed_variables_
466 ABSL_GUARDED_BY(mutex_);
469template <
typename ValueType>
471 absl::MutexLock mutex_lock(&mutex_);
472 return solutions_.size();
475template <
typename ValueType>
478 absl::MutexLock mutex_lock(&mutex_);
479 return solutions_[i];
482template <
typename ValueType>
484 int var_index,
int solution_index)
const {
485 absl::MutexLock mutex_lock(&mutex_);
486 return solutions_[solution_index].variable_values[var_index];
490template <
typename ValueType>
493 absl::BitGenRef random)
const {
494 absl::MutexLock mutex_lock(&mutex_);
495 const int64_t best_rank = solutions_[0].rank;
504 const int kExplorationThreshold = 100;
507 tmp_indices_.clear();
508 for (
int i = 0; i < solutions_.size(); ++i) {
509 const auto& solution = solutions_[i];
510 if (solution.rank == best_rank &&
511 solution.num_selected <= kExplorationThreshold) {
512 tmp_indices_.push_back(i);
517 if (tmp_indices_.empty()) {
518 index = absl::Uniform<int>(random, 0, solutions_.size());
520 index = tmp_indices_[absl::Uniform<int>(random, 0, tmp_indices_.size())];
522 solutions_[
index].num_selected++;
523 return solutions_[
index];
526template <
typename ValueType>
528 if (num_solutions_to_keep_ == 0)
return;
529 absl::MutexLock mutex_lock(&mutex_);
530 AddInternal(solution);
533template <
typename ValueType>
536 int worse_solution_index = 0;
537 for (
int i = 0; i < new_solutions_.size(); ++i) {
539 if (new_solutions_[i] == solution)
return;
540 if (new_solutions_[worse_solution_index] < new_solutions_[i]) {
541 worse_solution_index = i;
544 if (new_solutions_.size() < num_solutions_to_keep_) {
545 new_solutions_.push_back(solution);
546 }
else if (solution < new_solutions_[worse_solution_index]) {
547 new_solutions_[worse_solution_index] = solution;
551template <
typename ValueType>
553 absl::MutexLock mutex_lock(&mutex_);
554 if (new_solutions_.empty())
return;
556 solutions_.insert(solutions_.end(), new_solutions_.begin(),
557 new_solutions_.end());
558 new_solutions_.clear();
565 if (solutions_.size() > num_solutions_to_keep_) {
566 solutions_.resize(num_solutions_to_keep_);
569 if (!solutions_.empty()) {
570 VLOG(2) <<
"Solution pool update:"
571 <<
" num_solutions=" << solutions_.size()
572 <<
" min_rank=" << solutions_[0].rank
573 <<
" max_rank=" << solutions_.back().rank;
576 num_synchronization_++;
#define CHECK_GE(val1, val2)
#define VLOG(verboselevel)
Class that owns everything related to a particular optimization model.
void AddNewSolution(const std::vector< double > &lp_solution)
std::vector< double > GetNewSolution()
bool HasNewSolution() const
SharedLPSolutionRepository(int num_solutions_to_keep)
void NewLPSolution(std::vector< double > lp_solution)
SharedRelaxationSolutionRepository(int num_solutions_to_keep)
void NewRelaxationSolution(const CpSolverResponse &response)
bool ProblemIsSolved() const
void InitializeObjective(const CpModelProto &cp_model)
void SetStatsFromModel(Model *model)
CpSolverResponse GetResponse(bool full_response=true)
void AddSolutionPostprocessor(std::function< void(std::vector< int64_t > *)> postprocessor)
SharedSolutionRepository< int64_t > * MutableSolutionsRepository()
void AddFinalResponsePostprocessor(std::function< void(CpSolverResponse *)> postprocessor)
void set_dump_prefix(const std::string &dump_prefix)
IntegerValue GetInnerObjectiveUpperBound()
IntegerValue SynchronizedInnerObjectiveUpperBound()
IntegerValue SynchronizedInnerObjectiveLowerBound()
void NewSolution(const CpSolverResponse &response, Model *model)
void DisplayImprovementStatistics()
double GapIntegral() const
void NotifyThatImprovingProblemIsInfeasible(const std::string &worker_info)
void SetUpdateGapIntegralOnEachChange(bool set)
IntegerValue BestSolutionInnerObjectiveValue()
void AddUnsatCore(const std::vector< int > &core)
void SetGapLimitsFromParameters(const SatParameters ¶meters)
const SharedSolutionRepository< int64_t > & SolutionsRepository() const
CpSolverResponse * MutableResponse()
void LogMessage(std::string message)
void AddResponsePostprocessor(std::function< void(CpSolverResponse *)> postprocessor)
int AddSolutionCallback(std::function< void(const CpSolverResponse &)> callback)
void LoadDebugSolution(Model *)
IntegerValue GetInnerObjectiveLowerBound()
void UnregisterCallback(int callback_id)
SharedResponseManager(Model *model)
void UpdateInnerObjectiveBounds(const std::string &update_info, IntegerValue lb, IntegerValue ub)
void Add(const Solution &solution)
std::vector< Solution > new_solutions_ ABSL_GUARDED_BY(mutex_)
Solution GetRandomBiasedSolution(absl::BitGenRef random) const
SharedSolutionRepository(int num_solutions_to_keep)
Solution GetSolution(int index) const
const int num_solutions_to_keep_
std::vector< int > tmp_indices_ ABSL_GUARDED_BY(mutex_)
std::vector< Solution > solutions_ ABSL_GUARDED_BY(mutex_)
int64_t num_synchronization_ ABSL_GUARDED_BY(mutex_)=0
void AddInternal(const Solution &solution) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_)
ValueType GetVariableValueInSolution(int var_index, int solution_index) const
CpModelProto const * model_proto
SharedResponseManager * response
void STLStableSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
Collection of objects used to extend the Constraint Solver library.
bool operator<(const Solution &other) const
std::vector< ValueType > variable_values
bool operator==(const Solution &other) const