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 const std::vector<bool>& prefer_lower_value,
86 std::vector<Domain>* domains) {
87 int64_t fixed_activity = 0;
88 const int size =
ct.linear().vars().size();
89 std::vector<int> free_vars;
90 std::vector<int64_t> free_coeffs;
91 for (
int i = 0; i < size; ++i) {
92 const int var =
ct.linear().vars(i);
93 const int64_t coeff =
ct.linear().coeffs(i);
95 if (coeff == 0)
continue;
97 fixed_activity += (*domains)[
var].FixedValue() * coeff;
99 free_vars.push_back(
var);
100 free_coeffs.push_back(coeff);
103 if (free_vars.empty())
return;
107 if (free_vars.size() == 1) {
108 const int var = free_vars[0];
112 const int64_t
value = prefer_lower_value[
var] ? domain.
Min() : domain.
Max();
124 std::vector<Domain> rhs_domains;
125 rhs_domains.push_back(initial_rhs);
126 for (
int i = 0; i + 1 < free_vars.size(); ++i) {
133 rhs_domains.push_back(term.
AdditionWith(rhs_domains.back()));
135 for (
int i = free_vars.size() - 1; i >= 0; --i) {
139 const int var = free_vars[i];
140 const int64_t coeff = free_coeffs[i];
141 const Domain domain = rhs_domains[i]
150 const int64_t
value = prefer_lower_value[
var] ? domain.
Min() : domain.
Max();
153 fixed_activity += coeff *
value;
162 for (
const int ref :
ct.int_max().vars()) {
166 const int64_t
value =
171 const int64_t
value = (*domains)[
var].FixedValue();
174 const int target_ref =
ct.int_max().target();
177 (*domains)[target_var] = (*domains)[target_var].IntersectionWith(
Domain(m));
179 (*domains)[target_var] =
180 (*domains)[target_var].IntersectionWith(
Domain(-m));
182 CHECK(!(*domains)[target_var].IsEmpty());
187 const int index_ref =
ct.element().index();
189 const int target_ref =
ct.element().target();
195 if (!(*domains)[target_var].
IsFixed() && !(*domains)[index_var].
IsFixed()) {
196 const int64_t index_value = (*domains)[index_var].Min();
197 (*domains)[index_var] =
Domain(index_value);
200 const int selected_ref =
ct.element().vars(
202 const int selected_var =
PositiveRef(selected_ref);
203 if (!(*domains)[selected_var].
IsFixed()) {
204 (*domains)[selected_var] =
Domain((*domains)[selected_var].Min());
209 if ((*domains)[index_var].
IsFixed()) {
210 const int64_t index_value = (*domains)[index_var].FixedValue();
211 const int selected_ref =
ct.element().vars(
213 const int selected_var =
PositiveRef(selected_ref);
214 const int64_t selected_value = (*domains)[selected_var].FixedValue();
215 (*domains)[target_var] = (*domains)[target_var].IntersectionWith(
219 DCHECK(!(*domains)[target_var].IsEmpty());
224 const int64_t target_value = (*domains)[target_var].FixedValue();
225 int selected_index_value = -1;
226 for (
int i = 0; i <
ct.element().vars().size(); ++i) {
227 const int ref =
ct.element().vars(i);
229 const int64_t
value = (*domains)[
var].FixedValue();
231 if (
value == target_value) {
232 selected_index_value = i;
236 if (
value == -target_value) {
237 selected_index_value = i;
244 (*domains)[index_var] = (*domains)[index_var].IntersectionWith(
Domain(
245 RefIsPositive(index_var) ? selected_index_value : -selected_index_value));
246 DCHECK(!(*domains)[index_var].IsEmpty());
250 const CpModelProto& mapping_proto,
251 const std::vector<int>& postsolve_mapping,
255 *(
response->mutable_sufficient_assumptions_for_infeasibility())) {
265 if (
response->solution_size() != postsolve_mapping.size())
return;
269 std::vector<Domain> domains(mapping_proto.variables_size());
270 for (
int i = 0; i < postsolve_mapping.size(); ++i) {
271 CHECK_LE(postsolve_mapping[i], domains.size());
274 for (
int i = 0; i < domains.size(); ++i) {
275 if (domains[i].IsEmpty()) {
278 CHECK(!domains[i].IsEmpty());
285 CHECK(!mapping_proto.has_objective());
286 std::vector<bool> prefer_lower_value(domains.size(),
true);
287 if (mapping_proto.has_objective()) {
288 const int size = mapping_proto.objective().vars().size();
289 for (
int i = 0; i < size; ++i) {
290 int var = mapping_proto.objective().vars(i);
291 int64_t coeff = mapping_proto.objective().coeffs(i);
296 prefer_lower_value[i] = (coeff >= 0);
301 const int num_constraints = mapping_proto.constraints_size();
302 for (
int i = num_constraints - 1; i >= 0; i--) {
303 const ConstraintProto&
ct = mapping_proto.constraints(i);
306 bool enforced =
true;
307 for (
const int ref :
ct.enforcement_literal()) {
314 if (!enforced)
continue;
316 switch (
ct.constraint_case()) {
317 case ConstraintProto::kBoolOr:
320 case ConstraintProto::kExactlyOne:
323 case ConstraintProto::kLinear:
326 case ConstraintProto::kIntMax:
329 case ConstraintProto::kElement:
335 LOG(
FATAL) <<
"Unsupported constraint: " <<
ct.ShortDebugString();
340 response->mutable_solution()->Clear();
341 CHECK_LE(num_variables_in_original_model, domains.size());
342 for (
int i = 0; i < num_variables_in_original_model; ++i) {
343 if (prefer_lower_value[i]) {
344 response->add_solution(domains[i].Min());
346 response->add_solution(domains[i].Max());
#define CHECK_LT(val1, val2)
#define CHECK_NE(val1, val2)
#define DCHECK(condition)
#define CHECK_LE(val1, val2)
We call domain any subset of Int64 = [kint64min, kint64max].
Domain InverseMultiplicationBy(const int64_t coeff) const
Returns {x ∈ Int64, ∃ e ∈ D, x * coeff = e}.
bool Contains(int64_t value) const
Returns true iff value is in 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.
int64_t Min() const
Returns the min value of the domain.
bool IsEmpty() const
Returns true if this is the empty set.
int64_t Max() const
Returns the max value of the domain.
SharedResponseManager * response
void PostsolveElement(const ConstraintProto &ct, std::vector< Domain > *domains)
bool RefIsPositive(int ref)
void PostsolveResponse(const int64_t num_variables_in_original_model, const CpModelProto &mapping_proto, const std::vector< int > &postsolve_mapping, CpSolverResponse *response)
void PostsolveIntMax(const ConstraintProto &ct, std::vector< Domain > *domains)
void PostsolveExactlyOne(const ConstraintProto &ct, std::vector< Domain > *domains)
void PostsolveLinear(const ConstraintProto &ct, const std::vector< bool > &prefer_lower_value, std::vector< Domain > *domains)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
void PostsolveClause(const ConstraintProto &ct, std::vector< Domain > *domains)
std::function< bool(const Model &)> IsFixed(IntegerVariable v)
Collection of objects used to extend the Constraint Solver library.