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