103 CHECK_GE(nodes.size(), 2);
104 CHECK(literals_.empty()) <<
"Already initialized";
106 const Literal new_literal(var,
true);
107 literals_.push_back(new_literal);
114 std::vector<Literal> clause{new_literal.
Negated()};
117 clause.push_back(node->literals_[0]);
119 depth_ = std::max(node->depth_ + 1, depth_);
120 for_sorting_ = std::min(for_sorting_, node->for_sorting_);
503void ReduceNodes(Coefficient upper_bound, Coefficient* lower_bound,
504 std::vector<EncodingNode*>* nodes,
SatSolver* solver) {
510 *lower_bound += n->Reduce(*solver);
516 const Coefficient gap = upper_bound - *lower_bound;
522 n->ApplyWeightUpperBound(gap, solver);
527 nodes->erase(std::remove_if(nodes->begin(), nodes->end(),
532 switch (solver->
parameters().max_sat_assumption_order()) {
533 case SatParameters::DEFAULT_ASSUMPTION_ORDER:
535 case SatParameters::ORDER_ASSUMPTION_BY_DEPTH:
536 std::sort(nodes->begin(), nodes->end(), EncodingNodeByDepth);
538 case SatParameters::ORDER_ASSUMPTION_BY_WEIGHT:
539 std::sort(nodes->begin(), nodes->end(), EncodingNodeByWeight);
542 if (solver->
parameters().max_sat_reverse_assumption_order()) {
545 std::reverse(nodes->begin(), nodes->end());
589 Coefficient min_weight, Coefficient gap,
592 if (!sat_solver_->ResetToLevelZero())
return false;
593 if (core.size() == 1) {
594 return sat_solver_->AddUnitClause(core[0].Negated());
598 std::vector<EncodingNode*> to_merge;
601 std::vector<EncodingNode*> new_nodes;
602 for (
int i = 0;
i < core.size(); ++
i) {
606 for (; !nodes_[index]->AssumptionIs(core[
i]); ++index) {
607 CHECK_LT(index, nodes_.size());
608 new_nodes.push_back(nodes_[index]);
610 CHECK_LT(index, nodes_.size());
614 if (alternative_encoding_ && node->
ub() > node->
lb() + 1) {
618 new_nodes.push_back(node);
621 repository_.push_back(
623 repository_.back().set_depth(node->
depth());
624 node = &repository_.back();
627 to_merge.push_back(node);
634 if (node->
weight() > min_weight) {
636 new_nodes.push_back(node);
640 for (; index < nodes_.size(); ++index) {
641 new_nodes.push_back(nodes_[index]);
649 bool in_exactly_one = (2 * min_weight) > gap;
655 if (!in_exactly_one) {
657 std::vector<Literal> bool_nodes;
658 absl::flat_hash_map<LiteralIndex, int> node_indices;
659 for (
int i = 0;
i < to_merge.size(); ++
i) {
662 if (node.
size() != 1)
continue;
663 if (node.
ub() != node.
lb() + 1)
continue;
665 if (node_indices.contains(node.
literal(0).
Index()))
continue;
667 bool_nodes.push_back(node.
literal(0));
673 std::vector<int> buffer;
674 std::vector<absl::Span<const Literal>> decomposition;
675 if (params_.core_minimization_level() > 1 && bool_nodes.size() < 300 &&
676 bool_nodes.size() > 1) {
677 const auto& assignment = sat_solver_->Assignment();
678 const int size = bool_nodes.size();
679 std::vector<std::vector<int>> graph(size);
680 for (
int i = 0;
i < size; ++
i) {
681 if (!sat_solver_->ResetToLevelZero())
return false;
682 if (!sat_solver_->EnqueueDecisionIfNotConflicting(bool_nodes[
i])) {
686 for (
int j = 0; j < size; ++j) {
687 if (
i == j)
continue;
688 if (assignment.LiteralIsFalse(bool_nodes[j])) {
689 graph[
i].push_back(j);
692 graph[j].push_back(
i);
701 if (!sat_solver_->ResetToLevelZero())
return false;
703 for (std::vector<int>& adj : graph) {
706 const std::vector<absl::Span<int>> index_decompo =
710 std::vector<Literal> new_order;
711 for (
const int i : buffer) new_order.push_back(bool_nodes[
i]);
712 bool_nodes = new_order;
713 for (
const auto span : index_decompo) {
714 if (span.size() == 1)
continue;
715 decomposition.push_back(absl::MakeSpan(
716 bool_nodes.data() + (span.data() - buffer.data()), span.size()));
719 decomposition = implications_->HeuristicAmoPartition(&bool_nodes);
723 if (decomposition.size() == 1 && decomposition[0].size() == core.size()) {
724 in_exactly_one =
true;
727 int num_in_decompo = 0;
728 if (!in_exactly_one) {
729 for (
const auto amo : decomposition) {
730 num_in_decompo += amo.size();
733 std::vector<EncodingNode*> amo_nodes;
735 const int index = node_indices.at(l.Index());
736 amo_nodes.push_back(to_merge[index]);
737 to_merge[index] =
nullptr;
745 to_merge.push_back(n);
747 if (num_in_decompo > 0) {
748 absl::StrAppend(info,
" amo:", decomposition.size(),
749 " lit:", num_in_decompo);
755 if (node ==
nullptr)
continue;
756 to_merge[new_size++] = node;
758 to_merge.resize(new_size);
765 if (in_exactly_one) {
768 node->TransformToBoolean(sat_solver_);
771 absl::StrAppend(info,
" exo");
773 nodes_.push_back(&repository_.back());
778 std::vector<LiteralWithCoeff> cst;
779 cst.reserve(core.size());
781 cst.emplace_back(l.Negated(), Coefficient(1));
783 sat_solver_->AddLinearConstraint(
784 true, Coefficient(1),
785 true, Coefficient(1), &cst);
786 return !sat_solver_->ModelIsUnsat();
790 min_weight, to_merge, sat_solver_, &repository_));
791 absl::StrAppend(info,
" d:", nodes_.back()->depth());
792 return !sat_solver_->ModelIsUnsat();