22#include "absl/container/flat_hash_map.h"
23#include "absl/meta/type_traits.h"
24#include "absl/types/span.h"
28#include "ortools/sat/cp_model.pb.h"
39 const Index index = IndexFromLiteral(literal_ref);
44 if (
var >= tmp_num_occurrences_.size()) {
45 tmp_num_occurrences_.resize(
var + 1, 0);
47 const auto insert = deductions_.insert({{
index,
var}, domain});
54 const Domain& old_domain = insert.first->second;
63 absl::Span<const int> clause) {
64 std::vector<std::pair<int, Domain>> result;
68 for (
const int ref : clause) {
70 if (
index >= something_changed_.
size())
return result;
71 if (something_changed_[
index]) {
75 if (abort)
return result;
78 std::vector<int> to_process;
79 std::vector<int> to_clean;
80 for (
const int ref : clause) {
82 for (
const int var : enforcement_to_vars_[
index]) {
83 if (tmp_num_occurrences_[
var] == 0) {
84 to_clean.push_back(
var);
86 tmp_num_occurrences_[
var]++;
87 if (tmp_num_occurrences_[
var] == clause.size()) {
88 to_process.push_back(
var);
94 for (
const int var : to_clean) {
95 tmp_num_occurrences_[
var] = 0;
99 std::vector<Domain> domains(to_process.size());
100 for (
const int ref : clause) {
102 for (
int i = 0; i < to_process.size(); ++i) {
103 domains[i] = domains[i].UnionWith(
108 for (
int i = 0; i < to_process.size(); ++i) {
109 result.push_back({to_process[i], std::move(domains[i])});
117template <
typename ProtoWithVarsAndCoeffs>
118int64_t GetVarCoeffAndCopyOtherTerms(
119 const int var,
const ProtoWithVarsAndCoeffs&
proto,
120 std::vector<std::pair<int, int64_t>>* terms) {
121 int64_t var_coeff = 0;
122 const int size =
proto.vars().size();
123 for (
int i = 0; i < size; ++i) {
124 int ref =
proto.vars(i);
136 terms->push_back({ref,
coeff});
144template <
typename ProtoWithVarsAndCoeffs>
145void SortAndMergeTerms(std::vector<std::pair<int, int64_t>>* terms,
146 ProtoWithVarsAndCoeffs*
proto) {
148 proto->clear_coeffs();
149 std::sort(terms->begin(), terms->end());
151 int64_t current_coeff = 0;
152 for (
const auto& entry : *terms) {
154 if (entry.first == current_var) {
155 current_coeff += entry.second;
157 if (current_coeff != 0) {
158 proto->add_vars(current_var);
159 proto->add_coeffs(current_coeff);
161 current_var = entry.first;
162 current_coeff = entry.second;
165 if (current_coeff != 0) {
166 proto->add_vars(current_var);
167 proto->add_coeffs(current_coeff);
173void AddTermsFromVarDefinition(
const int var,
const int64_t var_coeff,
174 const ConstraintProto& definition,
175 std::vector<std::pair<int, int64_t>>* terms) {
176 const int definition_size = definition.linear().vars().size();
177 for (
int i = 0; i < definition_size; ++i) {
178 int ref = definition.linear().vars(i);
179 int64_t
coeff = definition.linear().coeffs(i);
188 terms->push_back({ref, -
coeff * var_coeff});
195 const ConstraintProto& definition,
196 ConstraintProto*
ct) {
198 CHECK_EQ(std::abs(var_coeff_in_definition), 1);
201 std::vector<std::pair<int, int64_t>> terms;
202 int64_t var_coeff = GetVarCoeffAndCopyOtherTerms(
var,
ct->linear(), &terms);
203 if (var_coeff == 0)
return false;
205 if (var_coeff_in_definition < 0) var_coeff *= -1;
207 AddTermsFromVarDefinition(
var, var_coeff, definition, &terms);
219 SortAndMergeTerms(&terms,
ct->mutable_linear());
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
void resize(size_type new_size)
void push_back(const value_type &x)
We call domain any subset of Int64 = [kint64min, kint64max].
bool IsIncludedIn(const Domain &domain) const
Returns true iff D is included in the given domain.
Domain AdditionWith(const Domain &domain) const
Returns {x ∈ Int64, ∃ a ∈ D, ∃ b ∈ domain, x = a + b}.
Domain MultiplicationBy(int64_t coeff, bool *exact=nullptr) const
Returns {x ∈ Int64, ∃ e ∈ D, x = e * coeff}.
Domain IntersectionWith(const Domain &domain) const
Returns the intersection of D and domain.
void Set(IntegerType index)
void Resize(IntegerType size)
std::vector< std::pair< int, Domain > > ProcessClause(absl::Span< const int > clause)
void AddDeduction(int literal_ref, int var, Domain domain)
const Collection::value_type::second_type & FindOrDieNoPrint(const Collection &collection, const typename Collection::value_type::first_type &key)
bool RefIsPositive(int ref)
void FillDomainInProto(const Domain &domain, ProtoWithDomain *proto)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
bool SubstituteVariable(int var, int64_t var_coeff_in_definition, const ConstraintProto &definition, ConstraintProto *ct)
Collection of objects used to extend the Constraint Solver library.