30 for_sorting_(l.Variable()),
37 CHECK(literals_.empty()) <<
"Already initialized";
39 const BooleanVariable first_var_index(solver->
NumVariables());
41 for (
int i = 0; i < n; ++i) {
42 literals_.push_back(
Literal(first_var_index + i,
true));
47 lb_ =
a->lb_ +
b->lb_;
52 for_sorting_ = first_var_index;
57 CHECK(literals_.empty()) <<
"Already initialized";
58 const BooleanVariable first_var_index(solver->
NumVariables());
60 literals_.emplace_back(first_var_index,
true);
63 ub_ =
a->ub_ +
b->ub_;
64 lb_ =
a->lb_ +
b->lb_;
68 for_sorting_ =
std::min(
a->for_sorting_,
b->for_sorting_);
72 CHECK(!literals_.empty());
74 literals_.emplace_back(BooleanVariable(solver->
NumVariables()),
true);
77 literals_[literals_.size() - 2]);
83 while (i < literals_.size() &&
88 literals_.erase(literals_.begin(), literals_.begin() + i);
89 while (!literals_.empty() &&
92 ub_ = lb_ + literals_.size();
98 if (
size() <= upper_bound)
return;
99 for (
int i = upper_bound; i <
size(); ++i) {
102 literals_.resize(upper_bound);
103 ub_ = lb_ + literals_.size();
118 std::vector<EncodingNode*> to_process;
119 to_process.push_back(node);
126 const bool complete_encoding =
false;
128 while (!to_process.empty()) {
132 to_process.pop_back();
144 if (
a->current_ub() !=
a->ub()) {
145 CHECK_GE(
a->current_ub() - 1 +
b->lb(), target - 1);
146 if (
a->current_ub() - 1 +
b->lb() < target) {
147 CHECK(
a->IncreaseCurrentUB(solver));
148 to_process.push_back(
a);
153 if (
b->current_ub() !=
b->ub()) {
154 CHECK_GE(
b->current_ub() - 1 +
a->lb(), target - 1);
155 if (
b->current_ub() - 1 +
a->lb() < target) {
156 CHECK(
b->IncreaseCurrentUB(solver));
157 to_process.push_back(
b);
162 for (
int ia =
a->lb(); ia < a->current_ub(); ++ia) {
163 const int ib = target - ia;
164 if (complete_encoding && ib >=
b->lb() && ib < b->current_ub()) {
167 a->GreaterThan(ia),
b->GreaterThan(ib));
169 if (complete_encoding && ib ==
b->ub()) {
174 if (ib - 1 ==
b->lb() - 1) {
176 a->GreaterThan(ia).Negated());
178 if ((ib - 1) >=
b->lb() && (ib - 1) <
b->current_ub()) {
181 a->GreaterThan(ia).Negated(),
182 b->GreaterThan(ib - 1).Negated());
188 const int ib = target - (
a->lb() - 1);
189 if ((ib - 1) ==
b->lb() - 1) {
192 if ((ib - 1) >=
b->lb() && (ib - 1) <
b->current_ub()) {
194 b->GreaterThan(ib - 1).Negated());
200 const int ib = target -
a->ub();
201 if (complete_encoding && ib >=
b->lb() && ib <
b->current_ub()) {
216 std::min(Coefficient(
a->size() +
b->size()), upper_bound).value();
218 for (
int ia = 0; ia <
a->size(); ++ia) {
219 if (ia +
b->size() < size) {
230 for (
int ib = 0; ib <
b->size(); ++ib) {
231 if (ib +
a->size() < size) {
242 for (
int ia = 0; ia <
a->size(); ++ia) {
243 for (
int ib = 0; ib <
b->size(); ++ib) {
244 if (ia + ib < size) {
249 if (ia + ib + 1 < size) {
252 a->literal(ia).Negated(),
253 b->literal(ib).Negated());
256 b->literal(ib).Negated());
264 const std::vector<EncodingNode*>& nodes,
266 std::deque<EncodingNode>* repository) {
267 std::deque<EncodingNode*> dq(nodes.begin(), nodes.end());
268 while (dq.size() > 1) {
273 repository->push_back(
FullMerge(upper_bound,
a,
b, solver));
274 dq.push_back(&repository->back());
280 struct SortEncodingNodePointers {
281 bool operator()(EncodingNode*
a, EncodingNode*
b)
const {
return *
a < *
b; }
287 std::deque<EncodingNode>* repository) {
288 std::priority_queue<EncodingNode*, std::vector<EncodingNode*>,
289 SortEncodingNodePointers>
290 pq(nodes.begin(), nodes.end());
291 while (pq.size() > 1) {
297 pq.push(&repository->back());
303 const std::vector<Literal>& literals,
304 const std::vector<Coefficient>& coeffs, Coefficient* offset,
305 std::deque<EncodingNode>* repository) {
306 CHECK_EQ(literals.size(), coeffs.size());
308 std::vector<EncodingNode*> nodes;
309 for (
int i = 0; i < literals.size(); ++i) {
312 repository->emplace_back(literals[i]);
313 nodes.push_back(&repository->back());
314 nodes.back()->set_weight(coeffs[i]);
316 repository->emplace_back(literals[i].Negated());
317 nodes.push_back(&repository->back());
318 nodes.back()->set_weight(-coeffs[i]);
321 *offset -= coeffs[i];
328 const LinearObjective& objective_proto, Coefficient* offset,
329 std::deque<EncodingNode>* repository) {
331 std::vector<EncodingNode*> nodes;
332 for (
int i = 0; i < objective_proto.literals_size(); ++i) {
336 if (objective_proto.coefficients(i) > 0) {
337 repository->emplace_back(
literal);
338 nodes.push_back(&repository->back());
339 nodes.back()->set_weight(Coefficient(objective_proto.coefficients(i)));
342 nodes.push_back(&repository->back());
343 nodes.back()->set_weight(Coefficient(-objective_proto.coefficients(i)));
346 *offset -= objective_proto.coefficients(i);
354 bool EncodingNodeByWeight(
const EncodingNode*
a,
const EncodingNode*
b) {
355 return a->weight() <
b->weight();
358 bool EncodingNodeByDepth(
const EncodingNode*
a,
const EncodingNode*
b) {
359 return a->depth() <
b->depth();
362 bool EmptyEncodingNode(
const EncodingNode*
a) {
return a->size() == 0; }
367 Coefficient upper_bound, Coefficient stratified_lower_bound,
368 Coefficient* lower_bound, std::vector<EncodingNode*>* nodes,
375 *lower_bound += n->Reduce(*solver) * n->weight();
380 const Coefficient gap = upper_bound - *lower_bound;
381 if (gap <= 0)
return {};
383 n->ApplyUpperBound((gap / n->weight()).value(), solver);
388 nodes->erase(std::remove_if(nodes->begin(), nodes->end(), EmptyEncodingNode),
392 switch (solver->
parameters().max_sat_assumption_order()) {
393 case SatParameters::DEFAULT_ASSUMPTION_ORDER:
395 case SatParameters::ORDER_ASSUMPTION_BY_DEPTH:
396 std::sort(nodes->begin(), nodes->end(), EncodingNodeByDepth);
398 case SatParameters::ORDER_ASSUMPTION_BY_WEIGHT:
399 std::sort(nodes->begin(), nodes->end(), EncodingNodeByWeight);
402 if (solver->
parameters().max_sat_reverse_assumption_order()) {
405 std::reverse(nodes->begin(), nodes->end());
409 std::vector<Literal> assumptions;
411 if (n->weight() >= stratified_lower_bound) {
412 assumptions.push_back(n->literal(0).Negated());
419 const std::vector<Literal>& core) {
422 for (
int i = 0; i < core.size(); ++i) {
434 Coefficient upper_bound) {
435 Coefficient result(0);
438 if (n->weight() < upper_bound) {
439 result =
std::max(result, n->weight());
445 void ProcessCore(
const std::vector<Literal>& core, Coefficient min_weight,
446 std::deque<EncodingNode>* repository,
447 std::vector<EncodingNode*>* nodes,
SatSolver* solver) {
451 if (core.size() == 1) {
456 if (n->literal(0).Negated() == core[0]) {
461 LOG(
FATAL) <<
"Node with literal " << core[0] <<
" not found!";
467 int new_node_index = 0;
468 std::vector<EncodingNode*> to_merge;
469 for (
int i = 0; i < core.size(); ++i) {
473 for (; (*nodes)[
index]->literal(0).Negated() != core[i]; ++
index) {
475 (*nodes)[new_node_index] = (*nodes)[
index];
479 to_merge.push_back((*nodes)[
index]);
488 (*nodes)[new_node_index] = (*nodes)[
index];
494 (*nodes)[new_node_index] = (*nodes)[
index];
497 nodes->resize(new_node_index);
500 nodes->back()->set_weight(min_weight);