14 #ifndef OR_TOOLS_SAT_SYNCHRONIZATION_H_
15 #define OR_TOOLS_SAT_SYNCHRONIZATION_H_
21 #include "absl/random/bit_gen_ref.h"
22 #include "absl/random/random.h"
23 #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);
238 IntegerValue lb, IntegerValue ub);
293 dump_prefix_ = dump_prefix;
297 void TestGapLimitsIfNeeded() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
298 void FillObjectiveValuesInBestResponse()
299 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
301 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
302 void UpdatePrimalIntegralInternal() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
304 const
bool log_updates_;
305 const
bool enumerate_all_solutions_;
306 const CpModelProto& model_proto_;
310 mutable
absl::Mutex mutex_;
313 double absolute_gap_limit_ ABSL_GUARDED_BY(mutex_) = 0.0;
314 double relative_gap_limit_ ABSL_GUARDED_BY(mutex_) = 0.0;
316 CpSolverResponse best_response_ ABSL_GUARDED_BY(mutex_);
319 int num_solutions_ ABSL_GUARDED_BY(mutex_) = 0;
320 int64 inner_objective_lower_bound_ ABSL_GUARDED_BY(mutex_) =
kint64min;
321 int64 inner_objective_upper_bound_ ABSL_GUARDED_BY(mutex_) =
kint64max;
322 int64 best_solution_objective_value_ ABSL_GUARDED_BY(mutex_) =
kint64max;
324 IntegerValue synchronized_inner_objective_lower_bound_
325 ABSL_GUARDED_BY(mutex_) = IntegerValue(
kint64min);
326 IntegerValue synchronized_inner_objective_upper_bound_
327 ABSL_GUARDED_BY(mutex_) = IntegerValue(
kint64max);
329 bool update_integral_on_each_change_ ABSL_GUARDED_BY(mutex_) = false;
330 double primal_integral_ ABSL_GUARDED_BY(mutex_) = 0.0;
331 double last_absolute_gap_ ABSL_GUARDED_BY(mutex_) = 0.0;
332 double last_primal_integral_time_stamp_ ABSL_GUARDED_BY(mutex_) = 0.0;
334 int next_callback_id_ ABSL_GUARDED_BY(mutex_) = 0;
335 std::vector<std::pair<
int, std::function<
void(const CpSolverResponse&)>>>
336 callbacks_ ABSL_GUARDED_BY(mutex_);
339 std::
string dump_prefix_;
351 void ReportPotentialNewBounds(
const CpModelProto&
model_proto,
352 const std::string& worker_name,
353 const std::vector<int>& variables,
354 const std::vector<int64>& new_lower_bounds,
355 const std::vector<int64>& new_upper_bounds);
364 void GetChangedBounds(
int id, std::vector<int>* variables,
365 std::vector<int64>* new_lower_bounds,
366 std::vector<int64>* new_upper_bounds);
373 const int num_variables_;
374 const CpModelProto& model_proto_;
379 std::vector<int64> lower_bounds_ ABSL_GUARDED_BY(mutex_);
380 std::vector<int64> upper_bounds_ ABSL_GUARDED_BY(mutex_);
382 ABSL_GUARDED_BY(mutex_);
385 std::vector<int64> synchronized_lower_bounds_ ABSL_GUARDED_BY(mutex_);
386 std::vector<int64> synchronized_upper_bounds_ ABSL_GUARDED_BY(mutex_);
387 std::deque<SparseBitset<int64>> id_to_changed_variables_
388 ABSL_GUARDED_BY(mutex_);
391 template <
typename ValueType>
393 absl::MutexLock mutex_lock(&mutex_);
394 return solutions_.size();
397 template <
typename ValueType>
400 absl::MutexLock mutex_lock(&mutex_);
401 return solutions_[i];
404 template <
typename ValueType>
406 int var_index,
int solution_index)
const {
407 absl::MutexLock mutex_lock(&mutex_);
408 return solutions_[solution_index].variable_values[var_index];
412 template <
typename ValueType>
415 absl::BitGenRef random)
const {
416 absl::MutexLock mutex_lock(&mutex_);
417 const int64 best_rank = solutions_[0].rank;
426 const int kExplorationThreshold = 100;
429 tmp_indices_.clear();
430 for (
int i = 0; i < solutions_.size(); ++i) {
431 const auto& solution = solutions_[i];
432 if (solution.rank == best_rank &&
433 solution.num_selected <= kExplorationThreshold) {
434 tmp_indices_.push_back(i);
439 if (tmp_indices_.empty()) {
440 index = absl::Uniform<int>(random, 0, solutions_.size());
442 index = tmp_indices_[absl::Uniform<int>(random, 0, tmp_indices_.size())];
444 solutions_[
index].num_selected++;
445 return solutions_[
index];
448 template <
typename ValueType>
450 absl::MutexLock mutex_lock(&mutex_);
451 AddInternal(solution);
454 template <
typename ValueType>
457 int worse_solution_index = 0;
458 for (
int i = 0; i < new_solutions_.size(); ++i) {
460 if (new_solutions_[i] == solution)
return;
461 if (new_solutions_[worse_solution_index] < new_solutions_[i]) {
462 worse_solution_index = i;
465 if (new_solutions_.size() < num_solutions_to_keep_) {
466 new_solutions_.push_back(solution);
467 }
else if (solution < new_solutions_[worse_solution_index]) {
468 new_solutions_[worse_solution_index] = solution;
472 template <
typename ValueType>
474 absl::MutexLock mutex_lock(&mutex_);
475 solutions_.insert(solutions_.end(), new_solutions_.begin(),
476 new_solutions_.end());
477 new_solutions_.clear();
484 if (solutions_.size() > num_solutions_to_keep_) {
485 solutions_.resize(num_solutions_to_keep_);
487 num_synchronization_++;
#define CHECK_GE(val1, val2)
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
CpSolverResponse GetResponse()
void SetStatsFromModel(Model *model)
SharedResponseManager(bool log_updates, bool enumerate_all_solutions, const CpModelProto *proto, const WallTimer *wall_timer, SharedTimeLimit *shared_time_limit)
double PrimalIntegral() const
const SharedSolutionRepository< int64 > & SolutionsRepository() const
SharedSolutionRepository< int64 > * MutableSolutionsRepository()
void set_dump_prefix(const std::string &dump_prefix)
void UpdatePrimalIntegral()
IntegerValue GetInnerObjectiveUpperBound()
IntegerValue SynchronizedInnerObjectiveUpperBound()
IntegerValue SynchronizedInnerObjectiveLowerBound()
void UpdateInnerObjectiveBounds(const std::string &worker_info, IntegerValue lb, IntegerValue ub)
void NewSolution(const CpSolverResponse &response, Model *model)
void NotifyThatImprovingProblemIsInfeasible(const std::string &worker_info)
IntegerValue BestSolutionInnerObjectiveValue()
void AddUnsatCore(const std::vector< int > &core)
void SetGapLimitsFromParameters(const SatParameters ¶meters)
int AddSolutionCallback(std::function< void(const CpSolverResponse &)> callback)
void SetUpdatePrimalIntegralOnEachChange(bool set)
void LoadDebugSolution(Model *)
IntegerValue GetInnerObjectiveLowerBound()
void UnregisterCallback(int callback_id)
void Add(const Solution &solution)
Solution GetRandomBiasedSolution(absl::BitGenRef random) const
std::vector< int > tmp_indices_ ABSL_GUARDED_BY(mutex_)
SharedSolutionRepository(int num_solutions_to_keep)
int64 num_synchronization_ ABSL_GUARDED_BY(mutex_)=0
Solution GetSolution(int index) const
const int num_solutions_to_keep_
std::vector< Solution > new_solutions_ ABSL_GUARDED_BY(mutex_)
void AddInternal(const Solution &solution) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_)
ValueType GetVariableValueInSolution(int var_index, int solution_index) const
std::vector< Solution > solutions_ ABSL_GUARDED_BY(mutex_)
CpModelProto const * model_proto
SharedResponseManager * response
static const int64 kint64max
static const int64 kint64min
void STLStableSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
bool operator<(const Solution &other) const
std::vector< ValueType > variable_values
bool operator==(const Solution &other) const