37 CHECK(objective !=
nullptr);
48 bool LbTreeSearch::NodeImprovesLowerBound(
const Node& node) {
49 return node.objective_lb >
54 const std::function<
void()>& feasible_solution_observer) {
68 int64_t restart = 100;
69 int64_t num_restart = 1;
70 const int kNumRestart = 10;
78 if (integer_trail_->
LowerBound(objective_var_) >
80 std::vector<Literal> reason =
82 objective_var_, integer_trail_->
LowerBound(objective_var_)));
90 if (current_branch_.size() == current_level) {
93 Node& node = nodes_[current_branch_.back()];
94 for (
const Literal l : reason) {
95 if (l.Variable() == node.literal.Variable())
continue;
96 max_level = std::max<int>(
100 node.true_level =
std::min(node.true_level, max_level);
103 node.false_level =
std::min(node.false_level, max_level);
105 const int level =
std::max(node.true_level, node.false_level);
106 if (level < current_level - 1) {
110 Node& ancestor = nodes_[current_branch_[level - 1]];
112 ancestor.true_child = current_branch_.back();
113 ancestor.UpdateTrueObjective(node.objective_lb);
116 ancestor.false_child = current_branch_.back();
117 ancestor.UpdateFalseObjective(node.objective_lb);
119 current_branch_.resize(level);
121 const Node copy = node;
123 current_branch_ = {0};
134 if (nodes_.size() > num_restart * restart && num_restart < kNumRestart) {
136 current_branch_.clear();
156 (current_branch_.size() > 1 &&
157 NodeImprovesLowerBound(nodes_[current_branch_.back()]))) {
158 const int child = current_branch_.back();
159 current_branch_.pop_back();
162 CHECK(!current_branch_.empty());
163 Node& node = nodes_[current_branch_.back()];
164 if (node.true_child == child) {
165 node.UpdateTrueObjective(nodes_[child].objective_lb);
168 node.UpdateFalseObjective(nodes_[child].objective_lb);
174 std::max(0, static_cast<int>(current_branch_.size()) - 1));
181 if (NodeImprovesLowerBound(nodes_[current_branch_[0]])) {
183 absl::StrCat(
"lb_tree_search #nodes:", nodes_.size()),
184 nodes_[current_branch_[0]].objective_lb,
188 objective_var_, nodes_[current_branch_[0]].objective_lb),
200 Node& node = nodes_[current_branch_.back()];
201 node.objective_lb =
std::max(node.objective_lb,
203 node.UpdateTrueObjective(node.objective_lb);
204 node.UpdateFalseObjective(node.objective_lb);
205 if (NodeImprovesLowerBound(node))
break;
216 new_lb = node.true_objective;
218 n = node.false_child;
219 new_lb = node.false_objective;
223 current_branch_.pop_back();
226 if (!current_branch_.empty()) {
227 const int parent = current_branch_.back();
229 nodes_[parent].true_child = n;
230 nodes_[parent].UpdateTrueObjective(new_lb);
234 nodes_[parent].false_child = n;
235 nodes_[parent].UpdateFalseObjective(new_lb);
237 if (NodeImprovesLowerBound(nodes_[parent]))
break;
241 bool choose_true = node.true_objective < node.false_objective;
242 if (node.true_objective == node.false_objective) {
243 choose_true = absl::Bernoulli(*random_, 0.5);
253 n = node.false_child;
268 node.UpdateTrueObjective(integer_trail_->
LowerBound(objective_var_));
270 node.UpdateFalseObjective(integer_trail_->
LowerBound(objective_var_));
272 if (NodeImprovesLowerBound(node))
break;
273 if (integer_trail_->
LowerBound(objective_var_) >
279 if (n < nodes_.size()) {
280 current_branch_.push_back(n);
288 (!current_branch_.empty() &&
289 NodeImprovesLowerBound(nodes_[current_branch_.back()]))) {
306 if (integer_trail_->
LowerBound(objective_var_) >
312 const LiteralIndex decision =
318 feasible_solution_observer();
324 const int n = nodes_.size();
325 nodes_.emplace_back(
Literal(decision),
327 if (!current_branch_.empty()) {
328 const int parent = current_branch_.back();
330 nodes_[parent].true_child = n;
331 nodes_[parent].UpdateTrueObjective(nodes_.back().objective_lb);
334 nodes_[parent].false_child = n;
335 nodes_[parent].UpdateFalseObjective(nodes_.back().objective_lb);
338 current_branch_.push_back(n);
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Class that owns everything related to a particular optimization model.
void UpdateVariableActivityIncrement()
IntegerValue LowerBound(IntegerVariable i) const
bool LiteralIsFalse(Literal literal) const
bool LiteralIsTrue(Literal literal) const
LbTreeSearch(Model *model)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::vector< Literal > ReasonFor(IntegerLiteral literal) const
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
std::function< BooleanOrIntegerLiteral()> SatSolverHeuristic(Model *model)
void UpdateInnerObjectiveBounds(const std::string &update_info, IntegerValue lb, IntegerValue ub)
Status UnsatStatus() const
bool ProblemIsSolved() const
bool LiteralIsAssigned(Literal literal) const
IntegerVariable objective_var
void Backtrack(int target_level)
bool BeforeTakingDecision()
#define CHECK_EQ(val1, val2)
bool RestoreSolverToAssumptionLevel()
const VariablesAssignment & Assignment() const
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
#define DCHECK_EQ(val1, val2)
void BumpVariableActivities(const std::vector< Literal > &literals)
SatSolver::Status Search(const std::function< void()> &feasible_solution_observer)
IntegerValue UpperBound(IntegerVariable i) const
int CurrentDecisionLevel() const
Collection of objects used to extend the Constraint Solver library.
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
const LiteralIndex kNoLiteralIndex(-1)
const Trail & LiteralTrail() const
bool TakeDecision(Literal decision)
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
const AssignmentInfo & Info(BooleanVariable var) const
std::function< BooleanOrIntegerLiteral()> SequentialSearch(std::vector< std::function< BooleanOrIntegerLiteral()>> heuristics)
LiteralIndex GetDecision(const std::function< BooleanOrIntegerLiteral()> &f)