31 const int size =
ct.bool_or().literals_size();
33 bool satisfied =
false;
34 for (
int i = 0; i < size; ++i) {
35 const int ref =
ct.bool_or().literals(i);
46 if (satisfied)
return;
49 const int first_ref =
ct.bool_or().literals(0);
54 std::vector<Domain>* domains) {
55 bool satisfied =
false;
56 std::vector<int> free_variables;
57 for (
const int ref :
ct.exactly_one().literals()) {
61 CHECK(!satisfied) <<
"Two variables at one in exactly one.";
65 free_variables.push_back(ref);
70 CHECK(!free_variables.empty()) <<
"All zero in exactly one";
71 const int ref = free_variables.back();
73 free_variables.pop_back();
77 for (
const int ref : free_variables) {
85 std::vector<Domain>* domains) {
86 CHECK(!
ct.enforcement_literal().empty());
87 bool has_free_enforcement_literal =
false;
88 for (
const int enf :
ct.enforcement_literal()) {
89 if ((*domains)[
PositiveRef(enf)].IsFixed())
continue;
90 has_free_enforcement_literal =
true;
92 (*domains)[enf] =
Domain(0);
98 if (!has_free_enforcement_literal) {
100 <<
"Unsatisfied linear constraint with no free enforcement literal: " 101 <<
ct.ShortDebugString();
108 const std::vector<bool>& prefer_lower_value,
109 std::vector<Domain>* domains) {
110 int64_t fixed_activity = 0;
111 const int size =
ct.linear().vars().size();
112 std::vector<int> free_vars;
113 std::vector<int64_t> free_coeffs;
114 for (
int i = 0; i < size; ++i) {
115 const int var =
ct.linear().vars(i);
116 const int64_t coeff =
ct.linear().coeffs(i);
118 if (coeff == 0)
continue;
119 if ((*domains)[
var].IsFixed()) {
120 fixed_activity += (*domains)[
var].FixedValue() * coeff;
122 free_vars.push_back(
var);
123 free_coeffs.push_back(coeff);
126 if (free_vars.empty()) {
128 if (!rhs.
Contains(fixed_activity)) {
136 if (free_vars.size() == 1) {
137 const int var = free_vars[0];
145 const int64_t
value = prefer_lower_value[
var] ? domain.
Min() : domain.
Max();
157 std::vector<Domain> rhs_domains;
158 rhs_domains.push_back(initial_rhs);
159 for (
int i = 0; i + 1 < free_vars.size(); ++i) {
166 rhs_domains.push_back(term.
AdditionWith(rhs_domains.back()));
168 for (
int i = free_vars.size() - 1; i >= 0; --i) {
172 const int var = free_vars[i];
173 const int64_t coeff = free_coeffs[i];
174 const Domain domain = rhs_domains[i]
175 .AdditionWith(
Domain(-fixed_activity))
176 .InverseMultiplicationBy(coeff)
177 .IntersectionWith((*domains)[
var]);
183 const int64_t
value = prefer_lower_value[
var] ? domain.
Min() : domain.
Max();
186 fixed_activity += coeff *
value;
199 for (
const int ref :
ct.int_max().vars()) {
203 const int64_t
value =
208 const int64_t
value = (*domains)[
var].FixedValue();
211 const int target_ref =
ct.int_max().target();
214 (*domains)[target_var] = (*domains)[target_var].IntersectionWith(
Domain(m));
216 (*domains)[target_var] =
217 (*domains)[target_var].IntersectionWith(
Domain(-m));
219 CHECK(!(*domains)[target_var].IsEmpty());
224 const int index_ref =
ct.element().index();
226 const int target_ref =
ct.element().target();
232 if (!(*domains)[target_var].
IsFixed() && !(*domains)[index_var].
IsFixed()) {
233 const int64_t index_value = (*domains)[index_var].Min();
234 (*domains)[index_var] =
Domain(index_value);
237 const int selected_ref =
ct.element().vars(
239 const int selected_var =
PositiveRef(selected_ref);
240 if (!(*domains)[selected_var].
IsFixed()) {
241 (*domains)[selected_var] =
Domain((*domains)[selected_var].Min());
246 if ((*domains)[index_var].
IsFixed()) {
247 const int64_t index_value = (*domains)[index_var].FixedValue();
248 const int selected_ref =
ct.element().vars(
250 const int selected_var =
PositiveRef(selected_ref);
251 const int64_t selected_value = (*domains)[selected_var].FixedValue();
252 (*domains)[target_var] = (*domains)[target_var].IntersectionWith(
256 DCHECK(!(*domains)[target_var].IsEmpty());
261 const int64_t target_value = (*domains)[target_var].FixedValue();
262 int selected_index_value = -1;
263 for (
const int64_t v : (*domains)[index_var].Values()) {
264 const int64_t i = index_var == index_ref ? v : -v;
265 if (i < 0 || i >=
ct.element().vars_size())
continue;
267 const int ref =
ct.element().vars(i);
269 const int64_t
value = (*domains)[
var].FixedValue();
271 if (
value == target_value) {
272 selected_index_value = i;
276 if (
value == -target_value) {
277 selected_index_value = i;
284 (*domains)[index_var] = (*domains)[index_var].IntersectionWith(
Domain(
285 RefIsPositive(index_var) ? selected_index_value : -selected_index_value));
286 DCHECK(!(*domains)[index_var].IsEmpty());
291 const std::vector<int>& postsolve_mapping,
295 *(
response->mutable_sufficient_assumptions_for_infeasibility())) {
305 if (
response->solution_size() != postsolve_mapping.size())
return;
310 for (
int i = 0; i < postsolve_mapping.size(); ++i) {
311 CHECK_LE(postsolve_mapping[i], domains.size());
314 for (
int i = 0; i < domains.size(); ++i) {
315 if (domains[i].IsEmpty()) {
318 CHECK(!domains[i].IsEmpty());
326 std::vector<bool> prefer_lower_value(domains.size(),
true);
329 for (
int i = 0; i < size; ++i) {
336 prefer_lower_value[i] = (coeff >= 0);
342 for (
int i = num_constraints - 1; i >= 0; i--) {
347 bool constraint_can_be_ignored =
false;
348 for (
const int enf :
ct.enforcement_literal()) {
350 const bool is_false =
351 domains[
var].IsFixed() &&
354 constraint_can_be_ignored =
true;
358 if (constraint_can_be_ignored)
continue;
360 switch (
ct.constraint_case()) {
379 LOG(
FATAL) <<
"Unsupported constraint: " <<
ct.ShortDebugString();
384 response->mutable_solution()->Clear();
385 CHECK_LE(num_variables_in_original_model, domains.size());
386 for (
int i = 0; i < num_variables_in_original_model; ++i) {
387 if (prefer_lower_value[i]) {
388 response->add_solution(domains[i].Min());
390 response->add_solution(domains[i].Max());
void PostsolveResponse(const int64_t num_variables_in_original_model, const CpModelProto &mapping_proto, const std::vector< int > &postsolve_mapping, CpSolverResponse *response)
Domain InverseMultiplicationBy(const int64_t coeff) const
Returns {x ∈ Int64, ∃ e ∈ D, x * coeff = e}.
int variables_size() const
void PostsolveClause(const ConstraintProto &ct, std::vector< Domain > *domains)
int64_t Max() const
Returns the max value of the domain.
#define CHECK_LT(val1, val2)
::PROTOBUF_NAMESPACE_ID::int32 vars(int index) const
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
int64_t Min() const
Returns the min value of the domain.
#define CHECK_LE(val1, val2)
const ::operations_research::sat::ConstraintProto & constraints(int index) const
std::function< bool(const Model &)> IsFixed(IntegerVariable v)
const ::operations_research::sat::CpObjectiveProto & objective() const
::PROTOBUF_NAMESPACE_ID::int64 coeffs(int index) const
Domain IntersectionWith(const Domain &domain) const
Returns the intersection of D and domain.
Domain MultiplicationBy(int64_t coeff, bool *exact=nullptr) const
Returns {x ∈ Int64, ∃ e ∈ D, x = e * coeff}.
int constraints_size() const
SharedResponseManager * response
void PostsolveElement(const ConstraintProto &ct, std::vector< Domain > *domains)
Domain AdditionWith(const Domain &domain) const
Returns {x ∈ Int64, ∃ a ∈ D, ∃ b ∈ domain, x = a + b}.
bool has_objective() const
void PostsolveIntMax(const ConstraintProto &ct, std::vector< Domain > *domains)
void PostsolveExactlyOne(const ConstraintProto &ct, std::vector< Domain > *domains)
#define DCHECK(condition)
We call domain any subset of Int64 = [kint64min, kint64max].
bool Contains(int64_t value) const
Returns true iff value is in Domain.
void SetEnforcementLiteralToFalse(const ConstraintProto &ct, std::vector< Domain > *domains)
Collection of objects used to extend the Constraint Solver library.
void PostsolveLinear(const ConstraintProto &ct, const std::vector< bool > &prefer_lower_value, std::vector< Domain > *domains)
bool RefIsPositive(int ref)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
bool IsEmpty() const
Returns true if this is the empty set.
#define CHECK_NE(val1, val2)