OR-Tools  9.6
cp_constraints.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
15 
16 #include <algorithm>
17 #include <vector>
18 
19 #include "absl/types/span.h"
20 #include "ortools/sat/integer.h"
21 #include "ortools/sat/model.h"
22 #include "ortools/sat/sat_base.h"
24 
25 namespace operations_research {
26 namespace sat {
27 
29  bool sum = false;
30  int unassigned_index = -1;
31  for (int i = 0; i < literals_.size(); ++i) {
32  const Literal l = literals_[i];
33  if (trail_->Assignment().LiteralIsFalse(l)) {
34  sum ^= false;
35  } else if (trail_->Assignment().LiteralIsTrue(l)) {
36  sum ^= true;
37  } else {
38  // If we have more than one unassigned literal, we can't deduce anything.
39  if (unassigned_index != -1) return true;
40  unassigned_index = i;
41  }
42  }
43 
44  // Propagates?
45  if (unassigned_index != -1) {
46  literal_reason_.clear();
47  for (int i = 0; i < literals_.size(); ++i) {
48  if (i == unassigned_index) continue;
49  const Literal l = literals_[i];
50  literal_reason_.push_back(
51  trail_->Assignment().LiteralIsFalse(l) ? l : l.Negated());
52  }
53  const Literal u = literals_[unassigned_index];
54  integer_trail_->EnqueueLiteral(sum == value_ ? u.Negated() : u,
55  literal_reason_, {});
56  return true;
57  }
58 
59  // Ok.
60  if (sum == value_) return true;
61 
62  // Conflict.
63  std::vector<Literal>* conflict = trail_->MutableConflict();
64  conflict->clear();
65  for (int i = 0; i < literals_.size(); ++i) {
66  const Literal l = literals_[i];
67  conflict->push_back(trail_->Assignment().LiteralIsFalse(l) ? l
68  : l.Negated());
69  }
70  return false;
71 }
72 
74  const int id = watcher->Register(this);
75  for (const Literal& l : literals_) {
76  watcher->WatchLiteral(l, id);
77  watcher->WatchLiteral(l.Negated(), id);
78  }
79 }
80 
82  IntegerVariable target_var, const absl::Span<const IntegerVariable> vars,
83  const absl::Span<const IntegerValue> offsets,
84  const absl::Span<const Literal> selectors,
85  const absl::Span<const Literal> enforcements, Model* model)
86  : target_var_(target_var),
87  vars_(vars.begin(), vars.end()),
88  offsets_(offsets.begin(), offsets.end()),
89  selectors_(selectors.begin(), selectors.end()),
90  enforcements_(enforcements.begin(), enforcements.end()),
91  trail_(model->GetOrCreate<Trail>()),
92  integer_trail_(model->GetOrCreate<IntegerTrail>()) {}
93 
95  // TODO(user): In case of a conflict, we could push one of them to false if
96  // it is the only one.
97  for (const Literal l : enforcements_) {
98  if (!trail_->Assignment().LiteralIsTrue(l)) return true;
99  }
100 
101  // Compute the min of the lower-bound for the still possible variables.
102  // TODO(user): This could be optimized by keeping more info from the last
103  // Propagate() calls.
104  IntegerValue target_min = kMaxIntegerValue;
105  const IntegerValue current_min = integer_trail_->LowerBound(target_var_);
106  for (int i = 0; i < vars_.size(); ++i) {
107  if (trail_->Assignment().LiteralIsTrue(selectors_[i])) return true;
108  if (trail_->Assignment().LiteralIsFalse(selectors_[i])) continue;
109  target_min = std::min(target_min,
110  integer_trail_->LowerBound(vars_[i]) + offsets_[i]);
111 
112  // Abort if we can't get a better bound.
113  if (target_min <= current_min) return true;
114  }
115  if (target_min == kMaxIntegerValue) {
116  // All false, conflit.
117  *(trail_->MutableConflict()) = selectors_;
118  return false;
119  }
120 
121  literal_reason_.clear();
122  integer_reason_.clear();
123  for (const Literal l : enforcements_) {
124  literal_reason_.push_back(l.Negated());
125  }
126  for (int i = 0; i < vars_.size(); ++i) {
127  if (trail_->Assignment().LiteralIsFalse(selectors_[i])) {
128  literal_reason_.push_back(selectors_[i]);
129  } else {
130  integer_reason_.push_back(
131  IntegerLiteral::GreaterOrEqual(vars_[i], target_min - offsets_[i]));
132  }
133  }
134  return integer_trail_->Enqueue(
135  IntegerLiteral::GreaterOrEqual(target_var_, target_min), literal_reason_,
136  integer_reason_);
137 }
138 
140  GenericLiteralWatcher* watcher) {
141  const int id = watcher->Register(this);
142  for (const Literal l : selectors_) watcher->WatchLiteral(l.Negated(), id);
143  for (const Literal l : enforcements_) watcher->WatchLiteral(l, id);
144  for (const IntegerVariable v : vars_) watcher->WatchLowerBound(v, id);
145 }
146 
147 } // namespace sat
148 } // namespace operations_research
const std::vector< IntVar * > vars_
Definition: alldiff_cst.cc:44
int64_t min
Definition: alldiff_cst.cc:139
void RegisterWith(GenericLiteralWatcher *watcher)
void WatchLiteral(Literal l, int id, int watch_index=-1)
Definition: integer.h:1673
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
Definition: integer.h:1681
int Register(PropagatorInterface *propagator)
Definition: integer.cc:2286
GreaterThanAtLeastOneOfPropagator(IntegerVariable target_var, const absl::Span< const IntegerVariable > vars, const absl::Span< const IntegerValue > offsets, const absl::Span< const Literal > selectors, const absl::Span< const Literal > enforcements, Model *model)
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition: integer.cc:1228
void EnqueueLiteral(Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
Definition: integer.cc:1387
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1557
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:42
std::vector< Literal > * MutableConflict()
Definition: sat_base.h:373
const VariablesAssignment & Assignment() const
Definition: sat_base.h:402
bool LiteralIsTrue(Literal literal) const
Definition: sat_base.h:164
bool LiteralIsFalse(Literal literal) const
Definition: sat_base.h:161
GRBmodel * model
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
Collection of objects used to extend the Constraint Solver library.
IntervalVar *const target_var_
std::optional< int64_t > end
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1499