31 for_sorting_(l.Variable()),
38 CHECK(literals_.empty()) <<
"Already initialized";
40 const BooleanVariable first_var_index(solver->
NumVariables());
42 for (
int i = 0; i < n; ++i) {
43 literals_.push_back(
Literal(first_var_index + i,
true));
48 lb_ =
a->lb_ +
b->lb_;
53 for_sorting_ = first_var_index;
58 CHECK(literals_.empty()) <<
"Already initialized";
59 const BooleanVariable first_var_index(solver->
NumVariables());
61 literals_.emplace_back(first_var_index,
true);
64 ub_ =
a->ub_ +
b->ub_;
65 lb_ =
a->lb_ +
b->lb_;
69 for_sorting_ =
std::min(
a->for_sorting_,
b->for_sorting_);
73 CHECK(!literals_.empty());
75 literals_.emplace_back(BooleanVariable(solver->
NumVariables()),
true);
78 literals_[literals_.size() - 2]);
84 while (i < literals_.size() &&
89 literals_.erase(literals_.begin(), literals_.begin() + i);
90 while (!literals_.empty() &&
93 ub_ = lb_ + literals_.size();
104 ub_ = lb_ + literals_.size();
119 std::vector<EncodingNode*> to_process;
120 to_process.push_back(node);
127 const bool complete_encoding =
false;
129 while (!to_process.empty()) {
133 to_process.pop_back();
145 if (
a->current_ub() !=
a->ub()) {
146 CHECK_GE(
a->current_ub() - 1 +
b->lb(), target - 1);
147 if (
a->current_ub() - 1 +
b->lb() < target) {
148 CHECK(
a->IncreaseCurrentUB(solver));
149 to_process.push_back(
a);
154 if (
b->current_ub() !=
b->ub()) {
155 CHECK_GE(
b->current_ub() - 1 +
a->lb(), target - 1);
156 if (
b->current_ub() - 1 +
a->lb() < target) {
157 CHECK(
b->IncreaseCurrentUB(solver));
158 to_process.push_back(
b);
163 for (
int ia =
a->lb(); ia < a->current_ub(); ++ia) {
164 const int ib = target - ia;
165 if (complete_encoding && ib >=
b->lb() && ib < b->current_ub()) {
168 a->GreaterThan(ia),
b->GreaterThan(ib));
170 if (complete_encoding && ib ==
b->ub()) {
175 if (ib - 1 ==
b->lb() - 1) {
177 a->GreaterThan(ia).Negated());
179 if ((ib - 1) >=
b->lb() && (ib - 1) <
b->current_ub()) {
182 a->GreaterThan(ia).Negated(),
183 b->GreaterThan(ib - 1).Negated());
189 const int ib = target - (
a->lb() - 1);
190 if ((ib - 1) ==
b->lb() - 1) {
193 if ((ib - 1) >=
b->lb() && (ib - 1) <
b->current_ub()) {
195 b->GreaterThan(ib - 1).Negated());
201 const int ib = target -
a->ub();
202 if (complete_encoding && ib >=
b->lb() && ib <
b->current_ub()) {
219 for (
int ia = 0; ia <
a->size(); ++ia) {
220 if (ia +
b->size() < size) {
231 for (
int ib = 0; ib <
b->size(); ++ib) {
232 if (ib +
a->size() < size) {
243 for (
int ia = 0; ia <
a->size(); ++ia) {
244 for (
int ib = 0; ib <
b->size(); ++ib) {
245 if (ia + ib < size) {
250 if (ia + ib + 1 < size) {
253 a->literal(ia).Negated(),
254 b->literal(ib).Negated());
257 b->literal(ib).Negated());
265 const std::vector<EncodingNode*>&
nodes,
267 std::deque<EncodingNode>* repository) {
268 std::deque<EncodingNode*> dq(
nodes.begin(),
nodes.end());
269 while (dq.size() > 1) {
275 dq.push_back(&repository->back());
281 struct SortEncodingNodePointers {
282 bool operator()(EncodingNode*
a, EncodingNode*
b)
const {
return *
a < *
b; }
288 std::deque<EncodingNode>* repository) {
289 std::priority_queue<EncodingNode*, std::vector<EncodingNode*>,
290 SortEncodingNodePointers>
292 while (pq.size() > 1) {
298 pq.push(&repository->back());
304 const std::vector<Literal>& literals,
305 const std::vector<Coefficient>& coeffs, Coefficient* offset,
306 std::deque<EncodingNode>* repository) {
307 CHECK_EQ(literals.size(), coeffs.size());
309 std::vector<EncodingNode*>
nodes;
310 for (
int i = 0; i < literals.size(); ++i) {
313 repository->emplace_back(literals[i]);
314 nodes.push_back(&repository->back());
315 nodes.back()->set_weight(coeffs[i]);
317 repository->emplace_back(literals[i].Negated());
318 nodes.push_back(&repository->back());
319 nodes.back()->set_weight(-coeffs[i]);
322 *offset -= coeffs[i];
329 const LinearObjective& objective_proto, Coefficient* offset,
330 std::deque<EncodingNode>* repository) {
332 std::vector<EncodingNode*>
nodes;
333 for (
int i = 0; i < objective_proto.literals_size(); ++i) {
337 if (objective_proto.coefficients(i) > 0) {
338 repository->emplace_back(
literal);
339 nodes.push_back(&repository->back());
340 nodes.back()->set_weight(Coefficient(objective_proto.coefficients(i)));
343 nodes.push_back(&repository->back());
344 nodes.back()->set_weight(Coefficient(-objective_proto.coefficients(i)));
347 *offset -= objective_proto.coefficients(i);
355 bool EncodingNodeByWeight(
const EncodingNode*
a,
const EncodingNode*
b) {
356 return a->weight() <
b->weight();
359 bool EncodingNodeByDepth(
const EncodingNode*
a,
const EncodingNode*
b) {
360 return a->depth() <
b->depth();
363 bool EmptyEncodingNode(
const EncodingNode*
a) {
return a->size() == 0; }
368 Coefficient
upper_bound, Coefficient stratified_lower_bound,
382 if (gap <= 0)
return {};
384 n->ApplyUpperBound((gap / n->weight()).value(), solver);
389 nodes->erase(std::remove_if(
nodes->begin(),
nodes->end(), EmptyEncodingNode),
393 switch (solver->
parameters().max_sat_assumption_order()) {
394 case SatParameters::DEFAULT_ASSUMPTION_ORDER:
396 case SatParameters::ORDER_ASSUMPTION_BY_DEPTH:
397 std::sort(
nodes->begin(),
nodes->end(), EncodingNodeByDepth);
399 case SatParameters::ORDER_ASSUMPTION_BY_WEIGHT:
400 std::sort(
nodes->begin(),
nodes->end(), EncodingNodeByWeight);
403 if (solver->
parameters().max_sat_reverse_assumption_order()) {
410 std::vector<Literal> assumptions;
412 if (n->weight() >= stratified_lower_bound) {
413 assumptions.push_back(n->literal(0).Negated());
420 const std::vector<Literal>& core) {
423 for (
int i = 0; i < core.size(); ++i) {
436 Coefficient result(0);
440 result =
std::max(result, n->weight());
446 void ProcessCore(
const std::vector<Literal>& core, Coefficient min_weight,
447 std::deque<EncodingNode>* repository,
452 if (core.size() == 1) {
457 if (n->literal(0).Negated() == core[0]) {
462 LOG(
FATAL) <<
"Node with literal " << core[0] <<
" not found!";
468 int new_node_index = 0;
469 std::vector<EncodingNode*> to_merge;
470 for (
int i = 0; i < core.size(); ++i) {
474 for (; (*nodes)[
index]->literal(0).Negated() != core[i]; ++
index) {
476 (*nodes)[new_node_index] = (*nodes)[
index];
489 (*nodes)[new_node_index] = (*nodes)[
index];
495 (*nodes)[new_node_index] = (*nodes)[
index];
498 nodes->resize(new_node_index);
501 nodes->back()->set_weight(min_weight);
#define CHECK_LT(val1, val2)
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
#define CHECK_GT(val1, val2)
int Reduce(const SatSolver &solver)
EncodingNode * child_a() const
bool IncreaseCurrentUB(SatSolver *solver)
void ApplyUpperBound(int64_t upper_bound, SatSolver *solver)
void InitializeLazyNode(EncodingNode *a, EncodingNode *b, SatSolver *solver)
void InitializeFullNode(int n, EncodingNode *a, EncodingNode *b, SatSolver *solver)
Literal literal(int i) const
EncodingNode * child_b() const
Literal GreaterThan(int i) const
void SetNumVariables(int num_variables)
bool AddTernaryClause(Literal a, Literal b, Literal c)
const SatParameters & parameters() const
const VariablesAssignment & Assignment() const
bool AddBinaryClause(Literal a, Literal b)
void Backtrack(int target_level)
bool AddUnitClause(Literal true_literal)
bool LiteralIsTrue(Literal literal) const
bool LiteralIsFalse(Literal literal) const
Coefficient ComputeCoreMinWeight(const std::vector< EncodingNode * > &nodes, const std::vector< Literal > &core)
EncodingNode * MergeAllNodesWithDeque(Coefficient upper_bound, const std::vector< EncodingNode * > &nodes, SatSolver *solver, std::deque< EncodingNode > *repository)
std::vector< Literal > ReduceNodesAndExtractAssumptions(Coefficient upper_bound, Coefficient stratified_lower_bound, Coefficient *lower_bound, std::vector< EncodingNode * > *nodes, SatSolver *solver)
EncodingNode * LazyMergeAllNodeWithPQ(const std::vector< EncodingNode * > &nodes, SatSolver *solver, std::deque< EncodingNode > *repository)
void IncreaseNodeSize(EncodingNode *node, SatSolver *solver)
EncodingNode LazyMerge(EncodingNode *a, EncodingNode *b, SatSolver *solver)
EncodingNode FullMerge(Coefficient upper_bound, EncodingNode *a, EncodingNode *b, SatSolver *solver)
void ProcessCore(const std::vector< Literal > &core, Coefficient min_weight, std::deque< EncodingNode > *repository, std::vector< EncodingNode * > *nodes, SatSolver *solver)
Coefficient MaxNodeWeightSmallerThan(const std::vector< EncodingNode * > &nodes, Coefficient upper_bound)
std::vector< EncodingNode * > CreateInitialEncodingNodes(const std::vector< Literal > &literals, const std::vector< Coefficient > &coeffs, Coefficient *offset, std::deque< EncodingNode > *repository)
const Coefficient kCoefficientMax(std::numeric_limits< Coefficient::ValueType >::max())
Collection of objects used to extend the Constraint Solver library.