23#include "absl/container/flat_hash_map.h" 
   24#include "absl/hash/hash.h" 
   25#include "absl/log/check.h" 
   26#include "absl/strings/str_format.h" 
   27#include "absl/types/span.h" 
   43  return a.literal.Index() < 
b.literal.Index();
 
   47  if (a.coefficient == 
b.coefficient) {
 
   48    return a.literal.Index() < 
b.literal.Index();
 
   50  return a.coefficient < 
b.coefficient;
 
   56    std::vector<LiteralWithCoeff>* cst, Coefficient* bound_shift,
 
   57    Coefficient* max_value) {
 
   65  std::sort(cst->begin(), cst->end(), LiteralComparator);
 
   68  for (
int i = 0; 
i < cst->size(); ++
i) {
 
   71    if (representative != 
nullptr &&
 
   86      if (representative != 
nullptr && representative->
coefficient == 0) {
 
   89      (*cst)[index] = current;
 
   90      representative = &((*cst)[index]);
 
   94  if (representative != 
nullptr && representative->
coefficient == 0) {
 
  101  for (
int i = 0; 
i < cst->size(); ++
i) {
 
  108    if (!
SafeAddInto((*cst)[
i].coefficient, max_value)) 
return false;
 
  112  std::sort(cst->begin(), cst->end(), CoeffComparator);
 
  113  DCHECK_GE(*max_value, 0);
 
 
  119    std::vector<LiteralWithCoeff>* cst, Coefficient* bound_shift,
 
  120    Coefficient* max_value) {
 
  122  Coefficient shift_due_to_fixed_variables(0);
 
  124    if (mapping[entry.literal] >= 0) {
 
  129      if (!
SafeAddInto(-entry.coefficient, &shift_due_to_fixed_variables)) {
 
  139    *bound_shift = shift_due_to_fixed_variables;
 
  145  if (!
SafeAddInto(shift_due_to_fixed_variables, bound_shift)) 
return false;
 
 
  151    absl::Span<const LiteralWithCoeff> cst) {
 
  152  Coefficient previous(1);
 
  154    if (term.coefficient < previous) 
return false;
 
  155    previous = term.coefficient;
 
 
  163    std::vector<LiteralWithCoeff>* cst, Coefficient* rhs) {
 
  170    if (x.coefficient > *rhs) x.coefficient = *rhs + 1;
 
 
  175                                Coefficient bound_shift,
 
  176                                Coefficient max_value) {
 
  177  Coefficient rhs = upper_bound;
 
  179    if (bound_shift > 0) {
 
  185      return Coefficient(-1);
 
  188  if (rhs < 0) 
return Coefficient(-1);
 
  189  return std::min(max_value, rhs);
 
 
  193                                       Coefficient bound_shift,
 
  194                                       Coefficient max_value) {
 
  197  Coefficient shifted_lb = lower_bound;
 
  199    if (bound_shift > 0) {
 
  201      return Coefficient(-1);
 
  207  if (shifted_lb <= 0) {
 
  212  return max_value - shifted_lb;
 
 
  216    bool use_lower_bound, Coefficient lower_bound, 
bool use_upper_bound,
 
  217    Coefficient upper_bound, std::vector<LiteralWithCoeff>* cst) {
 
  219  Coefficient bound_shift;
 
  220  Coefficient max_value;
 
  225  if (use_upper_bound) {
 
  226    const Coefficient rhs =
 
  228    if (!AddConstraint(*cst, max_value, rhs)) 
return false;
 
  230  if (use_lower_bound) {
 
  232    for (
int i = 0; 
i < cst->size(); ++
i) {
 
  233      (*cst)[
i].literal = (*cst)[
i].literal.Negated();
 
  235    const Coefficient rhs =
 
  237    if (!AddConstraint(*cst, max_value, rhs)) 
return false;
 
 
  242bool CanonicalBooleanLinearProblem::AddConstraint(
 
  243    absl::Span<const LiteralWithCoeff> cst, Coefficient max_value,
 
  245  if (rhs < 0) 
return false;          
 
  246  if (rhs >= max_value) 
return true;  
 
  247  constraints_.emplace_back(cst.begin(), cst.end());
 
  254  if (terms_.size() != num_variables) {
 
  255    terms_.assign(num_variables, Coefficient(0));
 
  256    non_zeros_.ClearAndResize(BooleanVariable(num_variables));
 
 
  266  for (BooleanVariable var : non_zeros_.PositionsSetAtLeastOnce()) {
 
  267    terms_[var] = Coefficient(0);
 
  269  non_zeros_.ResetAllToFalse();
 
 
  276  CHECK_LT(rhs_, max_sum_) << 
"Trivially sat.";
 
  277  Coefficient removed_sum(0);
 
  278  const Coefficient bound = max_sum_ - rhs_;
 
  283      terms_[var] = (terms_[var] > 0) ? bound : -bound;
 
  287  max_sum_ -= removed_sum;
 
  288  DCHECK_EQ(max_sum_, ComputeMaxSum());
 
 
  294    if (!result.empty()) result += 
" + ";
 
  298  result += absl::StrFormat(
" <= %d", rhs_.value());
 
 
  305    const Trail& trail, 
int trail_index)
 const {
 
  306  Coefficient activity(0);
 
  314  return rhs_ - activity;
 
 
  320  Coefficient activity(0);
 
  321  Coefficient removed_sum(0);
 
  322  const Coefficient bound = max_sum_ - rhs_;
 
  330        terms_[var] = (terms_[var] > 0) ? bound : -bound;
 
  342  max_sum_ -= removed_sum;
 
  343  DCHECK_EQ(max_sum_, ComputeMaxSum());
 
  344  return rhs_ - activity;
 
 
  348    const Trail& trail, 
int trail_index, Coefficient initial_slack,
 
  349    Coefficient target) {
 
  351  const Coefficient slack = initial_slack;
 
  353  CHECK_LE(target, slack);
 
  359  CHECK_LT(slack, coeff);
 
  362  if (slack == target) 
return;
 
  365  const Coefficient diff = slack - target;
 
  374      terms_[var] = (terms_[var] > 0) ? terms_[var] - diff : terms_[var] + diff;
 
  381  DCHECK_EQ(max_sum_, ComputeMaxSum());
 
 
  385    std::vector<LiteralWithCoeff>* output) {
 
  387  for (BooleanVariable var : non_zeros_.PositionsSetAtLeastOnce()) {
 
  393  std::sort(output->begin(), output->end(), CoeffComparator);
 
 
  396Coefficient MutableUpperBoundedLinearConstraint::ComputeMaxSum()
 const {
 
  397  Coefficient result(0);
 
  405    const std::vector<LiteralWithCoeff>& cst)
 
  406    : is_marked_for_deletion_(false),
 
  408      first_reason_trail_index_(-1),
 
  410  DCHECK(!cst.empty());
 
  411  DCHECK(std::is_sorted(cst.begin(), cst.end(), CoeffComparator));
 
  412  literals_.reserve(cst.size());
 
  419      if (term.coefficient != prev) {
 
  420        prev = term.coefficient;
 
  424    coeffs_.reserve(size);
 
  425    starts_.reserve(size + 1);
 
  430    if (term.coefficient != prev) {
 
  431      prev = term.coefficient;
 
  432      coeffs_.push_back(term.coefficient);
 
  433      starts_.push_back(literals_.size());
 
  435    literals_.push_back(term.literal);
 
  439  starts_.push_back(literals_.size());
 
  441  hash_ = absl::Hash<std::vector<LiteralWithCoeff>>()(cst);
 
 
  446  int literal_index = 0;
 
  448  for (
Literal literal : literals_) {
 
  449    conflict->
AddTerm(literal, coeffs_[coeff_index]);
 
  451    if (literal_index == starts_[coeff_index + 1]) ++coeff_index;
 
 
  457    absl::Span<const LiteralWithCoeff> cst) {
 
  458  if (cst.size() != literals_.size()) 
return false;
 
  459  int literal_index = 0;
 
  462    if (literals_[literal_index] != term.literal) 
return false;
 
  463    if (coeffs_[coeff_index] != term.coefficient) 
return false;
 
  465    if (literal_index == starts_[coeff_index + 1]) {
 
 
  473    Coefficient rhs, 
int trail_index, Coefficient* threshold, 
Trail* trail,
 
  479  Coefficient slack = rhs;
 
  485  std::vector<Coefficient> sum_at_previous_level(last_level + 2,
 
  488  int max_relevant_trail_index = 0;
 
  489  if (trail_index > 0) {
 
  490    int literal_index = 0;
 
  492    for (
Literal literal : literals_) {
 
  493      const BooleanVariable var = literal.Variable();
 
  494      const Coefficient coeff = coeffs_[coeff_index];
 
  497        max_relevant_trail_index =
 
  500        sum_at_previous_level[trail->
Info(var).
level + 1] += coeff;
 
  503      if (literal_index == starts_[coeff_index + 1]) ++coeff_index;
 
  507    if (slack < 0) 
return false;
 
  510    for (
int i = 1; 
i < sum_at_previous_level.size(); ++
i) {
 
  511      sum_at_previous_level[
i] += sum_at_previous_level[
i - 1];
 
  516  int literal_index = 0;
 
  518  for (
Literal literal : literals_) {
 
  519    const BooleanVariable var = literal.Variable();
 
  524      CHECK_LE(coeffs_[coeff_index], rhs_ - sum_at_previous_level[level])
 
  525          << 
"var should have been propagated at an earlier level !";
 
  528    if (literal_index == starts_[coeff_index + 1]) ++coeff_index;
 
  538  index_ = coeffs_.size() - 1;
 
  539  already_propagated_end_ = literals_.size();
 
  540  Update(slack, threshold);
 
  541  return *threshold < 0
 
  542             ? 
Propagate(max_relevant_trail_index, threshold, trail, helper)
 
 
  547    int trail_index, Coefficient* threshold, 
Trail* trail,
 
  549  DCHECK_LT(*threshold, 0);
 
  550  const Coefficient slack = GetSlackFromThreshold(*threshold);
 
  551  DCHECK_GE(slack, 0) << 
"The constraint is already a conflict!";
 
  552  while (index_ >= 0 && coeffs_[index_] > slack) --index_;
 
  555  BooleanVariable first_propagated_variable(-1);
 
  556  for (
int i = starts_[index_ + 1]; 
i < already_propagated_end_; ++
i) {
 
  563        helper->
conflict.push_back(literals_[
i].Negated());
 
  564        Update(slack, threshold);
 
  569      if (first_propagated_variable < 0) {
 
  570        if (first_reason_trail_index_ == -1) {
 
  571          first_reason_trail_index_ = trail->
Index();
 
  573        helper->
Enqueue(literals_[
i].Negated(), trail_index, 
this, trail);
 
  574        first_propagated_variable = literals_[
i].Variable();
 
  580                                       first_propagated_variable);
 
  584  Update(slack, threshold);
 
  585  DCHECK_GE(*threshold, 0);
 
 
  590    const Trail& trail, 
int source_trail_index,
 
  591    BooleanVariable propagated_variable, std::vector<Literal>* reason) {
 
  597    reason->push_back(trail[source_trail_index].Negated());
 
  604  int last_coeff_index = 0;
 
  610  Coefficient slack = rhs_;
 
  611  Coefficient propagated_variable_coefficient(0);
 
  612  int coeff_index = coeffs_.size() - 1;
 
  613  for (
int i = literals_.size() - 1; 
i >= 0; --
i) {
 
  614    const Literal literal = literals_[
i];
 
  615    if (literal.
Variable() == propagated_variable) {
 
  616      propagated_variable_coefficient = coeffs_[coeff_index];
 
  621          reason->push_back(literal.
Negated());
 
  623          last_coeff_index = coeff_index;
 
  625        slack -= coeffs_[coeff_index];
 
  628    if (
i == starts_[coeff_index]) {
 
  632  DCHECK_GT(propagated_variable_coefficient, slack);
 
  633  DCHECK_GE(propagated_variable_coefficient, 0);
 
  636  if (reason->size() <= 1 || coeffs_.size() == 1) 
return;
 
  638  Coefficient limit = propagated_variable_coefficient - slack;
 
  643  coeff_index = last_coeff_index;
 
  644  if (coeffs_[coeff_index] >= limit) 
return;
 
  645  for (
int i = last_i; 
i < literals_.size(); ++
i) {
 
  646    const Literal literal = literals_[
i];
 
  647    if (
i == starts_[coeff_index + 1]) {
 
  649      if (coeffs_[coeff_index] >= limit) 
break;
 
  651    if (literal.
Negated() != reason->back()) 
continue;
 
  652    limit -= coeffs_[coeff_index];
 
  654    if (coeffs_[coeff_index] >= limit) 
break;
 
  656  DCHECK(!reason->empty());
 
 
  661    const Trail& trail, 
int trail_index,
 
  663  Coefficient result(0);
 
  664  int literal_index = 0;
 
  666  for (
Literal literal : literals_) {
 
  672    if (literal_index == starts_[coeff_index + 1]) ++coeff_index;
 
 
  678    const Trail& trail, BooleanVariable var,
 
  680    Coefficient* conflict_slack) {
 
  686  Coefficient var_coeff(0);
 
  687  int literal_index = 0;
 
  689  for (
Literal literal : literals_) {
 
  690    if (literal.Variable() == var) {
 
  693      var_coeff = coeffs_[coeff_index];
 
  699    if (literal_index == starts_[coeff_index + 1]) ++coeff_index;
 
  720    DCHECK_EQ(*conflict_slack,
 
  726  const Coefficient slack = rhs_ - 
activity;
 
  730  DCHECK_EQ(*conflict_slack,
 
  736  const Coefficient cancelation =
 
  744  const Coefficient conflict_var_coeff = conflict->
GetCoefficient(var);
 
  745  const Coefficient min_coeffs = std::min(var_coeff, conflict_var_coeff);
 
  746  const Coefficient new_slack_ub = slack + *conflict_slack - min_coeffs;
 
  747  CHECK_LT(*conflict_slack, conflict_var_coeff);
 
  748  CHECK_LT(slack, var_coeff);
 
  749  if (new_slack_ub < 0) {
 
  751    DCHECK_EQ(*conflict_slack + slack - cancelation,
 
  766  Coefficient conflict_diff(0);
 
  769  if (new_slack_ub < std::max(var_coeff, conflict_var_coeff) - min_coeffs) {
 
  770    const Coefficient reduc = new_slack_ub + 1;
 
  771    if (var_coeff < conflict_var_coeff) {
 
  772      conflict_diff += reduc;
 
  781    conflict_diff = *conflict_slack;
 
  785  CHECK_GE(conflict_diff, 0);
 
  786  CHECK_LE(conflict_diff, *conflict_slack);
 
  787  if (conflict_diff > 0) {
 
  788    conflict->
ReduceSlackTo(trail, limit_trail_index, *conflict_slack,
 
  789                            *conflict_slack - conflict_diff);
 
  790    *conflict_slack -= conflict_diff;
 
  796  CHECK_LE(diff, slack);
 
  805  for (
Literal literal : literals_) {
 
  808      conflict->
AddTerm(literal, coeffs_[coeff_index]);
 
  810      const Coefficient new_coeff = coeffs_[coeff_index] - diff;
 
  814        conflict->
AddTerm(literal, new_coeff);
 
  818    if (literal_index == starts_[coeff_index + 1]) ++coeff_index;
 
 
  827  const Coefficient slack = GetSlackFromThreshold(*threshold);
 
  828  while (index_ + 1 < coeffs_.size() && coeffs_[index_ + 1] <= slack) ++index_;
 
  829  Update(slack, threshold);
 
  830  if (first_reason_trail_index_ >= trail_index) {
 
  831    first_reason_trail_index_ = -1;
 
 
  838                                  Coefficient rhs, 
Trail* trail) {
 
  840  DCHECK(!cst.empty());
 
  841  DCHECK(std::is_sorted(cst.begin(), cst.end(), CoeffComparator));
 
  844  if (constraints_.empty()) {
 
  851  std::unique_ptr<UpperBoundedLinearConstraint> c(
 
  853  std::vector<UpperBoundedLinearConstraint*>& duplicate_candidates =
 
  854      possible_duplicates_[c->hash()];
 
  858    if (candidate->HasIdenticalTerms(cst)) {
 
  859      if (rhs < candidate->Rhs()) {
 
  863        ConstraintIndex 
i(0);
 
  864        while (
i < constraints_.size() &&
 
  865               constraints_[
i.value()].get() != candidate) {
 
  868        CHECK_LT(
i, constraints_.size());
 
  870                                        &thresholds_[
i], trail,
 
  879  thresholds_.push_back(Coefficient(0));
 
  881                        trail, &enqueue_helper_)) {
 
  882    thresholds_.pop_back();
 
  886  const ConstraintIndex cst_index(constraints_.size());
 
  887  duplicate_candidates.push_back(c.get());
 
  888  constraints_.emplace_back(c.release());
 
  890    DCHECK_LT(term.literal.Index(), to_update_.size());
 
  891    to_update_[term.literal].push_back(ConstraintIndexWithCoeff(
 
  893        cst_index, term.coefficient));
 
 
  899    const std::vector<LiteralWithCoeff>& cst, Coefficient rhs, 
Trail* trail) {
 
  900  DeleteSomeLearnedConstraintIfNeeded();
 
  901  const int old_num_constraints = constraints_.size();
 
  906  if (result && constraints_.size() > old_num_constraints) {
 
  907    constraints_.back()->set_is_learned(
true);
 
 
  912bool PbConstraints::PropagateNext(
Trail* trail) {
 
  920  bool conflict = 
false;
 
  921  num_threshold_updates_ += to_update_[true_literal].size();
 
  922  for (ConstraintIndexWithCoeff& update : to_update_[true_literal]) {
 
  923    const Coefficient threshold =
 
  924        thresholds_[update.index] - update.coefficient;
 
  925    thresholds_[update.index] = threshold;
 
  926    if (threshold < 0 && !conflict) {
 
  928          constraints_[update.index.value()].get();
 
  929      update.need_untrail_inspection = 
true;
 
  930      ++num_constraint_lookups_;
 
  932      if (!cst->
Propagate(source_trail_index, &thresholds_[update.index], trail,
 
  935        conflicting_constraint_index_ = update.index;
 
  941      num_inspected_constraint_literals_ +=
 
  949  const int old_index = trail->
Index();
 
  951    if (!PropagateNext(trail)) 
return false;
 
 
  958  to_untrail_.ClearAndResize(ConstraintIndex(constraints_.size()));
 
  962    for (ConstraintIndexWithCoeff& update : to_update_[literal]) {
 
  963      thresholds_[update.index] += update.coefficient;
 
  967      if (update.need_untrail_inspection) {
 
  968        update.need_untrail_inspection = 
false;
 
  969        to_untrail_.Set(update.index);
 
  973  for (ConstraintIndex cst_index : to_untrail_.PositionsSetAtLeastOnce()) {
 
  974    constraints_[cst_index.value()]->Untrail(&(thresholds_[cst_index]),
 
 
  984      enqueue_helper_.reasons[trail_index];
 
  987                                        trail[trail_index].Variable(), reason);
 
 
  992    int trail_index)
 const {
 
  994      enqueue_helper_.reasons[trail_index];
 
 
 1001void PbConstraints::ComputeNewLearnedConstraintLimit() {
 
 1002  const int num_constraints = constraints_.size();
 
 1003  target_number_of_learned_constraint_ =
 
 1005  num_learned_constraint_before_cleanup_ =
 
 1006      static_cast<int>(target_number_of_learned_constraint_ /
 
 1011void PbConstraints::DeleteSomeLearnedConstraintIfNeeded() {
 
 1012  if (num_learned_constraint_before_cleanup_ == 0) {
 
 1014    ComputeNewLearnedConstraintLimit();
 
 1017  --num_learned_constraint_before_cleanup_;
 
 1018  if (num_learned_constraint_before_cleanup_ > 0) 
return;
 
 1023  std::vector<double> activities;
 
 1024  for (
int i = 0; 
i < constraints_.size(); ++
i) {
 
 1025    const UpperBoundedLinearConstraint& constraint = *(constraints_[
i].get());
 
 1026    if (constraint.is_learned() && !constraint.is_used_as_a_reason()) {
 
 1027      activities.push_back(constraint.activity());
 
 1033  std::sort(activities.begin(), activities.end());
 
 1034  const int num_constraints_to_delete =
 
 1035      constraints_.size() - target_number_of_learned_constraint_;
 
 1036  CHECK_GT(num_constraints_to_delete, 0);
 
 1037  if (num_constraints_to_delete >= activities.size()) {
 
 1040    for (
int i = 0; 
i < constraints_.size(); ++
i) {
 
 1041      UpperBoundedLinearConstraint& constraint = *(constraints_[
i].get());
 
 1042      if (constraint.is_learned() && !constraint.is_used_as_a_reason()) {
 
 1043        constraint.MarkForDeletion();
 
 1047    const double limit_activity = activities[num_constraints_to_delete];
 
 1048    int num_constraint_at_limit_activity = 0;
 
 1049    for (
int i = num_constraints_to_delete; 
i >= 0; --
i) {
 
 1050      if (activities[
i] == limit_activity) {
 
 1051        ++num_constraint_at_limit_activity;
 
 1061    for (
int i = constraints_.size() - 1; 
i >= 0; --
i) {
 
 1062      UpperBoundedLinearConstraint& constraint = *(constraints_[
i].get());
 
 1063      if (constraint.is_learned() && !constraint.is_used_as_a_reason()) {
 
 1064        if (constraint.activity() <= limit_activity) {
 
 1065          if (constraint.activity() == limit_activity &&
 
 1066              num_constraint_at_limit_activity > 0) {
 
 1067            --num_constraint_at_limit_activity;
 
 1069            constraint.MarkForDeletion();
 
 1077  DeleteConstraintMarkedForDeletion();
 
 1078  ComputeNewLearnedConstraintLimit();
 
 1083  const double max_activity = parameters_->max_clause_activity_value();
 
 1085                           constraint_activity_increment_);
 
 1086  if (constraint->
activity() > max_activity) {
 
 
 1092  constraint_activity_increment_ *= scaling_factor;
 
 1093  for (
int i = 0; 
i < constraints_.size(); ++
i) {
 
 1094    constraints_[
i]->set_activity(constraints_[
i]->activity() * scaling_factor);
 
 
 1099  const double decay = parameters_->clause_activity_decay();
 
 1100  constraint_activity_increment_ *= 1.0 / decay;
 
 
 1103void PbConstraints::DeleteConstraintMarkedForDeletion() {
 
 1105      constraints_.size(), ConstraintIndex(-1));
 
 1106  ConstraintIndex new_index(0);
 
 1107  for (ConstraintIndex 
i(0); 
i < constraints_.size(); ++
i) {
 
 1108    if (!constraints_[
i.value()]->is_marked_for_deletion()) {
 
 1109      index_mapping[
i] = new_index;
 
 1110      if (new_index < 
i) {
 
 1111        constraints_[new_index.value()] = std::move(constraints_[
i.value()]);
 
 1112        thresholds_[new_index] = thresholds_[
i];
 
 1117      UpperBoundedLinearConstraint* c = constraints_[
i.value()].get();
 
 1118      std::vector<UpperBoundedLinearConstraint*>& ref =
 
 1119          possible_duplicates_[c->hash()];
 
 1120      for (
int i = 0; 
i < ref.size(); ++
i) {
 
 1122          std::swap(ref[
i], ref.back());
 
 1129  constraints_.resize(new_index.value());
 
 1130  thresholds_.resize(new_index.value());
 
 1134  for (LiteralIndex lit(0); lit < to_update_.size(); ++lit) {
 
 1135    std::vector<ConstraintIndexWithCoeff>& updates = to_update_[lit];
 
 1137    for (
int i = 0; 
i < updates.size(); ++
i) {
 
 1138      const ConstraintIndex m = index_mapping[updates[
i].index];
 
 1140        updates[new_index] = updates[
i];
 
 1141        updates[new_index].index = m;
 
 1145    updates.resize(new_index);
 
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
bool AddLinearConstraint(bool use_lower_bound, Coefficient lower_bound, bool use_upper_bound, Coefficient upper_bound, std::vector< LiteralWithCoeff > *cst)
BooleanVariable Variable() const
std::string DebugString()
Returns a string representation of the constraint.
Coefficient ReduceCoefficientsAndComputeSlackForTrailPrefix(const Trail &trail, int trail_index)
Coefficient CancelationAmount(Literal literal, Coefficient coeff) const
Returns the "cancelation" amount of AddTerm(literal, coeff).
void ReduceCoefficients()
Coefficient GetCoefficient(BooleanVariable var) const
Returns the coefficient (>= 0) of the given variable.
Coefficient ComputeSlackForTrailPrefix(const Trail &trail, int trail_index) const
void AddToRhs(Coefficient value)
Adds a non-negative value to this constraint Rhs().
void CopyIntoVector(std::vector< LiteralWithCoeff > *output)
Copies this constraint into a vector<LiteralWithCoeff> representation.
const std::vector< BooleanVariable > & PossibleNonZeros() const
void ReduceSlackTo(const Trail &trail, int trail_index, Coefficient initial_slack, Coefficient target)
void AddTerm(Literal literal, Coefficient coeff)
void ClearAndResize(int num_variables)
Literal GetLiteral(BooleanVariable var) const
void UpdateActivityIncrement()
bool AddConstraint(const std::vector< LiteralWithCoeff > &cst, Coefficient rhs, Trail *trail)
bool Propagate(Trail *trail) final
UpperBoundedLinearConstraint * ReasonPbConstraint(int trail_index) const
absl::Span< const Literal > Reason(const Trail &trail, int trail_index, int64_t conflict_id) const final
void BumpActivity(UpperBoundedLinearConstraint *constraint)
bool AddLearnedConstraint(const std::vector< LiteralWithCoeff > &cst, Coefficient rhs, Trail *trail)
void RescaleActivities(double scaling_factor)
void Untrail(const Trail &trail, int trail_index) final
::int32_t pb_cleanup_increment() const
double pb_cleanup_ratio() const
int propagation_trail_index_
int NumVariables() const
Getters.
std::vector< Literal > * MutableConflict()
void EnqueueWithSameReasonAs(Literal true_literal, BooleanVariable reference_var)
int CurrentDecisionLevel() const
const AssignmentInfo & Info(BooleanVariable var) const
std::vector< Literal > * GetEmptyVectorToStoreReason(int trail_index) const
const VariablesAssignment & Assignment() const
void ResolvePBConflict(const Trail &trail, BooleanVariable var, MutableUpperBoundedLinearConstraint *conflict, Coefficient *conflict_slack)
UpperBoundedLinearConstraint(const std::vector< LiteralWithCoeff > &cst)
Takes a pseudo-Boolean formula in canonical form.
Coefficient ComputeCancelation(const Trail &trail, int trail_index, const MutableUpperBoundedLinearConstraint &conflict)
bool Propagate(int trail_index, Coefficient *threshold, Trail *trail, PbConstraintsEnqueueHelper *helper)
void set_activity(double activity)
void AddToConflict(MutableUpperBoundedLinearConstraint *conflict)
void FillReason(const Trail &trail, int source_trail_index, BooleanVariable propagated_variable, std::vector< Literal > *reason)
void Untrail(Coefficient *threshold, int trail_index)
int already_propagated_end() const
bool HasIdenticalTerms(absl::Span< const LiteralWithCoeff > cst)
Returns true if the given terms are the same as the one in this constraint.
bool InitializeRhs(Coefficient rhs, int trail_index, Coefficient *threshold, Trail *trail, PbConstraintsEnqueueHelper *helper)
bool VariableIsAssigned(BooleanVariable var) const
Returns true iff the given variable is assigned.
bool LiteralIsFalse(Literal literal) const
bool LiteralIsTrue(Literal literal) const
void SimplifyCanonicalBooleanLinearConstraint(std::vector< LiteralWithCoeff > *cst, Coefficient *rhs)
bool ApplyLiteralMapping(const util_intops::StrongVector< LiteralIndex, LiteralIndex > &mapping, std::vector< LiteralWithCoeff > *cst, Coefficient *bound_shift, Coefficient *max_value)
Coefficient ComputeNegatedCanonicalRhs(Coefficient lower_bound, Coefficient bound_shift, Coefficient max_value)
const LiteralIndex kTrueLiteralIndex(-2)
bool BooleanLinearExpressionIsCanonical(absl::Span< const LiteralWithCoeff > cst)
Returns true iff the Boolean linear expression is in canonical form.
const LiteralIndex kFalseLiteralIndex(-3)
Coefficient ComputeCanonicalRhs(Coefficient upper_bound, Coefficient bound_shift, Coefficient max_value)
bool ComputeBooleanLinearExpressionCanonicalForm(std::vector< LiteralWithCoeff > *cst, Coefficient *bound_shift, Coefficient *max_value)
In SWIG mode, we don't want anything besides these top-level includes.
bool SafeAddInto(IntegerType a, IntegerType *b)
#define SCOPED_TIME_STAT(stats)
int32_t trail_index
The index of this assignment in the trail.
Represents a term in a pseudo-Boolean formula.
UpperBoundedLinearConstraint * pb_constraint
void Enqueue(Literal l, int source_trail_index, UpperBoundedLinearConstraint *ct, Trail *trail)
std::vector< Literal > conflict
A temporary vector to store the last conflict.