14#ifndef OR_TOOLS_SAT_INTEGER_H_
15#define OR_TOOLS_SAT_INTEGER_H_
27#include "absl/container/flat_hash_map.h"
28#include "absl/container/inlined_vector.h"
29#include "absl/strings/str_cat.h"
30#include "absl/types/span.h"
71 const double kInfinity = std::numeric_limits<double>::infinity();
74 return static_cast<double>(
value.value());
77template <
class IntType>
79 return IntType(std::abs(t.value()));
83 IntegerValue positive_divisor) {
85 const IntegerValue result = dividend / positive_divisor;
86 const IntegerValue adjust =
87 static_cast<IntegerValue
>(result * positive_divisor < dividend);
88 return result + adjust;
92 IntegerValue positive_divisor) {
94 const IntegerValue result = dividend / positive_divisor;
95 const IntegerValue adjust =
96 static_cast<IntegerValue
>(result * positive_divisor > dividend);
97 return result - adjust;
107 IntegerValue positive_divisor) {
109 const IntegerValue m = dividend % positive_divisor;
110 return m < 0 ? m + positive_divisor : m;
115 const int64_t prod =
CapProd(
a.value(),
b.value());
119 const int64_t add =
CapAdd(prod, result->value());
123 *result = IntegerValue(add);
135 return IntegerVariable(i.value() ^ 1);
139 return (i.value() & 1) == 0;
143 return IntegerVariable(i.value() & (~1));
149 return PositiveOnlyIndex(
var.value() / 2);
153 IntegerValue coeff) {
155 return absl::StrCat(coeff.value(),
"*X",
var.value() / 2);
160 const std::vector<IntegerVariable>& vars);
198 ? absl::StrCat(
"I",
var.value() / 2,
">=",
bound.value())
199 : absl::StrCat(
"I",
var.value() / 2,
"<=", -
bound.value());
204 IntegerValue
bound = IntegerValue(0);
262 return absl::StrCat(
"(",
coeff.value(),
" * X",
var.value(),
")");
264 return absl::StrCat(
"(",
coeff.value(),
" * X",
var.value(),
" + ",
271 IntegerValue
coeff = IntegerValue(0);
311 num_created_variables_(0) {}
314 VLOG(1) <<
"#variables created = " << num_created_variables_;
363 IntegerVariable
var)
const;
411 IntegerValue
value)
const;
425 if (lit.
Index() >= reverse_encoding_.size()) {
426 return empty_integer_literal_vector_;
428 return reverse_encoding_[lit.
Index()];
435 if (lit.
Index() >= full_reverse_encoding_.size()) {
436 return empty_integer_literal_vector_;
438 return full_reverse_encoding_[lit.
Index()];
444 return newly_fixed_integer_literals_;
447 newly_fixed_integer_literals_.clear();
456 return literal_view_[lit.
Index()];
475 IntegerValue*
bound)
const;
483 literal_index_true_ = literal_true.
Index();
486 return Literal(literal_index_true_);
494 IntegerVariable
var)
const {
495 if (
var >= encoding_by_var_.size()) {
496 return std::map<IntegerValue, Literal>();
498 return encoding_by_var_[
var];
514 void AddImplications(
const std::map<IntegerValue, Literal>& map,
515 std::map<IntegerValue, Literal>::const_iterator it,
521 bool add_implications_ =
true;
522 int64_t num_created_variables_ = 0;
538 full_reverse_encoding_;
539 std::vector<IntegerLiteral> newly_fixed_integer_literals_;
551 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>,
Literal>
552 equality_to_associated_literal_;
566 std::vector<IntegerValue> tmp_values_;
591 void Untrail(const
Trail& trail,
int literal_trail_index) final;
593 int trail_index) const final;
600 return IntegerVariable(vars_.size());
660 const LiteralIndex is_ignored_literal = is_ignored_literals_[i];
666 return Literal(is_ignored_literals_[i]);
675 is_ignored_literals_[i] == is_considered.
NegatedIndex());
681 IntegerValue
LowerBound(IntegerVariable i)
const;
682 IntegerValue
UpperBound(IntegerVariable i)
const;
685 bool IsFixed(IntegerVariable i)
const;
734 absl::Span<const IntegerValue> coeffs,
735 std::vector<IntegerLiteral>* reason)
const;
739 absl::Span<const IntegerValue> coeffs,
740 absl::Span<const IntegerVariable> vars,
741 std::vector<IntegerLiteral>* reason)
const;
745 absl::Span<const IntegerValue> coeffs,
746 std::vector<int>* trail_indices)
const;
769 ABSL_MUST_USE_RESULT
bool Enqueue(
771 absl::Span<const IntegerLiteral> integer_reason);
781 std::vector<IntegerLiteral>* integer_reason);
790 ABSL_MUST_USE_RESULT
bool Enqueue(
792 absl::Span<const IntegerLiteral> integer_reason,
793 int trail_index_with_same_reason);
808 std::vector<Literal>* literals, std::vector<int>* dependencies)>;
815 absl::Span<const IntegerLiteral> integer_reason);
825 std::vector<Literal>* output)
const;
834 int64_t
timestamp()
const {
return num_enqueues_ + num_untrails_; }
844 watchers_.push_back(p);
850 absl::Span<const IntegerLiteral> integer_reason) {
851 DCHECK(ReasonIsValid(literal_reason, integer_reason));
853 conflict->assign(literal_reason.begin(), literal_reason.end());
858 DCHECK(ReasonIsValid({}, integer_reason));
867 return vars_[
var].current_trail_index < vars_.size();
873 reversible_classes_.push_back(rev);
876 int Index()
const {
return integer_trail_.size(); }
904 return !literal_to_fix_.empty() || !integer_literal_to_fix_.empty();
910 bool ReasonIsValid(absl::Span<const Literal> literal_reason,
911 absl::Span<const IntegerLiteral> integer_reason);
916 std::vector<Literal>* InitializeConflict(
918 absl::Span<const Literal> literals_reason,
919 absl::Span<const IntegerLiteral> bounds_reason);
922 ABSL_MUST_USE_RESULT
bool EnqueueInternal(
924 absl::Span<const Literal> literal_reason,
925 absl::Span<const IntegerLiteral> integer_reason,
926 int trail_index_with_same_reason);
930 absl::Span<const Literal> literal_reason,
931 absl::Span<const IntegerLiteral> integer_reason);
936 ABSL_MUST_USE_RESULT
bool EnqueueAssociatedIntegerLiteral(
940 void MergeReasonIntoInternal(std::vector<Literal>* output)
const;
945 int FindLowestTrailIndexThatExplainBound(
IntegerLiteral i_lit)
const;
950 void ComputeLazyReasonIfNeeded(
int trail_index)
const;
957 absl::Span<const int> Dependencies(
int trail_index)
const;
963 void AppendLiteralsReason(
int trail_index,
964 std::vector<Literal>* output)
const;
967 std::string DebugString();
972 IntegerValue current_bound;
975 int current_trail_index;
985 mutable int var_trail_index_cache_threshold_ = 0;
990 absl::flat_hash_map<IntegerValue, IntegerVariable> constant_map_;
997 int32_t prev_trail_index;
1002 int32_t reason_index;
1004 std::vector<TrailEntry> integer_trail_;
1005 std::vector<LazyReasonFunction> lazy_reasons_;
1009 std::vector<int> integer_search_levels_;
1016 std::vector<int> reason_decision_levels_;
1017 std::vector<int> literals_reason_starts_;
1018 std::vector<int> bounds_reason_starts_;
1019 std::vector<Literal> literals_reason_buffer_;
1024 std::vector<IntegerLiteral> bounds_reason_buffer_;
1025 mutable std::vector<int> trail_index_reason_buffer_;
1028 mutable std::vector<Literal> lazy_reason_literals_;
1029 mutable std::vector<int> lazy_reason_trail_indices_;
1040 RevMap<absl::flat_hash_map<IntegerVariable, int>>
1041 var_to_current_lb_interval_index_;
1044 mutable bool has_dependency_ =
false;
1045 mutable std::vector<int> tmp_queue_;
1046 mutable std::vector<IntegerVariable> tmp_to_clear_;
1048 tmp_var_to_trail_index_in_queue_;
1049 mutable SparseBitset<BooleanVariable> added_variables_;
1056 std::vector<Literal> literal_to_fix_;
1057 std::vector<IntegerLiteral> integer_literal_to_fix_;
1060 struct RelaxHeapEntry {
1064 bool operator<(
const RelaxHeapEntry& o)
const {
return index < o.index; }
1066 mutable std::vector<RelaxHeapEntry> relax_heap_;
1067 mutable std::vector<int> tmp_indices_;
1070 mutable SparseBitset<IntegerVariable> tmp_marked_;
1076 std::vector<int> boolean_trail_index_to_integer_one_;
1080 int first_level_without_full_propagation_ = -1;
1082 int64_t num_enqueues_ = 0;
1083 int64_t num_untrails_ = 0;
1084 int64_t num_level_zero_enqueues_ = 0;
1085 mutable int64_t num_decisions_to_break_loop_ = 0;
1087 std::vector<SparseBitset<IntegerVariable>*> watchers_;
1088 std::vector<ReversibleInterface*> reversible_classes_;
1090 IntegerDomains* domains_;
1091 IntegerEncoder* encoder_;
1093 const SatParameters& parameters_;
1098 absl::flat_hash_map<std::pair<LiteralIndex, IntegerVariable>, IntegerValue>
1162 void Untrail(
const Trail& trail,
int literal_trail_index)
final;
1248 const std::function<
void(
const std::vector<IntegerVariable>&)> cb) {
1249 level_zero_modified_variable_callback_.push_back(cb);
1260 void UpdateCallingNeeds(
Trail* trail);
1270 return id == o.id && watch_index == o.watch_index;
1275 std::vector<PropagatorInterface*> watchers_;
1276 SparseBitset<IntegerVariable> modified_vars_;
1280 std::vector<std::deque<int>> queue_by_priority_;
1281 std::vector<bool> in_queue_;
1284 DEFINE_INT_TYPE(IdType, int32_t);
1285 std::vector<int> id_to_level_at_last_call_;
1286 RevVector<IdType, int> id_to_greatest_common_level_since_last_call_;
1287 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1288 std::vector<std::vector<int*>> id_to_reversible_ints_;
1289 std::vector<std::vector<int>> id_to_watch_indices_;
1290 std::vector<int> id_to_priority_;
1291 std::vector<int> id_to_idempotence_;
1294 std::vector<int> propagator_ids_to_call_at_level_zero_;
1299 std::vector<std::function<void(
const std::vector<IntegerVariable>&)>>
1300 level_zero_modified_variable_callback_;
1310 IntegerValue
bound) {
1316 IntegerValue
bound) {
1331 IntegerValue
bound)
const {
1346 return vars_[i].current_bound;
1354 return vars_[i].current_bound == -vars_[
NegationOf(i)].current_bound;
1363 Literal l, IntegerVariable i)
const {
1364 const auto it = conditional_lbs_.find({l.
Index(), i});
1365 if (it != conditional_lbs_.end()) {
1366 return std::max(vars_[i].current_bound, it->second);
1368 return vars_[i].current_bound;
1388 IntegerVariable i)
const {
1393 IntegerVariable i)
const {
1408 IntegerVariable
var)
const {
1409 return integer_trail_[
var.value()].bound;
1413 IntegerVariable
var)
const {
1418 return integer_trail_[
var.value()].bound ==
1424 if (l.
Index() >= literal_to_watcher_.size()) {
1425 literal_to_watcher_.resize(l.
Index().value() + 1);
1427 literal_to_watcher_[l.
Index()].push_back({id, watch_index});
1433 if (
var.value() >= var_to_watcher_.size()) {
1434 var_to_watcher_.resize(
var.value() + 1);
1441 const WatchData data = {id, watch_index};
1442 if (!var_to_watcher_[
var].empty() && var_to_watcher_[
var].back() == data) {
1445 var_to_watcher_[
var].push_back(data);
1479 ->GetOrCreateConstantIntegerVariable(IntegerValue(
value));
1488 IntegerValue(lb), IntegerValue(ub));
1508 IntegerVariable
var;
1510 if (assignment.LiteralIsTrue(lit)) {
1512 }
else if (assignment.LiteralIsFalse(lit)) {
1518 encoder->AssociateToIntegerEqualValue(lit,
var, IntegerValue(1));
1544inline std::function<int64_t(
const Model&)>
Value(IntegerVariable v) {
1557 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1559 VLOG(1) <<
"Model trivially infeasible, variable " << v
1561 <<
" and GreaterOrEqual() was called with a lower bound of "
1571 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1573 LOG(
WARNING) <<
"Model trivially infeasible, variable " << v
1575 <<
" and LowerOrEqual() was called with an upper bound of "
1596 const std::vector<Literal>& enforcement_literals,
IntegerLiteral i) {
1603 std::vector<Literal> clause;
1624 int64_t lb, int64_t ub) {
1630 v, IntegerValue(lb))));
1644inline std::function<std::vector<IntegerEncoder::ValueLiteralPair>(Model*)>
1660std::function<void(Model*)>
#define DCHECK_LE(val1, val2)
#define DCHECK_NE(val1, val2)
#define CHECK_EQ(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2)
#define DCHECK(condition)
#define CHECK_LE(val1, val2)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
An Assignment is a variable -> domains mapping, used to report solutions to the user.
We call domain any subset of Int64 = [kint64min, kint64max].
void ClearAndResize(IntegerType size)
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
bool Propagate(Trail *trail) final
void WatchLowerBound(IntegerValue i, int id)
void AlwaysCallAtLevelZero(int id)
void RegisterLevelZeroModifiedVariablesCallback(const std::function< void(const std::vector< IntegerVariable > &)> cb)
void WatchIntegerVariable(IntegerValue v, int id)
int NumPropagators() const
void WatchLowerBound(AffineExpression e, int id)
void WatchUpperBound(AffineExpression e, int id)
void RegisterReversibleInt(int id, int *rev)
void RegisterReversibleClass(int id, ReversibleInterface *rev)
void WatchLiteral(Literal l, int id, int watch_index=-1)
void WatchUpperBound(IntegerValue i, int id)
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
GenericLiteralWatcher(Model *model)
void WatchIntegerVariable(IntegerVariable i, int id, int watch_index=-1)
void WatchAffineExpression(AffineExpression e, int id)
~GenericLiteralWatcher() final
void WatchUpperBound(IntegerVariable var, int id, int watch_index=-1)
void SetPropagatorPriority(int id, int priority)
int Register(PropagatorInterface *propagator)
void NotifyThatPropagatorMayNotReachFixedPointInOnePass(int id)
void Untrail(const Trail &trail, int literal_trail_index) final
Literal GetOrCreateLiteralAssociatedToEquality(IntegerVariable var, IntegerValue value)
LiteralIndex SearchForLiteralAtOrBefore(IntegerLiteral i, IntegerValue *bound) const
const std::vector< IntegerLiteral > NewlyFixedIntegerLiterals() const
LiteralIndex GetAssociatedLiteral(IntegerLiteral i_lit) const
void FullyEncodeVariable(IntegerVariable var)
std::map< IntegerValue, Literal > PartialGreaterThanEncoding(IntegerVariable var) const
Literal GetFalseLiteral()
const IntegerVariable GetLiteralView(Literal lit) const
const InlinedIntegerLiteralVector & GetAllIntegerLiterals(Literal lit) const
std::pair< IntegerLiteral, IntegerLiteral > Canonicalize(IntegerLiteral i_lit) const
void DisableImplicationBetweenLiteral()
void ClearNewlyFixedIntegerLiterals()
void AssociateToIntegerEqualValue(Literal literal, IntegerVariable var, IntegerValue value)
bool LiteralIsAssociated(IntegerLiteral i_lit) const
std::vector< ValueLiteralPair > FullDomainEncoding(IntegerVariable var) const
std::vector< ValueLiteralPair > PartialDomainEncoding(IntegerVariable var) const
const bool LiteralOrNegationHasView(Literal lit) const
void AddAllImplicationsBetweenAssociatedLiterals()
bool VariableIsFullyEncoded(IntegerVariable var) const
std::vector< ValueLiteralPair > RawDomainEncoding(IntegerVariable var) const
const InlinedIntegerLiteralVector & GetIntegerLiterals(Literal lit) const
IntegerEncoder(Model *model)
LiteralIndex GetAssociatedEqualityLiteral(IntegerVariable var, IntegerValue value) const
void AssociateToIntegerLiteral(Literal literal, IntegerLiteral i_lit)
Literal GetOrCreateAssociatedLiteral(IntegerLiteral i_lit)
IntegerVariable FirstUnassignedVariable() const
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
IntegerVariable GetOrCreateConstantIntegerVariable(IntegerValue value)
int64_t num_enqueues() const
void RegisterWatcher(SparseBitset< IntegerVariable > *p)
bool Propagate(Trail *trail) final
void ReserveSpaceForNumVariables(int num_vars)
int FindTrailIndexOfVarBefore(IntegerVariable var, int threshold) const
bool IsCurrentlyIgnored(IntegerVariable i) const
std::vector< Literal > ReasonFor(IntegerLiteral literal) const
bool ReportConflict(absl::Span< const IntegerLiteral > integer_reason)
std::function< void(IntegerLiteral literal_to_explain, int trail_index_of_literal, std::vector< Literal > *literals, std::vector< int > *dependencies)> LazyReasonFunction
int64_t num_level_zero_enqueues() const
bool IsFixed(IntegerVariable i) const
LiteralIndex OptionalLiteralIndex(IntegerVariable i) const
absl::Span< const Literal > Reason(const Trail &trail, int trail_index) const final
IntegerLiteral LowerBoundAsLiteral(IntegerVariable i) const
bool CurrentBranchHadAnIncompletePropagation()
bool InPropagationLoop() const
bool ReportConflict(absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
void EnqueueLiteral(Literal literal, absl::Span< const Literal > literal_reason, absl::Span< const IntegerLiteral > integer_reason)
IntegerVariable NextVariableToBranchOnInPropagationLoop() const
IntegerValue UpperBound(IntegerVariable i) const
void MarkIntegerVariableAsOptional(IntegerVariable i, Literal is_considered)
IntegerValue LevelZeroUpperBound(IntegerVariable var) const
IntegerValue ConditionalLowerBound(Literal l, IntegerVariable i) const
bool VariableLowerBoundIsFromLevelZero(IntegerVariable var) const
void AppendRelaxedLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, absl::Span< const IntegerVariable > vars, std::vector< IntegerLiteral > *reason) const
IntegerValue LevelZeroLowerBound(IntegerVariable var) const
void RelaxLinearReason(IntegerValue slack, absl::Span< const IntegerValue > coeffs, std::vector< IntegerLiteral > *reason) const
void AppendNewBounds(std::vector< IntegerLiteral > *output) const
bool IntegerLiteralIsTrue(IntegerLiteral l) const
IntegerValue LowerBound(IntegerVariable i) const
IntegerLiteral UpperBoundAsLiteral(IntegerVariable i) const
bool HasPendingRootLevelDeduction() const
int NumConstantVariables() const
bool IsFixedAtLevelZero(IntegerVariable var) const
void MergeReasonInto(absl::Span< const IntegerLiteral > literals, std::vector< Literal > *output) const
Literal IsIgnoredLiteral(IntegerVariable i) const
bool IsOptional(IntegerVariable i) const
ABSL_MUST_USE_RESULT bool ConditionalEnqueue(Literal lit, IntegerLiteral i_lit, std::vector< Literal > *literal_reason, std::vector< IntegerLiteral > *integer_reason)
int64_t timestamp() const
bool IntegerLiteralIsFalse(IntegerLiteral l) const
void RemoveLevelZeroBounds(std::vector< IntegerLiteral > *reason) const
IntegerVariable AddIntegerVariable()
void RegisterReversibleClass(ReversibleInterface *rev)
const Domain & InitialVariableDomain(IntegerVariable var) const
void Untrail(const Trail &trail, int literal_trail_index) final
IntegerVariable NumIntegerVariables() const
bool UpdateInitialDomain(IntegerVariable var, Domain domain)
IntegerTrail(Model *model)
LiteralIndex NegatedIndex() const
LiteralIndex Index() const
Class that owns everything related to a particular optimization model.
virtual ~PropagatorInterface()
virtual bool Propagate()=0
virtual bool IncrementalPropagate(const std::vector< int > &watch_indices)
RevIntRepository(Model *model)
RevIntegerValueRepository(Model *model)
BooleanVariable NewBooleanVariable()
int CurrentDecisionLevel() const
bool AddUnitClause(Literal true_literal)
const VariablesAssignment & Assignment() const
std::vector< Literal > * MutableConflict()
bool LiteralIsTrue(Literal literal) const
absl::InlinedVector< IntegerLiteral, 2 > InlinedIntegerLiteralVector
std::function< IntegerVariable(Model *)> NewIntegerVariableFromLiteral(Literal lit)
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue *result)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::function< void(Model *)> Equality(IntegerVariable v, int64_t value)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
IntType IntTypeAbs(IntType t)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
const LiteralIndex kNoLiteralIndex(-1)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue)
std::function< void(Model *)> ClauseConstraint(absl::Span< const Literal > literals)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
std::function< BooleanVariable(Model *)> NewBooleanVariable()
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
std::string IntegerTermDebugString(IntegerVariable var, IntegerValue coeff)
std::function< bool(const Model &)> IsFixed(IntegerVariable v)
const IntegerVariable kNoIntegerVariable(-1)
std::function< IntegerVariable(Model *)> ConstantIntegerVariable(int64_t value)
std::function< void(Model *)> Implication(const std::vector< Literal > &enforcement_literals, IntegerLiteral i)
IntegerVariable PositiveVariable(IntegerVariable i)
IntegerValue PositiveRemainder(IntegerValue dividend, IntegerValue positive_divisor)
DEFINE_INT_TYPE(ClauseIndex, int)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> ExcludeCurrentSolutionWithoutIgnoredVariableAndBacktrack()
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
std::function< void(Model *)> GreaterOrEqual(IntegerVariable v, int64_t lb)
PositiveOnlyIndex GetPositiveOnlyIndex(IntegerVariable var)
std::function< void(Model *)> ImpliesInInterval(Literal in_interval, IntegerVariable v, int64_t lb, int64_t ub)
bool VariableIsPositive(IntegerVariable i)
std::function< std::vector< IntegerEncoder::ValueLiteralPair >(Model *)> FullyEncodeVariable(IntegerVariable var)
double ToDouble(IntegerValue value)
Collection of objects used to extend the Constraint Solver library.
int64_t CapAdd(int64_t x, int64_t y)
int64_t CapProd(int64_t x, int64_t y)
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
IntegerValue Min(IntegerTrail *integer_trail) const
AffineExpression Negated() const
bool IsFixed(IntegerTrail *integer_trail) const
AffineExpression(IntegerVariable v, IntegerValue c, IntegerValue cst)
AffineExpression(IntegerValue cst)
IntegerLiteral GreaterOrEqual(IntegerValue bound) const
IntegerLiteral LowerOrEqual(IntegerValue bound) const
IntegerValue Max(IntegerTrail *integer_trail) const
double LpValue(const absl::StrongVector< IntegerVariable, double > &lp_values) const
AffineExpression(IntegerVariable v, IntegerValue c)
const std::string DebugString() const
bool operator==(AffineExpression o) const
AffineExpression(IntegerVariable v)
DebugSolution(Model *model)
IntegerDomains(Model *model)
ValueLiteralPair(IntegerValue v, Literal l)
bool operator<(const ValueLiteralPair &o) const
bool operator==(const ValueLiteralPair &o) const
bool operator==(IntegerLiteral o) const
IntegerLiteral(IntegerVariable v, IntegerValue b)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
std::string DebugString() const
IntegerLiteral Negated() const
bool operator!=(IntegerLiteral o) const