83 : model_proto_(model_proto),
84 ignored_constraints_(model_proto.constraints_size(), false) {
87 absl::flat_hash_set<BoolArgumentProto> exactly_ones_cache;
88 absl::flat_hash_set<LinearConstraintProto> encoding_cache;
89 std::vector<std::vector<EqualityDetectionHelper>> var_to_equalities(
90 model_proto_.variables_size());
91 absl::flat_hash_map<int, std::vector<VarValueCtIndex>>
92 literal_to_var_value_ct_indices;
95 for (
int c = 0; c < model_proto_.constraints_size(); ++c) {
96 const ConstraintProto&
ct = model_proto_.constraints(c);
97 if (
ct.constraint_case() == ConstraintProto::ConstraintCase::kExactlyOne) {
98 BoolArgumentProto bool_arg =
ct.exactly_one();
100 std::sort(bool_arg.mutable_literals()->begin(),
101 bool_arg.mutable_literals()->end());
102 if (!exactly_ones_cache.insert(bool_arg).second) {
103 ignored_constraints_[c] =
true;
104 ++num_ignored_constraints_;
107 if (
ct.constraint_case() != ConstraintProto::ConstraintCase::kLinear) {
110 if (
ct.enforcement_literal().size() != 1)
continue;
111 if (
ct.linear().vars_size() != 1)
continue;
114 const int enforcement_literal =
ct.enforcement_literal(0);
115 const int ref =
ct.linear().vars(0);
119 const Domain domain_if_enforced =
132 var_to_equalities[
var].push_back(
133 {c, enforcement_literal, inter.
FixedValue(),
true});
134 literal_to_var_value_ct_indices[enforcement_literal].push_back(
142 var_to_equalities[
var].push_back(
143 {c, enforcement_literal, inter.
FixedValue(),
false});
149 absl::flat_hash_map<int64_t, LitVarEncodingInfo> value_encodings;
150 std::vector<std::pair<int64_t, int>> value_literal_pairs;
152 for (
int var = 0;
var < var_to_equalities.size(); ++
var) {
153 std::vector<EqualityDetectionHelper>& encoding = var_to_equalities[
var];
154 if (encoding.empty())
continue;
156 std::sort(encoding.begin(), encoding.end());
158 value_encodings.clear();
160 for (
int j = 0; j + 1 < encoding.size(); j++) {
161 if ((encoding[j].
value != encoding[j + 1].
value) ||
169 value_encodings[encoding[j].value] = {encoding[j].literal,
170 encoding[j].constraint_index,
171 encoding[j + 1].constraint_index};
173 if (value_encodings.size() == domain.
Size()) {
174 value_literal_pairs.clear();
175 for (
const auto& [
value, value_encoding] : value_encodings) {
176 ignored_constraints_[value_encoding.positive_ct_index] =
true;
177 ignored_constraints_[value_encoding.negative_ct_index] =
true;
178 num_ignored_constraints_ += 2;
179 value_literal_pairs.push_back({
value, value_encoding.lit});
183 std::sort(value_literal_pairs.begin(), value_literal_pairs.end());
185 ConstraintProto var_encoding;
186 ConstraintProto exactly_one;
188 int64_t min_value = 0;
189 var_encoding.mutable_linear()->add_vars(
var);
190 var_encoding.mutable_linear()->add_coeffs(-1);
191 bool first_iteration =
true;
192 for (
const auto [
value,
lit] : value_literal_pairs) {
194 exactly_one.mutable_exactly_one()->add_literals(
lit);
197 if (first_iteration) {
201 first_iteration =
false;
206 var_encoding.mutable_linear()->add_vars(
lit);
207 var_encoding.mutable_linear()->add_coeffs(
delta);
210 var_encoding.mutable_linear()->add_coeffs(-
delta);
215 var_encoding.mutable_linear()->add_domain(-offset);
216 var_encoding.mutable_linear()->add_domain(-offset);
217 if (encoding_cache.insert(var_encoding.linear()).second) {
218 additional_constraints_.push_back(var_encoding);
219 num_full_encodings_++;
223 std::sort(exactly_one.mutable_exactly_one()->mutable_literals()->begin(),
224 exactly_one.mutable_exactly_one()->mutable_literals()->end());
225 if (exactly_ones_cache.insert(exactly_one.exactly_one()).second) {
226 additional_constraints_.push_back(exactly_one);
232 VLOG(1) <<
"Linear model created:";
233 VLOG(1) <<
" #model constraints: " << model_proto_.constraints_size();
234 VLOG(1) <<
" #full encodings detected: " << num_full_encodings_;
235 VLOG(1) <<
" #exactly_ones added: " << num_exactly_ones_;
236 VLOG(1) <<
" #constraints ignored: " << num_ignored_constraints_;