OR-Tools  9.3
bop_ls.h
Go to the documentation of this file.
1// Copyright 2010-2021 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// This file defines the needed classes to efficiently perform Local Search in
15// Bop.
16// Local Search is a technique used to locally improve an existing solution by
17// flipping a limited number of variables. To be successful the produced
18// solution has to satisfy all constraints of the problem and improve the
19// objective cost.
20//
21// The class BopLocalSearchOptimizer is the only public interface for Local
22// Search in Bop. For unit-testing purposes this file also contains the four
23// internal classes AssignmentAndConstraintFeasibilityMaintainer,
24// OneFlipConstraintRepairer, SatWrapper and LocalSearchAssignmentIterator.
25// They are implementation details and should not be used outside of bop_ls.
26
27#ifndef OR_TOOLS_BOP_BOP_LS_H_
28#define OR_TOOLS_BOP_BOP_LS_H_
29
30#include <array>
31#include <cstdint>
32#include <string>
33
34#include "absl/container/flat_hash_map.h"
35#include "absl/container/flat_hash_set.h"
36#include "absl/random/random.h"
37#include "ortools/base/hash.h"
42#include "ortools/sat/boolean_problem.pb.h"
45
46namespace operations_research {
47namespace bop {
48
49// This class is used to ease the connection with the SAT solver.
50//
51// TODO(user): remove? the meat of the logic is used in just one place, so I am
52// not sure having this extra layer improve the readability.
54 public:
55 explicit SatWrapper(sat::SatSolver* sat_solver);
56
57 // Returns the current state of the solver propagation trail.
58 std::vector<sat::Literal> FullSatTrail() const;
59
60 // Returns true if the problem is UNSAT.
61 // Note that an UNSAT problem might not be marked as UNSAT at first because
62 // the SAT solver is not able to prove it; After some decisions / learned
63 // conflicts, the SAT solver might be able to prove UNSAT and so this will
64 // return true.
65 bool IsModelUnsat() const { return sat_solver_->IsModelUnsat(); }
66
67 // Return the current solver VariablesAssignment.
69 return sat_solver_->Assignment();
70 }
71
72 // Applies the decision that makes the given literal true and returns the
73 // number of decisions to backtrack due to conflicts if any.
74 // Two cases:
75 // - No conflicts: Returns 0 and fills the propagated_literals with the
76 // literals that have been propagated due to the decision including the
77 // the decision itself.
78 // - Conflicts: Returns the number of decisions to backtrack (the current
79 // decision included, i.e. returned value > 0) and fills the
80 // propagated_literals with the literals that the conflicts propagated.
81 // Note that the decision variable should not be already assigned in SAT.
82 int ApplyDecision(sat::Literal decision_literal,
83 std::vector<sat::Literal>* propagated_literals);
84
85 // Backtracks the last decision if any.
86 void BacktrackOneLevel();
87
88 // Bactracks all the decisions.
89 void BacktrackAll();
90
91 // Extracts any new information learned during the search.
93
94 // Returns a deterministic number that should be correlated with the time
95 // spent in the SAT wrapper. The order of magnitude should be close to the
96 // time in seconds.
97 double deterministic_time() const;
98
99 private:
100 sat::SatSolver* sat_solver_;
101 DISALLOW_COPY_AND_ASSIGN(SatWrapper);
102};
103
104// Forward declaration.
105class LocalSearchAssignmentIterator;
106
107// This class defines a Local Search optimizer. The goal is to find a new
108// solution with a better cost than the given solution by iterating on all
109// assignments that can be reached in max_num_decisions decisions or less.
110// The bop parameter max_number_of_explored_assignments_per_try_in_ls can be
111// used to specify the number of new assignments to iterate on each time the
112// method Optimize() is called. Limiting that parameter allows to reduce the
113// time spent in the Optimize() method at once, and still explore all the
114// reachable assignments (if Optimize() is called enough times).
115// Note that due to propagation, the number of variables with a different value
116// in the new solution can be greater than max_num_decisions.
118 public:
119 LocalSearchOptimizer(const std::string& name, int max_num_decisions,
120 absl::BitGenRef random, sat::SatSolver* sat_propagator);
121 ~LocalSearchOptimizer() override;
122
123 private:
124 bool ShouldBeRun(const ProblemState& problem_state) const override;
125 Status Optimize(const BopParameters& parameters,
126 const ProblemState& problem_state, LearnedInfo* learned_info,
127 TimeLimit* time_limit) override;
128
129 int64_t state_update_stamp_;
130
131 // Maximum number of decisions the Local Search can take.
132 // Note that there is no limit on the number of changed variables due to
133 // propagation.
134 const int max_num_decisions_;
135
136 // A wrapper around the given sat_propagator.
137 SatWrapper sat_wrapper_;
138
139 // Iterator on all reachable assignments.
140 // Note that this iterator is only reset when Synchronize() is called, i.e.
141 // the iterator continues its iteration of the next assignments each time
142 // Optimize() is called until everything is explored or a solution is found.
143 std::unique_ptr<LocalSearchAssignmentIterator> assignment_iterator_;
144
145 // Random generator.
146 absl::BitGenRef random_;
147};
148
149//------------------------------------------------------------------------------
150// Implementation details. The declarations of those utility classes are in
151// the .h for testing reasons.
152//------------------------------------------------------------------------------
153
154// Maintains some information on a sparse set of integers in [0, n). More
155// specifically this class:
156// - Allows to dynamically add/remove element from the set.
157// - Has a backtracking support.
158// - Maintains the number of elements in the set.
159// - Maintains a superset of the elements of the set that contains all the
160// modified elements.
161template <typename IntType>
163 public:
165
166 // Prepares the class for integers in [0, n) and initializes the set to the
167 // empty one. Note that this run in O(n). Once resized, it is better to call
168 // BacktrackAll() instead of this to clear the set.
169 void ClearAndResize(IntType n);
170
171 // Changes the state of the given integer i to be either inside or outside the
172 // set. Important: this should only be called with the opposite state of the
173 // current one, otherwise size() will not be correct.
174 void ChangeState(IntType i, bool should_be_inside);
175
176 // Returns the current number of elements in the set.
177 // Note that this is not its maximum size n.
178 int size() const { return size_; }
179
180 // Returns a superset of the current set of integers.
181 const std::vector<IntType>& Superset() const { return stack_; }
182
183 // BacktrackOneLevel() backtracks to the state the class was in when the
184 // last AddBacktrackingLevel() was called. BacktrackAll() just restore the
185 // class to its state just after the last ClearAndResize().
187 void BacktrackOneLevel();
188 void BacktrackAll();
189
190 private:
191 int size_;
192
193 // Contains the elements whose status has been changed at least once.
194 std::vector<IntType> stack_;
195 std::vector<bool> in_stack_;
196
197 // Used for backtracking. Contains the size_ and the stack_.size() at the time
198 // of each call to AddBacktrackingLevel() that is not yet backtracked over.
199 std::vector<int> saved_sizes_;
200 std::vector<int> saved_stack_sizes_;
201};
202
203// A simple and efficient class to hash a given set of integers in [0, n).
204// It uses O(n) memory and produces a good hash (random linear function).
205template <typename IntType>
207 public:
208 explicit NonOrderedSetHasher(absl::BitGenRef random) : random_(random) {}
209
210 // Initializes the NonOrderedSetHasher to hash sets of integer in [0, n).
211 void Initialize(int size) {
212 hashes_.resize(size);
213 for (IntType i(0); i < size; ++i) {
214 hashes_[i] = absl::Uniform<uint64_t>(random_);
215 }
216 }
217
218 // Ignores the given set element in all subsequent hash computation. Note that
219 // this will be reset by the next call to Initialize().
220 void IgnoreElement(IntType e) { hashes_[e] = 0; }
221
222 // Returns the hash of the given set. The hash is independent of the set
223 // order, but there must be no duplicate element in the set. This uses a
224 // simple random linear function which has really good hashing properties.
225 uint64_t Hash(const std::vector<IntType>& set) const {
226 uint64_t hash = 0;
227 for (const IntType i : set) hash ^= hashes_[i];
228 return hash;
229 }
230
231 // The hash of a set is simply the XOR of all its elements. This allows
232 // to compute an hash incrementally or without the need of a vector<>.
233 uint64_t Hash(IntType e) const { return hashes_[e]; }
234
235 // Returns true if Initialize() has been called with a non-zero size.
236 bool IsInitialized() const { return !hashes_.empty(); }
237
238 private:
239 absl::BitGenRef random_;
241};
242
243// This class is used to incrementally maintain an assignment and the
244// feasibility of the constraints of a given LinearBooleanProblem.
245//
246// The current assignment is initialized using a feasible reference solution,
247// i.e. the reference solution satisfies all the constraints of the problem.
248// The current assignment is updated using the Assign() method.
249//
250// Note that the current assignment is not a solution in the sense that it
251// might not be feasible, ie. violates some constraints.
252//
253// The assignment can be accessed at any time using Assignment().
254// The set of infeasible constraints can be accessed at any time using
255// PossiblyInfeasibleConstraints().
256//
257// Note that this class is reversible, i.e. it is possible to backtrack to
258// previously added backtracking levels.
259// levels. Consider for instance variable a, b, c, and d.
260// Method called Assigned after method call
261// 1- Assign({a, b}) a b
262// 2- AddBacktrackingLevel() a b |
263// 3- Assign({c}) a b | c
264// 4- Assign({d}) a b | c d
265// 5- BacktrackOneLevel() a b
266// 6- Assign({c}) a b c
267// 7- BacktrackOneLevel()
269 public:
270 // Note that the constraint indices used in this class are not the same as
271 // the one used in the given LinearBooleanProblem here.
273 const sat::LinearBooleanProblem& problem, absl::BitGenRef random);
274
275 // When we construct the problem, we treat the objective as one constraint.
276 // This is the index of this special "objective" constraint.
277 static const ConstraintIndex kObjectiveConstraint;
278
279 // Sets a new reference solution and reverts all internal structures to their
280 // initial state. Note that the reference solution has to be feasible.
281 void SetReferenceSolution(const BopSolution& reference_solution);
282
283 // Behaves exactly like SetReferenceSolution() where the passed reference
284 // is the current assignment held by this class. Note that the current
285 // assignment must be feasible (i.e. IsFeasible() is true).
287
288 // Assigns all literals. That updates the assignment, the constraint values,
289 // and the infeasible constraints.
290 // Note that the assignment of those literals can be reverted thanks to
291 // AddBacktrackingLevel() and BacktrackOneLevel().
292 // Note that a variable can't be assigned twice, even for the same literal.
293 void Assign(const std::vector<sat::Literal>& literals);
294
295 // Adds a new backtracking level to specify the state that will be restored
296 // by BacktrackOneLevel().
297 // See the example in the class comment.
299
300 // Backtracks internal structures to the previous level defined by
301 // AddBacktrackingLevel(). As a consequence the state will be exactly as
302 // before the previous call to AddBacktrackingLevel().
303 // Note that backtracking the initial state has no effect.
304 void BacktrackOneLevel();
305 void BacktrackAll();
306
307 // This returns the list of literal that appear in exactly all the current
308 // infeasible constraints (ignoring the objective) and correspond to a flip in
309 // a good direction for all the infeasible constraint. Performing this flip
310 // may repair the problem without any propagations.
311 //
312 // Important: The returned reference is only valid until the next
313 // PotentialOneFlipRepairs() call.
314 const std::vector<sat::Literal>& PotentialOneFlipRepairs();
315
316 // Returns true if there is no infeasible constraint in the current state.
317 bool IsFeasible() const { return infeasible_constraint_set_.size() == 0; }
318
319 // Returns the *exact* number of infeasible constraints.
320 // Note that PossiblyInfeasibleConstraints() will potentially return a larger
321 // number of constraints.
323 return infeasible_constraint_set_.size();
324 }
325
326 // Returns a superset of all the infeasible constraints in the current state.
327 const std::vector<ConstraintIndex>& PossiblyInfeasibleConstraints() const {
328 return infeasible_constraint_set_.Superset();
329 }
330
331 // Returns the number of constraints of the problem, objective included,
332 // i.e. the number of constraint in the problem + 1.
333 size_t NumConstraints() const { return constraint_lower_bounds_.size(); }
334
335 // Returns the value of the var in the assignment.
336 // As the assignment is initialized with the reference solution, if the
337 // variable has not been assigned through Assign(), the returned value is
338 // the value of the variable in the reference solution.
339 bool Assignment(VariableIndex var) const { return assignment_.Value(var); }
340
341 // Returns the current assignment.
342 const BopSolution& reference() const { return reference_; }
343
344 // Returns the lower bound of the constraint.
345 int64_t ConstraintLowerBound(ConstraintIndex constraint) const {
346 return constraint_lower_bounds_[constraint];
347 }
348
349 // Returns the upper bound of the constraint.
350 int64_t ConstraintUpperBound(ConstraintIndex constraint) const {
351 return constraint_upper_bounds_[constraint];
352 }
353
354 // Returns the value of the constraint. The value is computed using the
355 // variable values in the assignment. Note that a constraint is feasible iff
356 // its value is between its two bounds (inclusive).
357 int64_t ConstraintValue(ConstraintIndex constraint) const {
358 return constraint_values_[constraint];
359 }
360
361 // Returns true if the given constraint is currently feasible.
362 bool ConstraintIsFeasible(ConstraintIndex constraint) const {
363 const int64_t value = ConstraintValue(constraint);
364 return value >= ConstraintLowerBound(constraint) &&
365 value <= ConstraintUpperBound(constraint);
366 }
367
368 std::string DebugString() const;
369
370 private:
371 // This is lazily called by PotentialOneFlipRepairs() once.
372 void InitializeConstraintSetHasher();
373
374 // This is used by PotentialOneFlipRepairs(). It encodes a ConstraintIndex
375 // together with a "repair" direction depending on the bound that make a
376 // constraint infeasible. An "up" direction means that the constraint activity
377 // is lower than the lower bound and we need to make the activity move up to
378 // fix the infeasibility.
379 DEFINE_STRONG_INDEX_TYPE(ConstraintIndexWithDirection);
380 ConstraintIndexWithDirection FromConstraintIndex(ConstraintIndex index,
381 bool up) const {
382 return ConstraintIndexWithDirection(2 * index.value() + (up ? 1 : 0));
383 }
384
385 // Over constrains the objective cost by the given delta. This should only be
386 // called on a feasible reference solution and a fully backtracked state.
387 void MakeObjectiveConstraintInfeasible(int delta);
388
389 // Local structure to represent the sparse matrix by variable used for fast
390 // update of the constraint values.
391 struct ConstraintEntry {
392 ConstraintEntry(ConstraintIndex c, int64_t w) : constraint(c), weight(w) {}
393 ConstraintIndex constraint;
394 int64_t weight;
395 };
396
397 absl::StrongVector<VariableIndex,
399 by_variable_matrix_;
400 absl::StrongVector<ConstraintIndex, int64_t> constraint_lower_bounds_;
401 absl::StrongVector<ConstraintIndex, int64_t> constraint_upper_bounds_;
402
403 BopSolution assignment_;
404 BopSolution reference_;
405
407 BacktrackableIntegerSet<ConstraintIndex> infeasible_constraint_set_;
408
409 // This contains the list of variable flipped in assignment_.
410 // flipped_var_trail_backtrack_levels_[i-1] is the index in flipped_var_trail_
411 // of the first variable flipped after the i-th AddBacktrackingLevel() call.
412 std::vector<int> flipped_var_trail_backtrack_levels_;
413 std::vector<VariableIndex> flipped_var_trail_;
414
415 // Members used by PotentialOneFlipRepairs().
416 std::vector<sat::Literal> tmp_potential_repairs_;
417 NonOrderedSetHasher<ConstraintIndexWithDirection> constraint_set_hasher_;
418 absl::flat_hash_map<uint64_t, std::vector<sat::Literal>>
419 hash_to_potential_repairs_;
420
421 DISALLOW_COPY_AND_ASSIGN(AssignmentAndConstraintFeasibilityMaintainer);
422};
423
424// This class is an utility class used to select which infeasible constraint to
425// repair and identify one variable to flip to actually repair the constraint.
426// A constraint 'lb <= sum_i(w_i * x_i) <= ub', with 'lb' the lower bound,
427// 'ub' the upper bound, 'w_i' the weight of the i-th term and 'x_i' the
428// boolean variable appearing in the i-th term, is infeasible for a given
429// assignment iff its value 'sum_i(w_i * x_i)' is outside of the bounds.
430// Repairing-a-constraint-in-one-flip means making the constraint feasible by
431// just flipping the value of one unassigned variable of the current assignment
432// from the AssignmentAndConstraintFeasibilityMaintainer.
433// For performance reasons, the pairs weight / variable (w_i, x_i) are stored
434// in a sparse manner as a vector of terms (w_i, x_i). In the following the
435// TermIndex term_index refers to the position of the term in the vector.
437 public:
438 // Note that the constraint indices used in this class follow the same
439 // convention as the one used in the
440 // AssignmentAndConstraintFeasibilityMaintainer.
441 //
442 // TODO(user): maybe merge the two classes? maintaining this implicit indices
443 // convention between the two classes sounds like a bad idea.
445 const sat::LinearBooleanProblem& problem,
447 const sat::VariablesAssignment& sat_assignment);
448
449 static const ConstraintIndex kInvalidConstraint;
450 static const TermIndex kInitTerm;
451 static const TermIndex kInvalidTerm;
452
453 // Returns the index of a constraint to repair. This will always return the
454 // index of a constraint that can be repaired in one flip if there is one.
455 // Note however that if there is only one possible candidate, it will be
456 // returned without checking that it can indeed be repaired in one flip.
457 // This is because the later check can be expensive, and is not needed in our
458 // context.
459 ConstraintIndex ConstraintToRepair() const;
460
461 // Returns the index of the next term which repairs the constraint when the
462 // value of its variable is flipped. This method explores terms with an
463 // index strictly greater than start_term_index and then terms with an index
464 // smaller than or equal to init_term_index if any.
465 // Returns kInvalidTerm when no reparing terms are found.
466 //
467 // Note that if init_term_index == start_term_index, then all the terms will
468 // be explored. Both TermIndex arguments can take values in [-1, constraint
469 // size).
470 TermIndex NextRepairingTerm(ConstraintIndex ct_index,
471 TermIndex init_term_index,
472 TermIndex start_term_index) const;
473
474 // Returns true if the constraint is infeasible and if flipping the variable
475 // at the given index will repair it.
476 bool RepairIsValid(ConstraintIndex ct_index, TermIndex term_index) const;
477
478 // Returns the literal formed by the variable at the given constraint term and
479 // assigned to the opposite value of this variable in the current assignment.
480 sat::Literal GetFlip(ConstraintIndex ct_index, TermIndex term_index) const;
481
482 // Local structure to represent the sparse matrix by constraint used for fast
483 // lookups.
485 ConstraintTerm(VariableIndex v, int64_t w) : var(v), weight(w) {}
486 VariableIndex var;
487 int64_t weight;
488 };
489
490 private:
491 // Sorts the terms of each constraints in the by_constraint_matrix_ to iterate
492 // on most promising variables first.
493 void SortTermsOfEachConstraints(int num_variables);
494
495 absl::StrongVector<ConstraintIndex,
497 by_constraint_matrix_;
499 const sat::VariablesAssignment& sat_assignment_;
500
501 DISALLOW_COPY_AND_ASSIGN(OneFlipConstraintRepairer);
502};
503
504// This class is used to iterate on all assignments that can be obtained by
505// deliberately flipping 'n' variables from the reference solution, 'n' being
506// smaller than or equal to max_num_decisions.
507// Note that one deliberate variable flip may lead to many other flips due to
508// constraint propagation, those additional flips are not counted in 'n'.
510 public:
511 LocalSearchAssignmentIterator(const ProblemState& problem_state,
512 int max_num_decisions,
513 int max_num_broken_constraints,
514 absl::BitGenRef random,
515 SatWrapper* sat_wrapper);
517
518 // Parameters of the LS algorithm.
519 void UseTranspositionTable(bool v) { use_transposition_table_ = v; }
521 use_potential_one_flip_repairs_ = v;
522 }
523
524 // Synchronizes the iterator with the problem state, e.g. set fixed variables,
525 // set the reference solution. Call this only when a new solution has been
526 // found. This will restart the LS.
527 void Synchronize(const ProblemState& problem_state);
528
529 // Synchronize the SatWrapper with our current search state. This needs to be
530 // called before calls to NextAssignment() if the underlying SatWrapper was
531 // used by someone else than this class.
533
534 // Move to the next assignment. Returns false when the search is finished.
535 bool NextAssignment();
536
537 // Returns the last feasible assignment.
539 return maintainer_.reference();
540 }
541
542 // Returns true if the current assignment has a better solution than the one
543 // passed to the last Synchronize() call.
545 return better_solution_has_been_found_;
546 }
547
548 // Returns a deterministic number that should be correlated with the time
549 // spent in the iterator. The order of magnitude should be close to the time
550 // in seconds.
551 double deterministic_time() const;
552
553 std::string DebugString() const;
554
555 private:
556 // This is called when a better solution has been found to restore the search
557 // to the new "root" node.
558 void UseCurrentStateAsReference();
559
560 // See transposition_table_ below.
561 static constexpr size_t kStoredMaxDecisions = 4;
562
563 // Internal structure used to represent a node of the search tree during local
564 // search.
565 struct SearchNode {
566 SearchNode()
567 : constraint(OneFlipConstraintRepairer::kInvalidConstraint),
568 term_index(OneFlipConstraintRepairer::kInvalidTerm) {}
569 SearchNode(ConstraintIndex c, TermIndex t) : constraint(c), term_index(t) {}
570 ConstraintIndex constraint;
571 TermIndex term_index;
572 };
573
574 // Applies the decision. Automatically backtracks when SAT detects conflicts.
575 void ApplyDecision(sat::Literal literal);
576
577 // Adds one more decision to repair infeasible constraints.
578 // Returns true in case of success.
579 bool GoDeeper();
580
581 // Backtracks and moves to the next decision in the search tree.
582 void Backtrack();
583
584 // Looks if the current decisions (in search_nodes_) plus the new one (given
585 // by l) lead to a position already present in transposition_table_.
586 bool NewStateIsInTranspositionTable(sat::Literal l);
587
588 // Inserts the current set of decisions in transposition_table_.
589 void InsertInTranspositionTable();
590
591 // Initializes the given array with the current decisions in search_nodes_ and
592 // by filling the other positions with 0.
593 void InitializeTranspositionTableKey(
594 std::array<int32_t, kStoredMaxDecisions>* a);
595
596 // Looks for the next repairing term in the given constraints while skipping
597 // the position already present in transposition_table_. A given TermIndex of
598 // -1 means that this is the first time we explore this constraint.
599 bool EnqueueNextRepairingTermIfAny(ConstraintIndex ct_to_repair,
600 TermIndex index);
601
602 const int max_num_decisions_;
603 const int max_num_broken_constraints_;
604 bool better_solution_has_been_found_;
605 AssignmentAndConstraintFeasibilityMaintainer maintainer_;
606 SatWrapper* const sat_wrapper_;
607 OneFlipConstraintRepairer repairer_;
608 std::vector<SearchNode> search_nodes_;
610
611 // Temporary vector used by ApplyDecision().
612 std::vector<sat::Literal> tmp_propagated_literals_;
613
614 // For each set of explored decisions, we store it in this table so that we
615 // don't explore decisions (a, b) and later (b, a) for instance. The decisions
616 // are converted to int32_t, sorted and padded with 0 before beeing inserted
617 // here.
618 //
619 // TODO(user): We may still miss some equivalent states because it is possible
620 // that completely differents decisions lead to exactly the same state.
621 // However this is more time consuming to detect because we must apply the
622 // last decision first before trying to compare the states.
623 //
624 // TODO(user): Currently, we only store kStoredMaxDecisions or less decisions.
625 // Ideally, this should be related to the maximum number of decision in the
626 // LS, but that requires templating the whole LS optimizer.
627 bool use_transposition_table_;
628 absl::flat_hash_set<std::array<int32_t, kStoredMaxDecisions>>
629 transposition_table_;
630
631 bool use_potential_one_flip_repairs_;
632
633 // The number of explored nodes.
634 int64_t num_nodes_;
635
636 // The number of skipped nodes thanks to the transposition table.
637 int64_t num_skipped_nodes_;
638
639 // The overall number of better solution found. And the ones found by the
640 // use_potential_one_flip_repairs_ heuristic.
641 int64_t num_improvements_;
642 int64_t num_improvements_by_one_flip_repairs_;
643 int64_t num_inspected_one_flip_repairs_;
644
645 DISALLOW_COPY_AND_ASSIGN(LocalSearchAssignmentIterator);
646};
647
648} // namespace bop
649} // namespace operations_research
650#endif // OR_TOOLS_BOP_BOP_LS_H_
void resize(size_type new_size)
size_type size() const
bool empty() const
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:106
int64_t ConstraintLowerBound(ConstraintIndex constraint) const
Definition: bop_ls.h:345
AssignmentAndConstraintFeasibilityMaintainer(const sat::LinearBooleanProblem &problem, absl::BitGenRef random)
Definition: bop_ls.cc:185
void SetReferenceSolution(const BopSolution &reference_solution)
Definition: bop_ls.cc:251
int64_t ConstraintUpperBound(ConstraintIndex constraint) const
Definition: bop_ls.h:350
bool ConstraintIsFeasible(ConstraintIndex constraint) const
Definition: bop_ls.h:362
int64_t ConstraintValue(ConstraintIndex constraint) const
Definition: bop_ls.h:357
const std::vector< ConstraintIndex > & PossiblyInfeasibleConstraints() const
Definition: bop_ls.h:327
void Assign(const std::vector< sat::Literal > &literals)
Definition: bop_ls.cc:304
const std::vector< sat::Literal > & PotentialOneFlipRepairs()
Definition: bop_ls.cc:353
void ChangeState(IntType i, bool should_be_inside)
Definition: bop_ls.cc:135
const std::vector< IntType > & Superset() const
Definition: bop_ls.h:181
const std::string & name() const
Definition: bop_base.h:49
bool Value(VariableIndex var) const
Definition: bop_solution.h:46
const BopSolution & LastReferenceAssignment() const
Definition: bop_ls.h:538
LocalSearchAssignmentIterator(const ProblemState &problem_state, int max_num_decisions, int max_num_broken_constraints, absl::BitGenRef random, SatWrapper *sat_wrapper)
Definition: bop_ls.cc:682
void Synchronize(const ProblemState &problem_state)
Definition: bop_ls.cc:713
LocalSearchOptimizer(const std::string &name, int max_num_decisions, absl::BitGenRef random, sat::SatSolver *sat_propagator)
Definition: bop_ls.cc:36
NonOrderedSetHasher(absl::BitGenRef random)
Definition: bop_ls.h:208
uint64_t Hash(IntType e) const
Definition: bop_ls.h:233
uint64_t Hash(const std::vector< IntType > &set) const
Definition: bop_ls.h:225
sat::Literal GetFlip(ConstraintIndex ct_index, TermIndex term_index) const
Definition: bop_ls.cc:597
bool RepairIsValid(ConstraintIndex ct_index, TermIndex term_index) const
Definition: bop_ls.cc:580
TermIndex NextRepairingTerm(ConstraintIndex ct_index, TermIndex init_term_index, TermIndex start_term_index) const
Definition: bop_ls.cc:550
OneFlipConstraintRepairer(const sat::LinearBooleanProblem &problem, const AssignmentAndConstraintFeasibilityMaintainer &maintainer, const sat::VariablesAssignment &sat_assignment)
Definition: bop_ls.cc:445
static const ConstraintIndex kInvalidConstraint
Definition: bop_ls.h:449
SatWrapper(sat::SatSolver *sat_solver)
Definition: bop_ls.cc:624
std::vector< sat::Literal > FullSatTrail() const
Definition: bop_ls.cc:628
int ApplyDecision(sat::Literal decision_literal, std::vector< sat::Literal > *propagated_literals)
Definition: bop_ls.cc:637
void ExtractLearnedInfo(LearnedInfo *info)
Definition: bop_ls.cc:670
const sat::VariablesAssignment & SatAssignment() const
Definition: bop_ls.h:68
const VariablesAssignment & Assignment() const
Definition: sat_solver.h:378
int64_t a
SatParameters parameters
ModelSharedTimeLimit * time_limit
int64_t value
IntVar * var
Definition: expr_array.cc:1874
int index
int64_t hash
Definition: matrix_utils.cc:61
Collection of objects used to extend the Constraint Solver library.
Literal literal
Definition: optimization.cc:89
int64_t weight
Definition: pack.cc:510
int64_t delta
Definition: resource.cc:1694