OR-Tools  8.0
optimization.h
Go to the documentation of this file.
1 // Copyright 2010-2018 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_OPTIMIZATION_H_
15 #define OR_TOOLS_SAT_OPTIMIZATION_H_
16 
17 #include <functional>
18 #include <vector>
19 
22 #include "ortools/sat/integer.h"
24 #include "ortools/sat/model.h"
25 #include "ortools/sat/sat_base.h"
26 #include "ortools/sat/sat_solver.h"
27 
28 namespace operations_research {
29 namespace sat {
30 
31 // Tries to minimize the given UNSAT core with a really simple heuristic.
32 // The idea is to remove literals that are consequences of others in the core.
33 // We already know that in the initial order, no literal is propagated by the
34 // one before it, so we just look for propagation in the reverse order.
35 //
36 // Important: The given SatSolver must be the one that just produced the given
37 // core.
38 void MinimizeCore(SatSolver* solver, std::vector<Literal>* core);
39 
40 // Like MinimizeCore() with a slower but strictly better heuristic. This
41 // algorithm should produce a minimal core with respect to propagation. We put
42 // each literal of the initial core "last" at least once, so if such literal can
43 // be inferred by propagation by any subset of the other literal, it will be
44 // removed.
45 //
46 // Note that this function doest NOT preserve the order of Literal in the core.
47 void MinimizeCoreWithPropagation(SatSolver* solver, std::vector<Literal>* core);
48 
49 // Because the Solve*() functions below are also used in scripts that requires a
50 // special output format, we use this to tell them whether or not to use the
51 // default logging framework or simply stdout. Most users should just use
52 // DEFAULT_LOG.
54 
55 // All the Solve*() functions below reuse the SatSolver::Status with a slightly
56 // different meaning:
57 // - FEASIBLE: The problem has been solved to optimality.
58 // - INFEASIBLE: Same meaning, the decision version is already unsat.
59 // - LIMIT_REACHED: we may have some feasible solution (if solution is
60 // non-empty), but the optimality is not proven.
61 
62 // Implements the "Fu & Malik" algorithm described in:
63 // Zhaohui Fu, Sharad Malik, "On solving the Partial MAX-SAT problem", 2006,
64 // International Conference on Theory and Applications of Satisfiability
65 // Testing. (SAT’06), LNCS 4121.
66 //
67 // This algorithm requires all the objective weights to be the same (CHECKed)
68 // and currently only works on minimization problems. The problem is assumed to
69 // be already loaded into the given solver.
70 //
71 // TODO(user): double-check the correctness if the objective coefficients are
72 // negative.
74  const LinearBooleanProblem& problem,
75  SatSolver* solver,
76  std::vector<bool>* solution);
77 
78 // The WPM1 algorithm is a generalization of the Fu & Malik algorithm to
79 // weighted problems. Note that if all objective weights are the same, this is
80 // almost the same as SolveWithFuMalik() but the encoding of the constraints is
81 // slightly different.
82 //
83 // Ansotegui, C., Bonet, M.L., Levy, J.: Solving (weighted) partial MaxSAT
84 // through satisfiability testing. In: Proc. of the 12th Int. Conf. on Theory and
85 // Applications of Satisfiability Testing (SAT’09). pp. 427-440 (2009)
87  const LinearBooleanProblem& problem,
88  SatSolver* solver, std::vector<bool>* solution);
89 
90 // Solves num_times the decision version of the given problem with different
91 // random parameters. Keep the best solution (regarding the objective) and
92 // returns it in solution. The problem is assumed to be already loaded into the
93 // given solver.
95  const LinearBooleanProblem& problem,
96  int num_times, SatSolver* solver,
97  std::vector<bool>* solution);
98 
99 // Starts by solving the decision version of the given LinearBooleanProblem and
100 // then simply add a constraint to find a lower objective that the current best
101 // solution and repeat until the problem becomes unsat.
102 //
103 // The problem is assumed to be already loaded into the given solver. If
104 // solution is initially a feasible solution, the search will starts from there.
105 // solution will be updated with the best solution found so far.
107  const LinearBooleanProblem& problem,
108  SatSolver* solver,
109  std::vector<bool>* solution);
110 
111 // Similar algorithm as the one used by qmaxsat, this is a linear scan with the
112 // at-most k constraint encoded in SAT. This only works on problems with
113 // constant weights.
115  LogBehavior log, const LinearBooleanProblem& problem, SatSolver* solver,
116  std::vector<bool>* solution);
117 
118 // This is an original algorithm. It is a mix between the cardinality encoding
119 // and the Fu & Malik algorithm. It also works on general weighted instances.
121  LogBehavior log, const LinearBooleanProblem& problem, SatSolver* solver,
122  std::vector<bool>* solution);
123 
124 // Model-based API, for now we just provide a basic algorithm that minimizes a
125 // given IntegerVariable by solving a sequence of decision problem by using
126 // SolveIntegerProblem(). Returns the status of the last solved decision
127 // problem.
128 //
129 // The feasible_solution_observer function will be called each time a new
130 // feasible solution is found.
131 //
132 // Note that this function will resume the search from the current state of the
133 // solver, and it is up to the client to backtrack to the root node if needed.
135  IntegerVariable objective_var,
136  const std::function<void()>& feasible_solution_observer, Model* model);
137 
138 // Use a low conflict limit and performs a binary search to try to restrict the
139 // domain of objective_var.
141  IntegerVariable objective_var,
142  const std::function<void()>& feasible_solution_observer, Model* model);
143 
144 // Same as MinimizeIntegerVariableWithLinearScanAndLazyEncoding() but use
145 // a core-based approach instead. Note that the given objective_var is just used
146 // for reporting the lower-bound/upper-bound and do not need to be linked with
147 // its linear representation.
148 //
149 // Unlike MinimizeIntegerVariableWithLinearScanAndLazyEncoding() this function
150 // just return the last solver status. In particular if it is INFEASIBLE but
151 // feasible_solution_observer() was called, it means we are at OPTIMAL.
153  public:
154  CoreBasedOptimizer(IntegerVariable objective_var,
155  const std::vector<IntegerVariable>& variables,
156  const std::vector<IntegerValue>& coefficients,
157  std::function<void()> feasible_solution_observer,
158  Model* model);
159 
160  // TODO(user): Change the algo slighlty to allow resuming from the last
161  // aborted position. Currently, the search is "resumable", but it will restart
162  // some of the work already done, so it might just never find anything.
164 
165  private:
166  CoreBasedOptimizer(const CoreBasedOptimizer&) = delete;
167  CoreBasedOptimizer& operator=(const CoreBasedOptimizer&) = delete;
168 
169  struct ObjectiveTerm {
170  IntegerVariable var;
171  IntegerValue weight;
172  int depth; // Only for logging/debugging.
173  IntegerValue old_var_lb;
174 
175  // An upper bound on the optimal solution if we were to optimize only this
176  // term. This is used by the cover optimization code.
177  IntegerValue cover_ub;
178  };
179 
180  // This will be called each time a feasible solution is found. Returns false
181  // if a conflict was detected while trying to constrain the objective to a
182  // smaller value.
183  bool ProcessSolution();
184 
185  // Use the gap an implied bounds to propagated the bounds of the objective
186  // variables and of its terms.
187  bool PropagateObjectiveBounds();
188 
189  // Heuristic that aim to find the "real" lower bound of the objective on each
190  // core by using a linear scan optimization approach.
191  bool CoverOptimization();
192 
193  // Computes the next stratification threshold.
194  // Sets it to zero if all the assumptions where already considered.
195  void ComputeNextStratificationThreshold();
196 
197  SatParameters* parameters_;
198  SatSolver* sat_solver_;
199  TimeLimit* time_limit_;
200  IntegerTrail* integer_trail_;
201  IntegerEncoder* integer_encoder_;
202  Model* model_; // TODO(user): remove this one.
203 
204  IntegerVariable objective_var_;
205  std::vector<ObjectiveTerm> terms_;
206  IntegerValue stratification_threshold_;
207  std::function<void()> feasible_solution_observer_;
208 
209  // This is used to not add the objective equation more than once if we
210  // solve in "chunk".
211  bool already_switched_to_linear_scan_ = false;
212 
213  // Set to true when we need to abort early.
214  //
215  // TODO(user): This is only used for the stop after first solution parameter
216  // which should likely be handled differently by simply using the normal way
217  // to stop a solver from the feasible solution callback.
218  bool stop_ = false;
219 };
220 
221 // Generalization of the max-HS algorithm (HS stands for Hitting Set). This is
222 // similar to MinimizeWithCoreAndLazyEncoding() but it uses a hybrid approach
223 // with a MIP solver to handle the discovered infeasibility cores.
224 //
225 // See, Jessica Davies and Fahiem Bacchus, "Solving MAXSAT by Solving a
226 // Sequence of Simpler SAT Instances",
227 // http://www.cs.toronto.edu/~jdavies/daviesCP11.pdf"
228 //
229 // Note that an implementation of this approach won the 2016 max-SAT competition
230 // on the industrial category, see
231 // http://maxsat.ia.udl.cat/results/#wpms-industrial
232 //
233 // TODO(user): This function brings dependency to the SCIP MIP solver which is
234 // quite big, maybe we should find a way not to do that.
236  const ObjectiveDefinition& objective_definition,
237  const std::function<void()>& feasible_solution_observer, Model* model);
238 
239 } // namespace sat
240 } // namespace operations_research
241 
242 #endif // OR_TOOLS_SAT_OPTIMIZATION_H_
var
IntVar * var
Definition: expr_array.cc:1858
operations_research::sat::MinimizeCoreWithPropagation
void MinimizeCoreWithPropagation(SatSolver *solver, std::vector< Literal > *core)
Definition: optimization.cc:249
operations_research::sat::STDOUT_LOG
@ STDOUT_LOG
Definition: optimization.h:53
coefficients
std::vector< double > coefficients
Definition: sat/lp_utils.cc:287
operations_research::sat::RestrictObjectiveDomainWithBinarySearch
void RestrictObjectiveDomainWithBinarySearch(IntegerVariable objective_var, const std::function< void()> &feasible_solution_observer, Model *model)
Definition: optimization.cc:1122
operations_research::sat::SolveWithLinearScan
SatSolver::Status SolveWithLinearScan(LogBehavior log, const LinearBooleanProblem &problem, SatSolver *solver, std::vector< bool > *solution)
Definition: optimization.cc:873
operations_research::sat::SolveWithRandomParameters
SatSolver::Status SolveWithRandomParameters(LogBehavior log, const LinearBooleanProblem &problem, int num_times, SatSolver *solver, std::vector< bool > *solution)
Definition: optimization.cc:793
operations_research::sat::CoreBasedOptimizer::CoreBasedOptimizer
CoreBasedOptimizer(IntegerVariable objective_var, const std::vector< IntegerVariable > &variables, const std::vector< IntegerValue > &coefficients, std::function< void()> feasible_solution_observer, Model *model)
Definition: optimization.cc:1341
operations_research::sat::CoreBasedOptimizer
Definition: optimization.h:152
operations_research::sat::MinimizeIntegerVariableWithLinearScanAndLazyEncoding
SatSolver::Status MinimizeIntegerVariableWithLinearScanAndLazyEncoding(IntegerVariable objective_var, const std::function< void()> &feasible_solution_observer, Model *model)
Definition: optimization.cc:1089
weight
int64 weight
Definition: pack.cc:509
model.h
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::sat::IntegerTrail
Definition: integer.h:534
operations_research::sat::LogBehavior
LogBehavior
Definition: optimization.h:53
sat_solver.h
operations_research::sat::Model
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
operations_research::sat::SolveWithWPM1
SatSolver::Status SolveWithWPM1(LogBehavior log, const LinearBooleanProblem &problem, SatSolver *solver, std::vector< bool > *solution)
Definition: optimization.cc:496
sat_base.h
operations_research::sat::CoreBasedOptimizer::Optimize
SatSolver::Status Optimize()
Definition: optimization.cc:1564
operations_research::sat::ObjectiveDefinition
Definition: cp_model_loader.h:38
operations_research::sat::SolveWithFuMalik
SatSolver::Status SolveWithFuMalik(LogBehavior log, const LinearBooleanProblem &problem, SatSolver *solver, std::vector< bool > *solution)
Definition: optimization.cc:299
operations_research::sat::SatSolver
Definition: sat_solver.h:58
operations_research::sat::MinimizeCore
void MinimizeCore(SatSolver *solver, std::vector< Literal > *core)
Definition: optimization.cc:218
operations_research::sat::IntegerEncoder
Definition: integer.h:278
operations_research::sat::MinimizeWithHittingSetAndLazyEncoding
SatSolver::Status MinimizeWithHittingSetAndLazyEncoding(const ObjectiveDefinition &objective_definition, const std::function< void()> &feasible_solution_observer, Model *model)
Definition: optimization.cc:1781
operations_research::TimeLimit
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:105
boolean_problem.pb.h
operations_research::sat::DEFAULT_LOG
@ DEFAULT_LOG
Definition: optimization.h:53
operations_research::sat::SolveWithCardinalityEncoding
SatSolver::Status SolveWithCardinalityEncoding(LogBehavior log, const LinearBooleanProblem &problem, SatSolver *solver, std::vector< bool > *solution)
Definition: optimization.cc:919
operations_research::sat::SatSolver::Status
Status
Definition: sat_solver.h:181
model
GRBmodel * model
Definition: gurobi_interface.cc:195
cp_model_loader.h
integer_search.h
operations_research::sat::SolveWithCardinalityEncodingAndCore
SatSolver::Status SolveWithCardinalityEncodingAndCore(LogBehavior log, const LinearBooleanProblem &problem, SatSolver *solver, std::vector< bool > *solution)
Definition: optimization.cc:987
integer.h