OR-Tools  9.1
integer_search.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 contains all the top-level logic responsible for driving the search
15 // of a satisfiability integer problem. What decision we take next, which new
16 // Literal associated to an IntegerLiteral we create and when we restart.
17 //
18 // For an optimization problem, our algorithm solves a sequence of decision
19 // problem using this file as an entry point. Note that some heuristics here
20 // still use the objective if there is one in order to orient the search towards
21 // good feasible solution though.
22 
23 #ifndef OR_TOOLS_SAT_INTEGER_SEARCH_H_
24 #define OR_TOOLS_SAT_INTEGER_SEARCH_H_
25 
26 #include <vector>
27 
28 #include "ortools/sat/integer.h"
31 #include "ortools/sat/sat_base.h"
32 #include "ortools/sat/sat_solver.h"
33 
34 namespace operations_research {
35 namespace sat {
36 
37 // This is used to hold the next decision the solver will take. It is either
38 // a pure Boolean literal decision or correspond to an IntegerLiteral one.
39 //
40 // At most one of the two options should be set.
43  explicit BooleanOrIntegerLiteral(LiteralIndex index)
46  : integer_literal(i_lit) {}
47 
48  bool HasValue() const {
51  }
52 
55 };
56 
57 // Model struct that contains the search heuristics used to find a feasible
58 // solution to an integer problem.
59 //
60 // This is reset by ConfigureSearchHeuristics() and used by
61 // SolveIntegerProblem(), see below.
63  // Decision and restart heuristics. The two vectors must be of the same size
64  // and restart_policies[i] will always be used in conjunction with
65  // decision_policies[i].
66  std::vector<std::function<BooleanOrIntegerLiteral()>> decision_policies;
67  std::vector<std::function<bool()>> restart_policies;
68 
69  // Index in the vectors above that indicate the current configuration.
71 
72  // Two special decision functions that are constructed at loading time.
73  // These are used by ConfigureSearchHeuristics() to fill the policies above.
74  std::function<BooleanOrIntegerLiteral()> fixed_search = nullptr;
75  std::function<BooleanOrIntegerLiteral()> hint_search = nullptr;
76 
77  // Some search strategy need to take more than one decision at once. They can
78  // set this function that will be called on the next decision. It will be
79  // automatically deleted the first time it returns an empty decision.
80  std::function<BooleanOrIntegerLiteral()> next_decision_override = nullptr;
81 };
82 
83 // Given a base "fixed_search" function that should mainly control in which
84 // order integer variables are lazily instantiated (and at what value), this
85 // uses the current solver parameters to set the SearchHeuristics class in the
86 // given model.
88 
89 // Callbacks that will be called when the search goes back to level 0.
90 // Callbacks should return false if the propagation fails.
92  std::vector<std::function<bool()>> callbacks;
93 };
94 
95 // Tries to find a feasible solution to the current model.
96 //
97 // This function continues from the current state of the solver and loop until
98 // all variables are instantiated (i.e. the next decision is kNoLiteralIndex) or
99 // a search limit is reached. It uses the heuristic from the SearchHeuristics
100 // class in the model to decide when to restart and what next decision to take.
101 //
102 // Each time a restart happen, this increment the policy index modulo the number
103 // of heuristics to act as a portfolio search.
105 
106 // Resets the solver to the given assumptions before calling
107 // SolveIntegerProblem().
109  const std::vector<Literal>& assumptions, Model* model);
110 
111 // Only used in tests. Move to a test utility file.
112 //
113 // This configures the model SearchHeuristics with a simple default heuristic
114 // and then call ResetAndSolveIntegerProblem() without any assumptions.
116 
117 // Returns decision corresponding to var at its lower bound.
118 // Returns an invalid literal if the variable is fixed.
119 IntegerLiteral AtMinValue(IntegerVariable var, IntegerTrail* integer_trail);
120 
121 // If a variable appear in the objective, branch on its best objective value.
123 
124 // Returns decision corresponding to var >= lb + max(1, (ub - lb) / 2). It also
125 // CHECKs that the variable is not fixed.
127  IntegerTrail* integer_trail);
128 
129 // This method first tries var <= value. If this does not reduce the domain it
130 // tries var >= value. If that also does not reduce the domain then returns
131 // an invalid literal.
132 IntegerLiteral SplitAroundGivenValue(IntegerVariable var, IntegerValue value,
133  Model* model);
134 
135 // Returns decision corresponding to var <= round(lp_value). If the variable
136 // does not appear in the LP, this method returns an invalid literal.
137 IntegerLiteral SplitAroundLpValue(IntegerVariable var, Model* model);
138 
139 // Returns decision corresponding to var <= best_solution[var]. If no solution
140 // has been found, this method returns a literal with kNoIntegerVariable. This
141 // was suggested in paper: "Solution-Based Phase Saving for CP" (2018) by Emir
142 // Demirovic, Geoffrey Chu, and Peter J. Stuckey.
144  Model* model);
145 
146 // Decision heuristic for SolveIntegerProblemWithLazyEncoding(). Returns a
147 // function that will return the literal corresponding to the fact that the
148 // first currently non-fixed variable value is <= its min. The function will
149 // return kNoLiteralIndex if all the given variables are fixed.
150 //
151 // Note that this function will create the associated literal if needed.
153  const std::vector<IntegerVariable>& vars, Model* model);
154 
155 // Decision heuristic for SolveIntegerProblemWithLazyEncoding(). Like
156 // FirstUnassignedVarAtItsMinHeuristic() but the function will return the
157 // literal corresponding to the fact that the currently non-assigned variable
158 // with the lowest min has a value <= this min.
159 std::function<BooleanOrIntegerLiteral()>
161  const std::vector<IntegerVariable>& vars, Model* model);
162 
163 // Set the first unassigned Literal/Variable to its value.
164 //
165 // TODO(user): This is currently quadratic as we scan all variables to find the
166 // first unassigned one. Fix. Note that this is also the case in many other
167 // heuristics and should be fixed.
169  BooleanVariable bool_var = kNoBooleanVariable;
170  IntegerVariable int_var = kNoIntegerVariable;
171 };
172 std::function<BooleanOrIntegerLiteral()> FollowHint(
173  const std::vector<BooleanOrIntegerVariable>& vars,
174  const std::vector<IntegerValue>& values, Model* model);
175 
176 // Combines search heuristics in order: if the i-th one returns kNoLiteralIndex,
177 // ask the (i+1)-th. If every heuristic returned kNoLiteralIndex,
178 // returns kNoLiteralIndex.
180  std::vector<std::function<BooleanOrIntegerLiteral()>> heuristics);
181 
182 // Changes the value of the given decision by 'var_selection_heuristic'. We try
183 // to see if the decision is "associated" with an IntegerVariable, and if it is
184 // the case, we choose the new value by the first 'value_selection_heuristics'
185 // that is applicable. If none of the heuristics are applicable then the given
186 // decision by 'var_selection_heuristic' is returned.
188  std::vector<std::function<IntegerLiteral(IntegerVariable)>>
189  value_selection_heuristics,
190  std::function<BooleanOrIntegerLiteral()> var_selection_heuristic,
191  Model* model);
192 
193 // Changes the value of the given decision by 'var_selection_heuristic'
194 // according to various value selection heuristics. Looks at the code to know
195 // exactly what heuristic we use.
197  std::function<BooleanOrIntegerLiteral()> var_selection_heuristic,
198  Model* model);
199 
200 // Returns the BooleanOrIntegerLiteral advised by the underliying SAT solver.
202 
203 // Gets the branching variable using pseudo costs and combines it with a value
204 // for branching.
205 std::function<BooleanOrIntegerLiteral()> PseudoCost(Model* model);
206 
207 // Simple scheduling heuristic that looks at all the no-overlap constraints
208 // and try to assign and perform the intervals that can be scheduled first.
210  Model* model);
211 
212 // Returns true if the number of variables in the linearized part represent
213 // a large enough proportion of all the problem variables.
215 
216 // A restart policy that restarts every k failures.
217 std::function<bool()> RestartEveryKFailures(int k, SatSolver* solver);
218 
219 // A restart policy that uses the underlying sat solver's policy.
220 std::function<bool()> SatSolverRestartPolicy(Model* model);
221 
222 // Concatenates each input_heuristic with a default heuristic that instantiate
223 // all the problem's Boolean variables, into a new vector.
224 std::vector<std::function<BooleanOrIntegerLiteral()>> CompleteHeuristics(
225  const std::vector<std::function<BooleanOrIntegerLiteral()>>&
226  incomplete_heuristics,
227  const std::function<BooleanOrIntegerLiteral()>& completion_heuristic);
228 
229 // Specialized search that will continuously probe Boolean variables and bounds
230 // of integer variables.
232  const std::vector<BooleanVariable>& bool_vars,
233  const std::vector<IntegerVariable>& int_vars,
234  const std::function<void()>& feasible_solution_observer, Model* model);
235 
236 // An helper class to share the code used by the different kind of search.
238  public:
239  explicit IntegerSearchHelper(Model* model);
240 
241  // Executes some code before a new decision.
242  // Returns false if model is UNSAT.
243  bool BeforeTakingDecision();
244 
245  // Calls the decision heuristics and extract a non-fixed literal.
246  // Note that we do not want to copy the function here.
247  LiteralIndex GetDecision(const std::function<BooleanOrIntegerLiteral()>& f);
248 
249  // Tries to take the current decision, this might backjump.
250  // Returns false if the model is UNSAT.
251  bool TakeDecision(Literal decision);
252 
253  private:
254  Model* model_;
255  SatSolver* sat_solver_;
256  IntegerTrail* integer_trail_;
257  IntegerEncoder* encoder_;
258  ImpliedBounds* implied_bounds_;
259  TimeLimit* time_limit_;
260  PseudoCosts* pseudo_costs_;
261  IntegerVariable objective_var_ = kNoIntegerVariable;
262 };
263 
264 } // namespace sat
265 } // namespace operations_research
266 
267 #endif // OR_TOOLS_SAT_INTEGER_SEARCH_H_
IntegerLiteral SplitDomainUsingBestSolutionValue(IntegerVariable var, Model *model)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:105
std::vector< std::function< bool()> > callbacks
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
SatSolver::Status SolveIntegerProblemWithLazyEncoding(Model *model)
GRBmodel * model
std::vector< std::function< BooleanOrIntegerLiteral()> > CompleteHeuristics(const std::vector< std::function< BooleanOrIntegerLiteral()>> &incomplete_heuristics, const std::function< BooleanOrIntegerLiteral()> &completion_heuristic)
SatSolver::Status ContinuousProbing(const std::vector< BooleanVariable > &bool_vars, const std::vector< IntegerVariable > &int_vars, const std::function< void()> &feasible_solution_observer, Model *model)
std::function< BooleanOrIntegerLiteral()> SatSolverHeuristic(Model *model)
std::function< bool()> RestartEveryKFailures(int k, SatSolver *solver)
std::function< BooleanOrIntegerLiteral()> fixed_search
std::function< BooleanOrIntegerLiteral()> FollowHint(const std::vector< BooleanOrIntegerVariable > &vars, const std::vector< IntegerValue > &values, Model *model)
void ConfigureSearchHeuristics(Model *model)
std::function< bool()> SatSolverRestartPolicy(Model *model)
const BooleanVariable kNoBooleanVariable(-1)
std::vector< std::function< BooleanOrIntegerLiteral()> > decision_policies
std::function< BooleanOrIntegerLiteral()> hint_search
int index
Definition: pack.cc:509
IntegerLiteral ChooseBestObjectiveValue(IntegerVariable var, Model *model)
std::function< BooleanOrIntegerLiteral()> SequentialValueSelection(std::vector< std::function< IntegerLiteral(IntegerVariable)>> value_selection_heuristics, std::function< BooleanOrIntegerLiteral()> var_selection_heuristic, Model *model)
IntegerLiteral GreaterOrEqualToMiddleValue(IntegerVariable var, IntegerTrail *integer_trail)
std::function< BooleanOrIntegerLiteral()> SchedulingSearchHeuristic(Model *model)
IntegerLiteral AtMinValue(IntegerVariable var, IntegerTrail *integer_trail)
SatSolver::Status SolveIntegerProblem(Model *model)
SatSolver::Status ResetAndSolveIntegerProblem(const std::vector< Literal > &assumptions, Model *model)
IntegerLiteral SplitAroundGivenValue(IntegerVariable var, IntegerValue value, Model *model)
std::function< BooleanOrIntegerLiteral()> next_decision_override
Collection of objects used to extend the Constraint Solver library.
const IntegerVariable kNoIntegerVariable(-1)
std::function< BooleanOrIntegerLiteral()> IntegerValueSelectionHeuristic(std::function< BooleanOrIntegerLiteral()> var_selection_heuristic, Model *model)
std::function< BooleanOrIntegerLiteral()> PseudoCost(Model *model)
const LiteralIndex kNoLiteralIndex(-1)
IntVar * var
Definition: expr_array.cc:1874
IntegerLiteral SplitAroundLpValue(IntegerVariable var, Model *model)
std::function< BooleanOrIntegerLiteral()> UnassignedVarWithLowestMinAtItsMinHeuristic(const std::vector< IntegerVariable > &vars, Model *model)
std::function< BooleanOrIntegerLiteral()> FirstUnassignedVarAtItsMinHeuristic(const std::vector< IntegerVariable > &vars, Model *model)
int64_t value
bool LinearizedPartIsLarge(Model *model)
std::vector< std::function< bool()> > restart_policies
std::function< BooleanOrIntegerLiteral()> SequentialSearch(std::vector< std::function< BooleanOrIntegerLiteral()>> heuristics)
LiteralIndex GetDecision(const std::function< BooleanOrIntegerLiteral()> &f)