OR-Tools  9.6
lb_tree_search.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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 <stdint.h>
18 
19 #include <algorithm>
20 #include <functional>
21 #include <limits>
22 #include <string>
23 #include <vector>
24 
25 #include "absl/strings/string_view.h"
26 #include "absl/time/time.h"
28 #include "ortools/sat/integer.h"
31 #include "ortools/sat/model.h"
32 #include "ortools/sat/sat_base.h"
34 #include "ortools/sat/sat_parameters.pb.h"
35 #include "ortools/sat/sat_solver.h"
37 #include "ortools/sat/util.h"
40 
41 namespace operations_research {
42 namespace sat {
43 
44 // Implement a "classic" MIP tree search by having an exhaustive list of open
45 // nodes.
46 //
47 // The goal of this subsolver is to improve the objective lower bound. It is
48 // meant to be used in a multi-thread portfolio, and as such it really do not
49 // care about finding solution. It is all about improving the lower bound.
50 //
51 // TODO(user): What this is doing is really similar to asking a SAT solver if
52 // the current objective lower bound is reachable by solving a SAT problem.
53 // However, this code handle on the side all the "conflict" of the form
54 // objective > current_lb. As a result, when it is UNSAT, we can bump the lower
55 // bound by a bigger amount than one. We also do not completely loose everything
56 // learned so far for the next iteration.
57 class LbTreeSearch {
58  public:
59  explicit LbTreeSearch(Model* model);
60 
61  // Explores the search space.
63  const std::function<void()>& feasible_solution_observer);
64 
65  private:
66  // Code a binary tree.
67  DEFINE_STRONG_INDEX_TYPE(NodeIndex);
68  struct Node {
69  Node(Literal l, IntegerValue lb)
70  : literal(l), true_objective(lb), false_objective(lb) {}
71 
72  // The objective lower bound at this node.
73  IntegerValue MinObjective() const {
74  return std::min(true_objective, false_objective);
75  }
76 
77  // Invariant: the objective bounds only increase.
78  void UpdateObjective(IntegerValue v) {
79  true_objective = std::max(true_objective, v);
80  false_objective = std::max(false_objective, v);
81  }
82  void UpdateTrueObjective(IntegerValue v) {
83  true_objective = std::max(true_objective, v);
84  }
85  void UpdateFalseObjective(IntegerValue v) {
86  false_objective = std::max(false_objective, v);
87  }
88 
89  // The decision for the true and false branch under this node.
90  /*const*/ Literal literal;
91 
92  // The objective lower bound in both branches.
93  IntegerValue true_objective;
94  IntegerValue false_objective;
95 
96  // Points to adjacent nodes in the tree. Large if no connection.
99 
100  // Indicates if this nodes was removed from the tree.
101  bool is_deleted = false;
102  };
103 
104  // Display the current tree, this is mainly here to investigate ideas to
105  // improve the code.
106  void DebugDisplayTree(NodeIndex root) const;
107 
108  // Updates the objective of the node in the current branch at level n from
109  // the one at level n - 1.
110  void UpdateObjectiveFromParent(int level);
111 
112  // Updates the objective of the node in the current branch at level n - 1 from
113  // the one at level n.
114  void UpdateParentObjective(int level);
115 
116  // Returns false on conflict.
117  bool FullRestart();
118 
119  // Mark the given node as deleted. Its literal is assumed to be set. We also
120  // delete the subtree that is not longer relevant.
121  void MarkAsDeletedNodeAndUnreachableSubtree(Node& node);
122  void MarkSubtreeAsDeleted(NodeIndex root);
123 
124  // Create a new node at the end of the current branch.
125  // This assume the last decision in the branch is assigned.
126  void AppendNewNodeToCurrentBranch(Literal decision);
127 
128  // Update the bounds on the given nodes by using reduced costs if possible.
129  void ExploitReducedCosts(NodeIndex n);
130 
131  // Returns a small number of decision needed to reach the same conflict.
132  // We basically reduce the number of decision at each level to 1.
133  std::vector<Literal> ExtractDecisions(int base_level,
134  const std::vector<Literal>& conflict);
135 
136  // Used in the solve logs.
137  std::string SmallProgressString() const;
138 
139  // Model singleton class used here.
140  TimeLimit* time_limit_;
141  ModelRandomGenerator* random_;
142  SatSolver* sat_solver_;
143  IntegerEncoder* integer_encoder_;
144  Trail* trail_;
145  IntegerTrail* integer_trail_;
146  GenericLiteralWatcher* watcher_;
147  SharedResponseManager* shared_response_;
148  SatDecisionPolicy* sat_decision_;
149  IntegerSearchHelper* search_helper_;
150  IntegerVariable objective_var_;
151  const SatParameters& parameters_;
152 
153  // This can stay null. Otherwise it will be the lp constraint with
154  // objective_var_ as objective.
155  LinearProgrammingConstraint* lp_constraint_ = nullptr;
156 
157  // We temporarily cache the shared_response_ objective lb here.
158  IntegerValue current_objective_lb_;
159 
160  // Memory for all the nodes.
161  int num_nodes_in_tree_ = 0;
163 
164  // The list of nodes in the current branch, in order from the root.
165  std::vector<NodeIndex> current_branch_;
166 
167  // Our heuristic used to explore the tree. See code for detail.
168  std::function<BooleanOrIntegerLiteral()> search_heuristic_;
169 
170  int64_t num_rc_detected_ = 0;
171 
172  // Counts the number of decisions we are taking while exploring the search
173  // tree.
174  int64_t num_decisions_taken_ = 0;
175 
176  // Used to trigger the initial restarts and imports.
177  int num_full_restarts_ = 0;
178  int64_t num_decisions_taken_at_last_restart_ = 0;
179  int64_t num_decisions_taken_at_last_level_zero_ = 0;
180 
181  // Count the number of time we are back to decision level zero.
182  int64_t num_back_to_root_node_ = 0;
183 
184  // Used to display periodic info to the log.
185  absl::Time last_logging_time_;
186 };
187 
188 } // namespace sat
189 } // namespace operations_research
190 
191 #endif // OR_TOOLS_SAT_LB_TREE_SEARCH_H_
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:106
SatSolver::Status Search(const std::function< void()> &feasible_solution_observer)
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:42
GRBmodel * model
Collection of objects used to extend the Constraint Solver library.
Literal literal
Definition: optimization.cc:88