27#ifndef OR_TOOLS_BOP_BOP_LS_H_
28#define OR_TOOLS_BOP_BOP_LS_H_
38#include "absl/container/flat_hash_map.h"
39#include "absl/container/flat_hash_set.h"
40#include "absl/random/bit_gen_ref.h"
41#include "absl/random/random.h"
42#include "absl/strings/string_view.h"
43#include "absl/types/span.h"
47#include "ortools/bop/bop_parameters.pb.h"
50#include "ortools/sat/boolean_problem.pb.h"
97 std::vector<sat::Literal>* propagated_literals);
118class LocalSearchAssignmentIterator;
137 bool ShouldBeRun(
const ProblemState& problem_state)
const override;
142 int64_t state_update_stamp_;
147 const int max_num_decisions_;
156 std::unique_ptr<LocalSearchAssignmentIterator> assignment_iterator_;
159 absl::BitGenRef random_;
174template <
typename IntType>
187 void ChangeState(IntType i,
bool should_be_inside);
191 int size()
const {
return size_; }
194 const std::vector<IntType>&
Superset()
const {
return stack_; }
207 std::vector<IntType> stack_;
208 std::vector<bool> in_stack_;
212 std::vector<int> saved_sizes_;
213 std::vector<int> saved_stack_sizes_;
218template <
typename IntType>
226 for (IntType i(0); i <
size; ++i) {
227 hashes_[i] = absl::Uniform<uint64_t>(random_);
238 uint64_t
Hash(
const std::vector<IntType>& set)
const {
240 for (
const IntType i : set)
hash ^= hashes_[i];
246 uint64_t
Hash(IntType e)
const {
return hashes_[e]; }
252 absl::BitGenRef random_;
286 const sat::LinearBooleanProblem& problem, absl::BitGenRef random);
312 void Assign(absl::Span<const sat::Literal> literals);
336 bool IsFeasible()
const {
return infeasible_constraint_set_.
size() == 0; }
342 return infeasible_constraint_set_.
size();
347 return infeasible_constraint_set_.
Superset();
352 size_t NumConstraints()
const {
return constraint_lower_bounds_.size(); }
365 return constraint_lower_bounds_[constraint];
370 return constraint_upper_bounds_[constraint];
377 return constraint_values_[constraint];
391 void InitializeConstraintSetHasher();
399 ConstraintIndexWithDirection FromConstraintIndex(ConstraintIndex
index,
401 return ConstraintIndexWithDirection(2 *
index.value() + (up ? 1 : 0));
406 void MakeObjectiveConstraintInfeasible(
int delta);
410 struct ConstraintEntry {
411 ConstraintEntry(ConstraintIndex c, int64_t
w) : constraint(c), weight(
w) {}
412 ConstraintIndex constraint;
422 BopSolution assignment_;
423 BopSolution reference_;
426 BacktrackableIntegerSet<ConstraintIndex> infeasible_constraint_set_;
431 std::vector<int> flipped_var_trail_backtrack_levels_;
432 std::vector<VariableIndex> flipped_var_trail_;
435 std::vector<sat::Literal> tmp_potential_repairs_;
436 NonOrderedSetHasher<ConstraintIndexWithDirection> constraint_set_hasher_;
437 absl::flat_hash_map<uint64_t, std::vector<sat::Literal>>
438 hash_to_potential_repairs_;
453class OneFlipConstraintRepairer {
462 const sat::LinearBooleanProblem& problem,
493 TermIndex init_term_index,
494 TermIndex start_term_index)
const;
515 void SortTermsOfEachConstraints(
int num_variables);
519 by_constraint_matrix_;
532 int max_num_decisions,
533 int max_num_broken_constraints,
534 absl::BitGenRef random,
547 use_potential_one_flip_repairs_ = v;
571 return better_solution_has_been_found_;
584 void UseCurrentStateAsReference();
587 static constexpr size_t kStoredMaxDecisions = 4;
595 SearchNode(ConstraintIndex c, TermIndex t) : constraint(c), term_index(t) {}
596 ConstraintIndex constraint;
597 TermIndex term_index;
601 void ApplyDecision(sat::Literal
literal);
612 bool NewStateIsInTranspositionTable(sat::Literal l);
615 void InsertInTranspositionTable();
619 void InitializeTranspositionTableKey(
620 std::array<int32_t, kStoredMaxDecisions>*
a);
625 bool EnqueueNextRepairingTermIfAny(ConstraintIndex ct_to_repair,
628 const int max_num_decisions_;
629 const int max_num_broken_constraints_;
630 bool better_solution_has_been_found_;
631 AssignmentAndConstraintFeasibilityMaintainer maintainer_;
632 SatWrapper*
const sat_wrapper_;
633 OneFlipConstraintRepairer repairer_;
634 std::vector<SearchNode> search_nodes_;
638 std::vector<sat::Literal> tmp_propagated_literals_;
653 bool use_transposition_table_;
654 absl::flat_hash_set<std::array<int32_t, kStoredMaxDecisions>>
655 transposition_table_;
657 bool use_potential_one_flip_repairs_;
663 int64_t num_skipped_nodes_;
667 int64_t num_improvements_;
668 int64_t num_improvements_by_one_flip_repairs_;
669 int64_t num_inspected_one_flip_repairs_;
void SetReferenceSolution(const BopSolution &reference_solution)
int64_t ConstraintUpperBound(ConstraintIndex constraint) const
Returns the upper bound of the constraint.
void Assign(absl::Span< const sat::Literal > literals)
void AddBacktrackingLevel()
bool Assignment(VariableIndex var) const
int64_t ConstraintValue(ConstraintIndex constraint) const
AssignmentAndConstraintFeasibilityMaintainer & operator=(const AssignmentAndConstraintFeasibilityMaintainer &)=delete
void UseCurrentStateAsReference()
std::string DebugString() const
const BopSolution & reference() const
Returns the current assignment.
const std::vector< ConstraintIndex > & PossiblyInfeasibleConstraints() const
Returns a superset of all the infeasible constraints in the current state.
int64_t ConstraintLowerBound(ConstraintIndex constraint) const
Returns the lower bound of the constraint.
static const ConstraintIndex kObjectiveConstraint
const std::vector< sat::Literal > & PotentialOneFlipRepairs()
int NumInfeasibleConstraints() const
AssignmentAndConstraintFeasibilityMaintainer(const sat::LinearBooleanProblem &problem, absl::BitGenRef random)
bool ConstraintIsFeasible(ConstraintIndex constraint) const
Returns true if the given constraint is currently feasible.
bool IsFeasible() const
Returns true if there is no infeasible constraint in the current state.
size_t NumConstraints() const
BacktrackableIntegerSet()=default
void AddBacktrackingLevel()
void ChangeState(IntType i, bool should_be_inside)
void ClearAndResize(IntType n)
const std::vector< IntType > & Superset() const
Returns a superset of the current set of integers.
const std::string & name() const
Returns the name given at construction.
bool Value(VariableIndex var) const
const BopSolution & LastReferenceAssignment() const
Returns the last feasible assignment.
~LocalSearchAssignmentIterator()
void UsePotentialOneFlipRepairs(bool v)
void UseTranspositionTable(bool v)
Parameters of the LS algorithm.
std::string DebugString() const
double deterministic_time() const
LocalSearchAssignmentIterator(const ProblemState &problem_state, int max_num_decisions, int max_num_broken_constraints, absl::BitGenRef random, SatWrapper *sat_wrapper)
bool BetterSolutionHasBeenFound() const
bool NextAssignment()
Move to the next assignment. Returns false when the search is finished.
void Synchronize(const ProblemState &problem_state)
void SynchronizeSatWrapper()
LocalSearchAssignmentIterator & operator=(const LocalSearchAssignmentIterator &)=delete
LocalSearchOptimizer(absl::string_view name, int max_num_decisions, absl::BitGenRef random, sat::SatSolver *sat_propagator)
~LocalSearchOptimizer() override
uint64_t Hash(const std::vector< IntType > &set) const
void IgnoreElement(IntType e)
bool IsInitialized() const
Returns true if Initialize() has been called with a non-zero size.
void Initialize(int size)
Initializes the NonOrderedSetHasher to hash sets of integer in [0, n).
NonOrderedSetHasher(absl::BitGenRef random)
OneFlipConstraintRepairer(const sat::LinearBooleanProblem &problem, const AssignmentAndConstraintFeasibilityMaintainer &maintainer, const sat::VariablesAssignment &sat_assignment)
static const ConstraintIndex kInvalidConstraint
bool RepairIsValid(ConstraintIndex ct_index, TermIndex term_index) const
static const TermIndex kInitTerm
ConstraintIndex ConstraintToRepair() const
OneFlipConstraintRepairer & operator=(const OneFlipConstraintRepairer &)=delete
TermIndex NextRepairingTerm(ConstraintIndex ct_index, TermIndex init_term_index, TermIndex start_term_index) const
sat::Literal GetFlip(ConstraintIndex ct_index, TermIndex term_index) const
static const TermIndex kInvalidTerm
int ApplyDecision(sat::Literal decision_literal, std::vector< sat::Literal > *propagated_literals)
void ExtractLearnedInfo(LearnedInfo *info)
Extracts any new information learned during the search.
const sat::VariablesAssignment & SatAssignment() const
Return the current solver VariablesAssignment.
SatWrapper(const SatWrapper &)=delete
This type is neither copyable nor movable.
SatWrapper(sat::SatSolver *sat_solver)
bool IsModelUnsat() const
SatWrapper & operator=(const SatWrapper &)=delete
void BacktrackOneLevel()
Backtracks the last decision if any.
double deterministic_time() const
void BacktrackAll()
Bactracks all the decisions.
std::vector< sat::Literal > FullSatTrail() const
Returns the current state of the solver propagation trail.
bool IsModelUnsat() const
const VariablesAssignment & Assignment() const
void resize(size_type new_size)
In SWIG mode, we don't want anything besides these top-level includes.
trees with all degrees equal w the current value of w
#define DEFINE_STRONG_INDEX_TYPE(index_type_name)
ConstraintTerm(VariableIndex v, int64_t w)