37 CHECK(objective !=
nullptr);
48bool 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);
233 nodes_[parent].literal));
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);
#define CHECK_EQ(val1, val2)
#define DCHECK_EQ(val1, val2)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
bool BeforeTakingDecision()
bool TakeDecision(Literal decision)
LiteralIndex GetDecision(const std::function< BooleanOrIntegerLiteral()> &f)
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
std::vector< Literal > ReasonFor(IntegerLiteral literal) const
IntegerValue UpperBound(IntegerVariable i) const
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
IntegerValue LowerBound(IntegerVariable i) const
LbTreeSearch(Model *model)
SatSolver::Status Search(const std::function< void()> &feasible_solution_observer)
Class that owns everything related to a particular optimization model.
void UpdateVariableActivityIncrement()
void BumpVariableActivities(const std::vector< Literal > &literals)
const VariablesAssignment & Assignment() const
const Trail & LiteralTrail() const
Status UnsatStatus() const
void Backtrack(int target_level)
bool RestoreSolverToAssumptionLevel()
int CurrentDecisionLevel() const
bool ProblemIsSolved() const
void UpdateInnerObjectiveBounds(const std::string &update_info, IntegerValue lb, IntegerValue ub)
const AssignmentInfo & Info(BooleanVariable var) const
bool LiteralIsAssigned(Literal literal) const
bool LiteralIsTrue(Literal literal) const
bool LiteralIsFalse(Literal literal) const
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::function< BooleanOrIntegerLiteral()> SequentialSearch(std::vector< std::function< BooleanOrIntegerLiteral()> > heuristics)
const LiteralIndex kNoLiteralIndex(-1)
std::function< BooleanOrIntegerLiteral()> SatSolverHeuristic(Model *model)
Collection of objects used to extend the Constraint Solver library.
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
IntegerVariable objective_var