OR-Tools  9.1
lb_tree_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 #ifndef OR_TOOLS_SAT_LB_TREE_SEARCH_H_
15 #define OR_TOOLS_SAT_LB_TREE_SEARCH_H_
16 
17 #include <limits>
18 #include <vector>
19 
20 #include "ortools/sat/integer.h"
22 #include "ortools/sat/sat_base.h"
23 #include "ortools/sat/sat_solver.h"
25 
26 namespace operations_research {
27 namespace sat {
28 
29 // Implement a "classic" MIP tree search by having an exhaustive list of open
30 // nodes.
31 //
32 // The goal of this subsolver is to improve the objective lower bound. It is
33 // meant to be used in a multi-thread portfolio, and as such it really do not
34 // care about finding solution. It is all about improving the lower bound.
35 //
36 // TODO(user): What this is doing is really similar to asking a SAT solver if
37 // the current objective lower bound is reachable by solving a SAT problem.
38 // However, this code handle on the side all the "conflict" of the form
39 // objective > current_lb. As a result, when it is UNSAT, we can bump the lower
40 // bound by a bigger amount than one. We also do not completely loose everything
41 // learned so far for the next iteration.
42 class LbTreeSearch {
43  public:
44  explicit LbTreeSearch(Model* model);
45 
46  // Explores the search space.
48  const std::function<void()>& feasible_solution_observer);
49 
50  private:
51  // Code a binary tree.
52  struct Node {
53  Node(Literal l, IntegerValue lb)
54  : literal(l),
55  objective_lb(lb),
56  true_objective(lb),
57  false_objective(lb) {}
58 
59  // Invariant: the objective bounds only increase.
60  void UpdateObjective() {
61  objective_lb =
62  std::max(objective_lb, std::min(true_objective, false_objective));
63  }
64  void UpdateTrueObjective(IntegerValue v) {
65  true_objective = std::max(true_objective, v);
66  UpdateObjective();
67  }
68  void UpdateFalseObjective(IntegerValue v) {
69  false_objective = std::max(false_objective, v);
70  UpdateObjective();
71  }
72 
73  // The decision for the true and false branch under this node.
74  /*const*/ Literal literal;
75 
76  // The objective lower bound at this node.
77  IntegerValue objective_lb;
78 
79  // The objective lower bound in both branches.
80  // This is only updated when we backtrack over this node.
81  IntegerValue true_objective;
82  IntegerValue false_objective;
83 
84  // Points to adjacent nodes in the tree. Large if no connection.
85  int true_child = std::numeric_limits<int32_t>::max();
86  int false_child = std::numeric_limits<int32_t>::max();
87 
88  // Instead of storing the full reason for an objective LB increase in one
89  // the branches (which can lead to a quadratic memory usage), we stores the
90  // level of the highest decision needed, not counting this node literal.
91  // Basically, the reason for true_objective without {literal} only includes
92  // literal with levels in [0, true_level].
93  //
94  // This allows us to slighlty reduce the size of the overall tree. If both
95  // branches have a low enough level, then we can backjump in the search tree
96  // and skip all the nodes in-between by connecting directly the correct
97  // ancestor to this node. Note that when we do that, the level of the nodes
98  // in the sub-branch change, but this still work.
99  int true_level = std::numeric_limits<int32_t>::max();
100  int false_level = std::numeric_limits<int32_t>::max();
101  };
102 
103  // Returns true if this node objective lb is greater than the root level
104  // objective lower bound.
105  bool NodeImprovesLowerBound(const LbTreeSearch::Node& node);
106 
107  // Model singleton class used here.
108  TimeLimit* time_limit_;
109  ModelRandomGenerator* random_;
110  SatSolver* sat_solver_;
111  IntegerTrail* integer_trail_;
112  SharedResponseManager* shared_response_;
113  SatDecisionPolicy* sat_decision_;
114  IntegerSearchHelper* search_helper_;
115  IntegerVariable objective_var_;
116 
117  // Memory for all the nodes.
118  std::vector<Node> nodes_;
119 
120  // The list of nodes in the current branch, in order from the root.
121  std::vector<int> current_branch_;
122 
123  // Our heuristic used to explore the tree. See code for detail.
124  std::function<BooleanOrIntegerLiteral()> search_heuristic_;
125 };
126 
127 } // namespace sat
128 } // namespace operations_research
129 
130 #endif // OR_TOOLS_SAT_LB_TREE_SEARCH_H_
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:105
int64_t min
Definition: alldiff_cst.cc:139
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
GRBmodel * model
int64_t max
Definition: alldiff_cst.cc:140
SatSolver::Status Search(const std::function< void()> &feasible_solution_observer)
Collection of objects used to extend the Constraint Solver library.
Literal literal
Definition: optimization.cc:85