OR-Tools  9.2
cp_model_lns.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#ifndef OR_TOOLS_SAT_CP_MODEL_LNS_H_
15#define OR_TOOLS_SAT_CP_MODEL_LNS_H_
16
17#include <cstdint>
18#include <vector>
19
20#include "absl/container/flat_hash_map.h"
21#include "absl/random/bit_gen_ref.h"
22#include "absl/synchronization/mutex.h"
23#include "absl/types/span.h"
27#include "ortools/sat/model.h"
32
33namespace operations_research {
34namespace sat {
35
36// Neighborhood returned by Neighborhood generators.
38 // True if neighborhood generator was able to generate a neighborhood.
39 bool is_generated = false;
40
41 // True if an optimal solution to the neighborhood is also an optimal solution
42 // to the original model.
43 bool is_reduced = false;
44
45 // True if this neighborhood was just obtained by fixing some variables.
46 bool is_simple = false;
47
48 // Specification of the delta between the initial model and the lns fragment.
49 // The delta will contains all variables from the initial model, potentially
50 // with updated domains.
51 // It can contains new variables and new constraints, and solution hinting.
53 std::vector<int> constraints_to_ignore;
54
55 // Neighborhood Id. Used to identify the neighborhood by a generator.
56 // Currently only used by WeightedRandomRelaxationNeighborhoodGenerator.
57 // TODO(user): Make sure that the id is unique for each generated
58 // neighborhood for each generator.
59 int64_t id = 0;
60
61 // Used for identifying the source of the neighborhood if it is generated
62 // using solution repositories.
63 std::string source_info = "";
64
65 // Statistic, only filled when is_simple is true.
68
69 // Only filled when is_simple is true. If we solve the fragment to optimality,
70 // then we can just fix the variable listed here to that optimal solution.
71 //
72 // This can happen if the neighborhood fully cover some part that are
73 // completely independent from the rest of the model. Like for instance an
74 // unused but not yet fixed variable.
75 //
76 // WARNING: all such variables should be fixed at once in a lock-like manner,
77 // because they can be multiple optimal solutions on these variables.
79};
80
81// Contains pre-computed information about a given CpModelProto that is meant
82// to be used to generate LNS neighborhood. This class can be shared between
83// more than one generator in order to reduce memory usage.
84//
85// Note that its implement the SubSolver interface to be able to Synchronize()
86// the bounds of the base problem with the external world.
88 public:
92 SharedTimeLimit* shared_time_limit = nullptr,
93 SharedBoundsManager* shared_bounds = nullptr);
94
95 // SubSolver interface.
96 bool TaskIsAvailable() override { return false; }
97 std::function<void()> GenerateTask(int64_t task_id) override { return {}; }
98 void Synchronize() override;
99
100 // Returns the LNS fragment where the given variables are fixed to the value
101 // they take in the given solution.
103 const CpSolverResponse& base_solution,
104 const absl::flat_hash_set<int>& variables_to_fix) const;
105
106 // Returns the neighborhood where the given constraints are removed.
108 const std::vector<int>& constraints_to_remove) const;
109
110 // Returns the LNS fragment which will relax all inactive variables and all
111 // variables in relaxed_variables.
113 const CpSolverResponse& initial_solution,
114 const std::vector<int>& relaxed_variables) const;
115
116 // Returns a trivial model by fixing all active variables to the initial
117 // solution values.
118 Neighborhood FixAllVariables(const CpSolverResponse& initial_solution) const;
119
120 // Returns a neighborhood that correspond to the full problem.
122
123 // Returns a neighborhood that will just be skipped.
124 // It usually indicate that the generator failed to generated a neighborhood.
126
127 // Adds solution hinting to the neighborhood from the value of the initial
128 // solution.
129 void AddSolutionHinting(const CpSolverResponse& initial_solution,
131
132 // Indicates if the variable can be frozen. It happens if the variable is non
133 // constant, and if it is a decision variable, or if
134 // focus_on_decision_variables is false.
135 bool IsActive(int var) const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_);
136
137 // Returns the list of "active" variables.
138 std::vector<int> ActiveVariables() const {
139 std::vector<int> result;
140 absl::ReaderMutexLock lock(&graph_mutex_);
141 result = active_variables_;
142 return result;
143 }
144
145 int NumActiveVariables() const {
146 absl::ReaderMutexLock lock(&graph_mutex_);
147 return active_variables_.size();
148 }
149
150 bool DifficultyMeansFullNeighborhood(double difficulty) const {
151 absl::ReaderMutexLock lock(&graph_mutex_);
152 const int target_size = std::ceil(difficulty * active_variables_.size());
153 return target_size == active_variables_.size();
154 }
155
156 // Returns the vector of active variables. The graph_mutex_ must be
157 // locked before calling this method.
158 const std::vector<int>& ActiveVariablesWhileHoldingLock() const
159 ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_) {
160 return active_variables_;
161 }
162
163 // Constraints <-> Variables graph.
164 // Note that only non-constant variable are listed here.
165 const std::vector<std::vector<int>>& ConstraintToVar() const
166 ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_) {
167 return constraint_to_var_;
168 }
169 const std::vector<std::vector<int>>& VarToConstraint() const
170 ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_) {
171 return var_to_constraint_;
172 }
173
174 // Returns all the constraints indices of a given type.
175 const absl::Span<const int> TypeToConstraints(
177 if (type >= type_to_constraints_.size()) return {};
178 return absl::MakeSpan(type_to_constraints_[type]);
179 }
180
181 // Returns the list of indices of active interval constraints according
182 // to the initial_solution and the parameter lns_focus_on_performed_intervals.
183 // If true, this method returns the list of performed intervals in the
184 // solution. If false, it returns all intervals of the model.
185 std::vector<int> GetActiveIntervals(
186 const CpSolverResponse& initial_solution) const;
187
188 // Returns one sub-vector per circuit or per single vehicle ciruit in a routes
189 // constraints. Each circuit is non empty, and does not contain any
190 // self-looping arcs. Path are sorted, starting from the arc with the lowest
191 // tail index, and going in sequence up to the last arc before the circuit is
192 // closed. Each entry correspond to the arc literal on the circuit.
193 std::vector<std::vector<int>> GetRoutingPaths(
194 const CpSolverResponse& initial_solution) const;
195
196 // The initial problem.
197 // Note that the domain of the variables are not updated here.
198 const CpModelProto& ModelProto() const { return model_proto_; }
199 const SatParameters& Parameters() const { return parameters_; }
200
202 return *shared_response_;
203 }
204
205 // TODO(user): Refactor the class to be thread-safe instead, it should be
206 // safer and more easily maintenable. Some complication with accessing the
207 // variable<->constraint graph efficiently though.
208
209 // Note: This mutex needs to be public for thread annotations.
210 mutable absl::Mutex graph_mutex_;
211
212 // TODO(user): Display LNS statistics through the StatisticsString()
213 // method.
214
215 private:
216 // Precompute stuff that will never change. During the execution, only the
217 // domain of the variable will change, so data that only depends on the
218 // constraints need to be computed just once.
219 void InitializeHelperData();
220
221 // Recompute most of the class member. This needs to be called when the
222 // domains of the variables are updated.
223 void RecomputeHelperData();
224
225 // Indicates if a variable is fixed in the model.
226 bool IsConstant(int var) const ABSL_SHARED_LOCKS_REQUIRED(domain_mutex_);
227
228 // Returns true if the domain on the objective is constraining and we might
229 // get a lower objective value at optimum without it.
230 bool ObjectiveDomainIsConstraining() const
231 ABSL_SHARED_LOCKS_REQUIRED(domain_mutex_);
232
233 const SatParameters& parameters_;
234 const CpModelProto& model_proto_;
235 int shared_bounds_id_;
236 SharedTimeLimit* shared_time_limit_;
237 SharedBoundsManager* shared_bounds_;
238 SharedResponseManager* shared_response_;
239 SharedRelaxationSolutionRepository* shared_relaxation_solutions_;
240
241 // This proto will only contain the field variables() with an updated version
242 // of the domains compared to model_proto_.variables(). We do it like this to
243 // reduce the memory footprint of the helper when the model is large.
244 //
245 // TODO(user): Use custom domain repository rather than a proto?
246 CpModelProto model_proto_with_only_variables_ ABSL_GUARDED_BY(domain_mutex_);
247
248 // Constraints by types. This never changes.
249 std::vector<std::vector<int>> type_to_constraints_;
250
251 // Whether a model_proto_ variable appear in the objective. This never
252 // changes.
253 std::vector<bool> is_in_objective_;
254
255 // A copy of CpModelProto where we did some basic presolving to remove all
256 // constraint that are always true. The Variable-Constraint graph is based on
257 // this model. Note that only the constraints field is present here.
258 CpModelProto simplied_model_proto_ ABSL_GUARDED_BY(graph_mutex_);
259
260 // Variable-Constraint graph.
261 // We replace an interval by its variables in the scheduling constraints.
262 //
263 // TODO(user): Note that the objective is not considered here. Which is fine
264 // except if the objective domain is constraining.
265 std::vector<std::vector<int>> constraint_to_var_
266 ABSL_GUARDED_BY(graph_mutex_);
267 std::vector<std::vector<int>> var_to_constraint_
268 ABSL_GUARDED_BY(graph_mutex_);
269
270 // Connected components of the variable-constraint graph. If a variable is
271 // constant, it will not appear in any component and
272 // var_to_component_index_[var] will be -1.
273 std::vector<std::vector<int>> components_ ABSL_GUARDED_BY(graph_mutex_);
274 std::vector<int> var_to_component_index_ ABSL_GUARDED_BY(graph_mutex_);
275
276 // The set of active variables which is currently the list of non-constant
277 // variables. It is stored both as a list and as a set (using a Boolean
278 // vector).
279 std::vector<bool> active_variables_set_ ABSL_GUARDED_BY(graph_mutex_);
280 std::vector<int> active_variables_ ABSL_GUARDED_BY(graph_mutex_);
281
282 mutable absl::Mutex domain_mutex_;
283};
284
285// Base class for a CpModelProto neighborhood generator.
287 public:
288 NeighborhoodGenerator(const std::string& name,
289 NeighborhoodGeneratorHelper const* helper)
290 : name_(name), helper_(*helper), difficulty_(0.5) {}
292
293 // Generates a "local" subproblem for the given seed.
294 //
295 // The difficulty will be in [0, 1] and is related to the asked neighborhood
296 // size (and thus local problem difficulty). A difficulty of 0.0 means empty
297 // neighborhood and a difficulty of 1.0 means the full problem. The algorithm
298 // should try to generate a neighborhood according to this difficulty which
299 // will be dynamically adjusted depending on whether or not we can solve the
300 // subproblem in a given time limit.
301 //
302 // The given initial_solution should contain a feasible solution to the
303 // initial CpModelProto given to this class. Any solution to the returned
304 // CPModelProto should also be valid solution to the same initial model.
305 //
306 // This function should be thread-safe.
307 virtual Neighborhood Generate(const CpSolverResponse& initial_solution,
308 double difficulty, absl::BitGenRef random) = 0;
309
310 // Returns true if the neighborhood generator can generate a neighborhood.
311 virtual bool ReadyToGenerate() const;
312
313 // Returns true if the neighborhood generator generates relaxation of the
314 // given problem.
315 virtual bool IsRelaxationGenerator() const { return false; }
316
317 // Uses UCB1 algorithm to compute the score (Multi armed bandit problem).
318 // Details are at
319 // https://lilianweng.github.io/lil-log/2018/01/23/the-multi-armed-bandit-problem-and-its-solutions.html.
320 // 'total_num_calls' should be the sum of calls across all generators part of
321 // the multi armed bandit problem.
322 // If the generator is called less than 10 times then the method returns
323 // infinity as score in order to get more data about the generator
324 // performance.
325 double GetUCBScore(int64_t total_num_calls) const;
326
327 // Adds solve data about one "solved" neighborhood.
328 struct SolveData {
329 // Neighborhood Id. Used to identify the neighborhood by a generator.
330 // Currently only used by WeightedRandomRelaxationNeighborhoodGenerator.
331 int64_t neighborhood_id = 0;
332
333 // The status of the sub-solve.
335
336 // The difficulty when this neighborhood was generated.
337 double difficulty = 0.0;
338
339 // The determinitic time limit given to the solver for this neighborhood.
340 double deterministic_limit = 0.0;
341
342 // The time it took to solve this neighborhood.
343 double deterministic_time = 0.0;
344
345 // Objective information. These only refer to the "internal" objective
346 // without scaling or offset so we are exact and it is always in the
347 // minimization direction.
348 // - The initial best objective is the one of the best known solution at the
349 // time the neighborhood was generated.
350 // - The base objective is the one of the base solution from which this
351 // neighborhood was generated.
352 // - The new objective is the objective of the best solution found by
353 // solving the neighborhood.
354 IntegerValue initial_best_objective = IntegerValue(0);
355 IntegerValue base_objective = IntegerValue(0);
356 IntegerValue new_objective = IntegerValue(0);
357
358 // Bounds data is only used by relaxation neighborhoods.
359 IntegerValue initial_best_objective_bound = IntegerValue(0);
360 IntegerValue new_objective_bound = IntegerValue(0);
361
362 // This is just used to construct a deterministic order for the updates.
363 bool operator<(const SolveData& o) const {
364 return std::tie(status, difficulty, deterministic_limit,
365 deterministic_time, initial_best_objective,
366 base_objective, new_objective,
367 initial_best_objective_bound, new_objective_bound,
368 neighborhood_id) <
369 std::tie(o.status, o.difficulty, o.deterministic_limit,
374 }
375 };
377 absl::MutexLock mutex_lock(&generator_mutex_);
378 solve_data_.push_back(data);
379 }
380
381 // Process all the recently added solve data and update this generator
382 // score and difficulty.
383 void Synchronize();
384
385 // Returns a short description of the generator.
386 std::string name() const { return name_; }
387
388 // Number of times this generator was called.
389 int64_t num_calls() const {
390 absl::MutexLock mutex_lock(&generator_mutex_);
391 return num_calls_;
392 }
393
394 // Number of time the neighborhood was fully solved (OPTIMAL/INFEASIBLE).
395 int64_t num_fully_solved_calls() const {
396 absl::MutexLock mutex_lock(&generator_mutex_);
397 return num_fully_solved_calls_;
398 }
399
400 // The current difficulty of this generator
401 double difficulty() const {
402 absl::MutexLock mutex_lock(&generator_mutex_);
403 return difficulty_.value();
404 }
405
406 // The current time limit that the sub-solve should use on this generator.
407 double deterministic_limit() const {
408 absl::MutexLock mutex_lock(&generator_mutex_);
409 return deterministic_limit_;
410 }
411
412 // The sum of the deterministic time spent in this generator.
413 double deterministic_time() const {
414 absl::MutexLock mutex_lock(&generator_mutex_);
415 return deterministic_time_;
416 }
417
418 protected:
419 // Triggered with each call to Synchronize() for each recently added
420 // SolveData. This is meant to be used for processing feedbacks by specific
421 // neighborhood generators to adjust the neighborhood generation process.
422 virtual void AdditionalProcessingOnSynchronize(const SolveData& solve_data) {}
423
424 const std::string name_;
426 mutable absl::Mutex generator_mutex_;
427
428 private:
429 std::vector<SolveData> solve_data_;
430
431 // Current parameters to be used when generating/solving a neighborhood with
432 // this generator. Only updated on Synchronize().
433 AdaptiveParameterValue difficulty_;
434 double deterministic_limit_ = 0.1;
435
436 // Current statistics of the last solved neighborhood.
437 // Only updated on Synchronize().
438 int64_t num_calls_ = 0;
439 int64_t num_fully_solved_calls_ = 0;
440 int64_t num_consecutive_non_improving_calls_ = 0;
441 double deterministic_time_ = 0.0;
442 double current_average_ = 0.0;
443};
444
445// Pick a random subset of variables.
446//
447// TODO(user): In the presence of connected components, this should just work
448// on one of them.
450 public:
452 NeighborhoodGeneratorHelper const* helper, const std::string& name)
453 : NeighborhoodGenerator(name, helper) {}
454 Neighborhood Generate(const CpSolverResponse& initial_solution,
455 double difficulty, absl::BitGenRef random) final;
456};
457
458// Pick a random subset of constraints and relax all the variables of these
459// constraints. Note that to satisfy the difficulty, we might not relax all the
460// variable of the "last" constraint.
461//
462// TODO(user): In the presence of connected components, this should just work
463// on one of them.
465 public:
467 NeighborhoodGeneratorHelper const* helper, const std::string& name)
468 : NeighborhoodGenerator(name, helper) {}
469 Neighborhood Generate(const CpSolverResponse& initial_solution,
470 double difficulty, absl::BitGenRef random) final;
471};
472
473// Pick a random subset of variables that are constructed by a BFS in the
474// variable <-> constraint graph. That is, pick a random variable, then all the
475// variable connected by some constraint to the first one, and so on. The
476// variable of the last "level" are selected randomly.
477//
478// Note that in the presence of connected component, this works correctly
479// already.
481 public:
483 NeighborhoodGeneratorHelper const* helper, const std::string& name)
484 : NeighborhoodGenerator(name, helper) {}
485 Neighborhood Generate(const CpSolverResponse& initial_solution,
486 double difficulty, absl::BitGenRef random) final;
487};
488
489// Pick a random subset of constraint and relax all of their variables. We are a
490// bit smarter than this because after the first constraint is selected, we only
491// select constraints that share at least one variable with the already selected
492// constraints. The variable from the "last" constraint are selected randomly.
494 public:
496 NeighborhoodGeneratorHelper const* helper, const std::string& name)
497 : NeighborhoodGenerator(name, helper) {}
498 Neighborhood Generate(const CpSolverResponse& initial_solution,
499 double difficulty, absl::BitGenRef random) final;
500};
501
502// Helper method for the scheduling neighborhood generators. Returns the model
503// as neighborhood for the given set of intervals to relax. For each no_overlap
504// constraints, it adds strict relation order between the non-relaxed intervals.
506 const absl::Span<const int> intervals_to_relax,
507 const CpSolverResponse& initial_solution,
508 const NeighborhoodGeneratorHelper& helper);
509
510// Only make sense for scheduling problem. This select a random set of interval
511// of the problem according to the difficulty. Then, for each no_overlap
512// constraints, it adds strict relation order between the non-relaxed intervals.
513//
514// TODO(user): Also deal with cumulative constraint.
516 public:
518 NeighborhoodGeneratorHelper const* helper, const std::string& name)
519 : NeighborhoodGenerator(name, helper) {}
520
521 Neighborhood Generate(const CpSolverResponse& initial_solution,
522 double difficulty, absl::BitGenRef random) final;
523};
524
525// Similar to SchedulingNeighborhoodGenerator except the set of intervals that
526// are relaxed are from a specific random time interval.
528 public:
530 NeighborhoodGeneratorHelper const* helper, const std::string& name)
531 : NeighborhoodGenerator(name, helper) {}
532
533 Neighborhood Generate(const CpSolverResponse& initial_solution,
534 double difficulty, absl::BitGenRef random) final;
535};
536
537// This routing based LNS generator will relax random arcs in all the paths of
538// the circuit or routes constraints.
540 public:
542 const std::string& name)
543 : NeighborhoodGenerator(name, helper) {}
544
545 Neighborhood Generate(const CpSolverResponse& initial_solution,
546 double difficulty, absl::BitGenRef random) final;
547};
548
549// This routing based LNS generator will relax small sequences of arcs randomly
550// chosen in all the paths of the circuit or routes constraints.
552 public:
554 const std::string& name)
555 : NeighborhoodGenerator(name, helper) {}
556
557 Neighborhood Generate(const CpSolverResponse& initial_solution,
558 double difficulty, absl::BitGenRef random) final;
559};
560
561// This routing based LNS generator aims are relaxing one full path, and make
562// some room on the other paths to absorb the nodes of the relaxed path.
563//
564// In order to do so, it will relax the first and the last arc of each path in
565// the circuit or routes constraints. Then it will relax all arc literals in one
566// random path. Then it will relax random arcs in the remaining paths until it
567// reaches the given difficulty.
569 public:
571 NeighborhoodGeneratorHelper const* helper, const std::string& name)
572 : NeighborhoodGenerator(name, helper) {}
573
574 Neighborhood Generate(const CpSolverResponse& initial_solution,
575 double difficulty, absl::BitGenRef random) final;
576};
577
578// Generates a neighborhood by fixing the variables to solutions reported in
579// various repositories. This is inspired from RINS published in "Exploring
580// relaxation induced neighborhoods to improve MIP solutions" 2004 by E. Danna
581// et.
582//
583// If incomplete_solutions is provided, this generates a neighborhood by fixing
584// the variable values to a solution in the SharedIncompleteSolutionManager and
585// ignores the other repositories.
586//
587// Otherwise, if response_manager is not provided, this generates a neighborhood
588// using only the linear/general relaxation values. The domain of the variables
589// are reduced to the integer values around their lp solution/relaxation
590// solution values. This was published in "RENS – The Relaxation Enforced
591// Neighborhood" 2009 by Timo Berthold.
593 public:
595 NeighborhoodGeneratorHelper const* helper,
596 const SharedResponseManager* response_manager,
600 const std::string& name)
601 : NeighborhoodGenerator(name, helper),
602 response_manager_(response_manager),
603 relaxation_solutions_(relaxation_solutions),
604 lp_solutions_(lp_solutions),
605 incomplete_solutions_(incomplete_solutions) {
606 CHECK(lp_solutions_ != nullptr || relaxation_solutions_ != nullptr ||
607 incomplete_solutions != nullptr);
608 }
609
610 // Both initial solution and difficulty values are ignored.
611 Neighborhood Generate(const CpSolverResponse& initial_solution,
612 double difficulty, absl::BitGenRef random) final;
613
614 // Returns true if the required solutions are available.
615 bool ReadyToGenerate() const override;
616
617 private:
618 const SharedResponseManager* response_manager_;
619 const SharedRelaxationSolutionRepository* relaxation_solutions_;
620 const SharedLPSolutionRepository* lp_solutions_;
621 SharedIncompleteSolutionManager* incomplete_solutions_;
622};
623
624// Generates a relaxation of the original model by removing a consecutive span
625// of constraints starting at a random index. The number of constraints removed
626// is in sync with the difficulty passed to the generator.
628 : public NeighborhoodGenerator {
629 public:
631 NeighborhoodGeneratorHelper const* helper, const std::string& name)
632 : NeighborhoodGenerator(name, helper) {}
633 Neighborhood Generate(const CpSolverResponse& initial_solution,
634 double difficulty, absl::BitGenRef random) final;
635
636 bool IsRelaxationGenerator() const override { return true; }
637 bool ReadyToGenerate() const override { return true; }
638};
639
640// Generates a relaxation of the original model by removing some constraints
641// randomly with a given weight for each constraint that controls the
642// probability of constraint getting removed. The number of constraints removed
643// is in sync with the difficulty passed to the generator. Higher weighted
644// constraints are more likely to get removed.
646 : public NeighborhoodGenerator {
647 public:
649 NeighborhoodGeneratorHelper const* helper, const std::string& name);
650
651 // Generates the neighborhood as described above. Also stores the removed
652 // constraints indices for adjusting the weights.
653 Neighborhood Generate(const CpSolverResponse& initial_solution,
654 double difficulty, absl::BitGenRef random) final;
655
656 bool IsRelaxationGenerator() const override { return true; }
657 bool ReadyToGenerate() const override { return true; }
658
659 private:
660 // Adjusts the weights of the constraints removed to get the neighborhood
661 // based on the solve_data.
662 void AdditionalProcessingOnSynchronize(const SolveData& solve_data) override
663 ABSL_EXCLUSIVE_LOCKS_REQUIRED(generator_mutex_);
664
665 // Higher weighted constraints are more likely to get removed.
666 std::vector<double> constraint_weights_;
667 int num_removable_constraints_ = 0;
668
669 // Indices of the removed constraints per generated neighborhood.
670 absl::flat_hash_map<int64_t, std::vector<int>> removed_constraints_
671 ABSL_GUARDED_BY(generator_mutex_);
672
673 // TODO(user): Move this to parent class if other generators start using
674 // feedbacks.
675 int64_t next_available_id_ ABSL_GUARDED_BY(generator_mutex_) = 0;
676};
677
678} // namespace sat
679} // namespace operations_research
680
681#endif // OR_TOOLS_SAT_CP_MODEL_LNS_H_
#define CHECK(condition)
Definition: base/logging.h:495
ConsecutiveConstraintsRelaxationNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:630
ConstraintGraphNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:495
NeighborhoodGeneratorHelper(CpModelProto const *model_proto, SatParameters const *parameters, SharedResponseManager *shared_response, SharedTimeLimit *shared_time_limit=nullptr, SharedBoundsManager *shared_bounds=nullptr)
Definition: cp_model_lns.cc:39
Neighborhood FixAllVariables(const CpSolverResponse &initial_solution) const
const absl::Span< const int > TypeToConstraints(ConstraintProto::ConstraintCase type) const
Definition: cp_model_lns.h:175
Neighborhood FixGivenVariables(const CpSolverResponse &base_solution, const absl::flat_hash_set< int > &variables_to_fix) const
std::function< void()> GenerateTask(int64_t task_id) override
Definition: cp_model_lns.h:97
bool DifficultyMeansFullNeighborhood(double difficulty) const
Definition: cp_model_lns.h:150
Neighborhood RelaxGivenVariables(const CpSolverResponse &initial_solution, const std::vector< int > &relaxed_variables) const
std::vector< int > GetActiveIntervals(const CpSolverResponse &initial_solution) const
const SharedResponseManager & shared_response() const
Definition: cp_model_lns.h:201
const std::vector< std::vector< int > > & VarToConstraint() const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_)
Definition: cp_model_lns.h:169
bool IsActive(int var) const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_)
const std::vector< int > & ActiveVariablesWhileHoldingLock() const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_)
Definition: cp_model_lns.h:158
Neighborhood RemoveMarkedConstraints(const std::vector< int > &constraints_to_remove) const
void AddSolutionHinting(const CpSolverResponse &initial_solution, CpModelProto *model_proto) const
const std::vector< std::vector< int > > & ConstraintToVar() const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_)
Definition: cp_model_lns.h:165
std::vector< std::vector< int > > GetRoutingPaths(const CpSolverResponse &initial_solution) const
virtual Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random)=0
NeighborhoodGenerator(const std::string &name, NeighborhoodGeneratorHelper const *helper)
Definition: cp_model_lns.h:288
virtual void AdditionalProcessingOnSynchronize(const SolveData &solve_data)
Definition: cp_model_lns.h:422
const NeighborhoodGeneratorHelper & helper_
Definition: cp_model_lns.h:425
RelaxRandomConstraintsGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:466
RelaxRandomVariablesGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:451
RelaxationInducedNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const SharedResponseManager *response_manager, const SharedRelaxationSolutionRepository *relaxation_solutions, const SharedLPSolutionRepository *lp_solutions, SharedIncompleteSolutionManager *incomplete_solutions, const std::string &name)
Definition: cp_model_lns.h:594
RoutingFullPathNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:570
RoutingPathNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:553
RoutingRandomNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:541
SchedulingNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:517
SchedulingTimeWindowNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:529
VariableGraphNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
Definition: cp_model_lns.h:482
SatParameters parameters
SharedRelaxationSolutionRepository * relaxation_solutions
SharedLPSolutionRepository * lp_solutions
CpModelProto const * model_proto
SharedIncompleteSolutionManager * incomplete_solutions
IntVar * var
Definition: expr_array.cc:1874
absl::Status status
Definition: g_gurobi.cc:35
Definition: cleanup.h:22
Neighborhood GenerateSchedulingNeighborhoodForRelaxation(const absl::Span< const int > intervals_to_relax, const CpSolverResponse &initial_solution, const NeighborhoodGeneratorHelper &helper)
Collection of objects used to extend the Constraint Solver library.
STL namespace.
std::vector< int > variables_that_can_be_fixed_to_local_optimum
Definition: cp_model_lns.h:78
std::vector< int > constraints_to_ignore
Definition: cp_model_lns.h:53