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());
77 template <
class IntType>
79 return IntType(std::abs(t.value()));
82 inline IntegerValue
CeilRatio(IntegerValue dividend,
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;
104 IntegerValue positive_divisor) {
106 const IntegerValue m = dividend % positive_divisor;
107 return m < 0 ? m + positive_divisor : m;
112 const int64_t prod =
CapProd(
a.value(),
b.value());
116 const int64_t add =
CapAdd(prod, result->value());
120 *result = IntegerValue(add);
132 return IntegerVariable(i.value() ^ 1);
136 return (i.value() & 1) == 0;
140 return IntegerVariable(i.value() & (~1));
146 return PositiveOnlyIndex(
var.value() / 2);
151 const std::vector<IntegerVariable>& vars);
189 ? absl::StrCat(
"I",
var.value() / 2,
">=",
bound.value())
190 : absl::StrCat(
"I",
var.value() / 2,
"<=", -
bound.value());
195 IntegerValue
bound = IntegerValue(0);
246 IntegerValue
coeff = IntegerValue(0);
286 num_created_variables_(0) {}
289 VLOG(1) <<
"#variables created = " << num_created_variables_;
338 IntegerVariable
var)
const;
382 IntegerValue
value)
const;
396 if (lit.
Index() >= reverse_encoding_.
size()) {
397 return empty_integer_literal_vector_;
399 return reverse_encoding_[lit.
Index()];
406 if (lit.
Index() >= full_reverse_encoding_.
size()) {
407 return empty_integer_literal_vector_;
409 return full_reverse_encoding_[lit.
Index()];
415 return newly_fixed_integer_literals_;
418 newly_fixed_integer_literals_.clear();
427 return literal_view_[lit.
Index()];
446 IntegerValue*
bound)
const;
454 literal_index_true_ = literal_true.
Index();
457 return Literal(literal_index_true_);
465 IntegerVariable
var)
const {
466 if (
var >= encoding_by_var_.size()) {
467 return std::map<IntegerValue, Literal>();
469 return encoding_by_var_[
var];
485 void AddImplications(
const std::map<IntegerValue, Literal>& map,
486 std::map<IntegerValue, Literal>::const_iterator it,
492 bool add_implications_ =
true;
493 int64_t num_created_variables_ = 0;
509 full_reverse_encoding_;
510 std::vector<IntegerLiteral> newly_fixed_integer_literals_;
522 absl::flat_hash_map<std::pair<PositiveOnlyIndex, IntegerValue>,
Literal>
523 equality_to_associated_literal_;
537 std::vector<IntegerValue> tmp_values_;
552 parameters_(*
model->GetOrCreate<SatParameters>()) {
562 void Untrail(const
Trail& trail,
int literal_trail_index) final;
564 int trail_index) const final;
571 return IntegerVariable(vars_.
size());
631 const LiteralIndex is_ignored_literal = is_ignored_literals_[i];
637 return Literal(is_ignored_literals_[i]);
646 is_ignored_literals_[i] == is_considered.
NegatedIndex());
652 IntegerValue
LowerBound(IntegerVariable i)
const;
653 IntegerValue
UpperBound(IntegerVariable i)
const;
656 bool IsFixed(IntegerVariable i)
const;
700 absl::Span<const IntegerValue> coeffs,
701 std::vector<IntegerLiteral>* reason)
const;
705 absl::Span<const IntegerValue> coeffs,
706 absl::Span<const IntegerVariable> vars,
707 std::vector<IntegerLiteral>* reason)
const;
711 absl::Span<const IntegerValue> coeffs,
712 std::vector<int>* trail_indices)
const;
735 ABSL_MUST_USE_RESULT
bool Enqueue(
737 absl::Span<const IntegerLiteral> integer_reason);
747 std::vector<IntegerLiteral>* integer_reason);
756 ABSL_MUST_USE_RESULT
bool Enqueue(
758 absl::Span<const IntegerLiteral> integer_reason,
759 int trail_index_with_same_reason);
774 std::vector<Literal>* literals, std::vector<int>* dependencies)>;
781 absl::Span<const IntegerLiteral> integer_reason);
791 std::vector<Literal>* output)
const;
800 int64_t
timestamp()
const {
return num_enqueues_ + num_untrails_; }
810 watchers_.push_back(p);
816 absl::Span<const IntegerLiteral> integer_reason) {
817 DCHECK(ReasonIsValid(literal_reason, integer_reason));
819 conflict->assign(literal_reason.begin(), literal_reason.end());
824 DCHECK(ReasonIsValid({}, integer_reason));
833 return vars_[
var].current_trail_index < vars_.
size();
839 reversible_classes_.push_back(rev);
842 int Index()
const {
return integer_trail_.size(); }
870 return !literal_to_fix_.empty() || !integer_literal_to_fix_.empty();
876 bool ReasonIsValid(absl::Span<const Literal> literal_reason,
877 absl::Span<const IntegerLiteral> integer_reason);
882 std::vector<Literal>* InitializeConflict(
884 absl::Span<const Literal> literals_reason,
885 absl::Span<const IntegerLiteral> bounds_reason);
888 ABSL_MUST_USE_RESULT
bool EnqueueInternal(
890 absl::Span<const Literal> literal_reason,
891 absl::Span<const IntegerLiteral> integer_reason,
892 int trail_index_with_same_reason);
896 absl::Span<const Literal> literal_reason,
897 absl::Span<const IntegerLiteral> integer_reason);
902 ABSL_MUST_USE_RESULT
bool EnqueueAssociatedIntegerLiteral(
906 void MergeReasonIntoInternal(std::vector<Literal>* output)
const;
911 int FindLowestTrailIndexThatExplainBound(
IntegerLiteral i_lit)
const;
916 void ComputeLazyReasonIfNeeded(
int trail_index)
const;
923 absl::Span<const int> Dependencies(
int trail_index)
const;
929 void AppendLiteralsReason(
int trail_index,
930 std::vector<Literal>* output)
const;
933 std::string DebugString();
938 IntegerValue current_bound;
941 int current_trail_index;
951 mutable int var_trail_index_cache_threshold_ = 0;
956 absl::flat_hash_map<IntegerValue, IntegerVariable> constant_map_;
963 int32_t prev_trail_index;
968 int32_t reason_index;
970 std::vector<TrailEntry> integer_trail_;
971 std::vector<LazyReasonFunction> lazy_reasons_;
975 std::vector<int> integer_search_levels_;
982 std::vector<int> reason_decision_levels_;
983 std::vector<int> literals_reason_starts_;
984 std::vector<int> bounds_reason_starts_;
985 std::vector<Literal> literals_reason_buffer_;
990 std::vector<IntegerLiteral> bounds_reason_buffer_;
991 mutable std::vector<int> trail_index_reason_buffer_;
994 mutable std::vector<Literal> lazy_reason_literals_;
995 mutable std::vector<int> lazy_reason_trail_indices_;
1006 RevMap<absl::flat_hash_map<IntegerVariable, int>>
1007 var_to_current_lb_interval_index_;
1010 mutable bool has_dependency_ =
false;
1011 mutable std::vector<int> tmp_queue_;
1012 mutable std::vector<IntegerVariable> tmp_to_clear_;
1014 tmp_var_to_trail_index_in_queue_;
1015 mutable SparseBitset<BooleanVariable> added_variables_;
1022 std::vector<Literal> literal_to_fix_;
1023 std::vector<IntegerLiteral> integer_literal_to_fix_;
1026 struct RelaxHeapEntry {
1030 bool operator<(
const RelaxHeapEntry& o)
const {
return index < o.index; }
1032 mutable std::vector<RelaxHeapEntry> relax_heap_;
1033 mutable std::vector<int> tmp_indices_;
1036 mutable SparseBitset<IntegerVariable> tmp_marked_;
1042 std::vector<int> boolean_trail_index_to_integer_one_;
1046 int first_level_without_full_propagation_ = -1;
1048 int64_t num_enqueues_ = 0;
1049 int64_t num_untrails_ = 0;
1050 int64_t num_level_zero_enqueues_ = 0;
1051 mutable int64_t num_decisions_to_break_loop_ = 0;
1053 std::vector<SparseBitset<IntegerVariable>*> watchers_;
1054 std::vector<ReversibleInterface*> reversible_classes_;
1056 IntegerDomains* domains_;
1057 IntegerEncoder* encoder_;
1059 const SatParameters& parameters_;
1122 void Untrail(
const Trail& trail,
int literal_trail_index)
final;
1208 const std::function<
void(
const std::vector<IntegerVariable>&)> cb) {
1209 level_zero_modified_variable_callback_.push_back(cb);
1220 void UpdateCallingNeeds(
Trail* trail);
1230 return id == o.id && watch_index == o.watch_index;
1235 std::vector<PropagatorInterface*> watchers_;
1236 SparseBitset<IntegerVariable> modified_vars_;
1240 std::vector<std::deque<int>> queue_by_priority_;
1241 std::vector<bool> in_queue_;
1244 DEFINE_INT_TYPE(IdType, int32_t);
1245 std::vector<int> id_to_level_at_last_call_;
1246 RevVector<IdType, int> id_to_greatest_common_level_since_last_call_;
1247 std::vector<std::vector<ReversibleInterface*>> id_to_reversible_classes_;
1248 std::vector<std::vector<int*>> id_to_reversible_ints_;
1249 std::vector<std::vector<int>> id_to_watch_indices_;
1250 std::vector<int> id_to_priority_;
1251 std::vector<int> id_to_idempotence_;
1254 std::vector<int> propagator_ids_to_call_at_level_zero_;
1259 std::vector<std::function<void(
const std::vector<IntegerVariable>&)>>
1260 level_zero_modified_variable_callback_;
1270 IntegerValue
bound) {
1276 IntegerValue
bound) {
1291 IntegerValue
bound)
const {
1306 return vars_[i].current_bound;
1314 return vars_[i].current_bound == -vars_[
NegationOf(i)].current_bound;
1336 IntegerVariable i)
const {
1341 IntegerVariable i)
const {
1356 IntegerVariable
var)
const {
1357 return integer_trail_[
var.value()].bound;
1361 IntegerVariable
var)
const {
1366 return integer_trail_[
var.value()].bound ==
1372 if (l.
Index() >= literal_to_watcher_.
size()) {
1373 literal_to_watcher_.
resize(l.
Index().value() + 1);
1381 if (
var.value() >= var_to_watcher_.
size()) {
1382 var_to_watcher_.
resize(
var.value() + 1);
1389 const WatchData data = {id, watch_index};
1390 if (!var_to_watcher_[
var].empty() && var_to_watcher_[
var].back() == data) {
1427 ->GetOrCreateConstantIntegerVariable(IntegerValue(
value));
1436 IntegerValue(lb), IntegerValue(ub));
1456 IntegerVariable
var;
1458 if (assignment.LiteralIsTrue(lit)) {
1460 }
else if (assignment.LiteralIsFalse(lit)) {
1466 encoder->AssociateToIntegerEqualValue(lit,
var, IntegerValue(1));
1492 inline std::function<int64_t(
const Model&)>
Value(IntegerVariable v) {
1505 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1507 VLOG(1) <<
"Model trivially infeasible, variable " << v
1509 <<
" and GreaterOrEqual() was called with a lower bound of "
1519 std::vector<Literal>(), std::vector<IntegerLiteral>())) {
1521 LOG(
WARNING) <<
"Model trivially infeasible, variable " << v
1523 <<
" and LowerOrEqual() was called with an upper bound of "
1544 const std::vector<Literal>& enforcement_literals,
IntegerLiteral i) {
1551 std::vector<Literal> clause;
1572 int64_t lb, int64_t ub) {
1578 v, IntegerValue(lb))));
1592 inline std::function<std::vector<IntegerEncoder::ValueLiteralPair>(Model*)>
1608 std::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)
void resize(size_type new_size)
void push_back(const value_type &x)
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)
const InlinedIntegerLiteralVector & GetAllIntegerLiterals(Literal lit) const
LiteralIndex SearchForLiteralAtOrBefore(IntegerLiteral i, IntegerValue *bound) const
LiteralIndex GetAssociatedLiteral(IntegerLiteral i_lit) const
void FullyEncodeVariable(IntegerVariable var)
Literal GetFalseLiteral()
const IntegerVariable GetLiteralView(Literal lit) const
std::pair< IntegerLiteral, IntegerLiteral > Canonicalize(IntegerLiteral i_lit) const
void DisableImplicationBetweenLiteral()
void ClearNewlyFixedIntegerLiterals()
const std::vector< IntegerLiteral > NewlyFixedIntegerLiterals() const
void AssociateToIntegerEqualValue(Literal literal, IntegerVariable var, IntegerValue value)
const InlinedIntegerLiteralVector & GetIntegerLiterals(Literal lit) const
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::map< IntegerValue, Literal > PartialGreaterThanEncoding(IntegerVariable var) 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
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)
std::vector< Literal > * MutableConflict()
const VariablesAssignment & Assignment() const
bool LiteralIsTrue(Literal literal) const
absl::InlinedVector< IntegerLiteral, 2 > InlinedIntegerLiteralVector
IntegerValue FloorRatio(IntegerValue dividend, IntegerValue positive_divisor)
bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue *result)
std::function< void(Model *)> GreaterOrEqual(IntegerVariable v, int64_t lb)
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
std::function< void(Model *)> ClauseConstraint(absl::Span< const Literal > literals)
IntType IntTypeAbs(IntType t)
IntegerValue CeilRatio(IntegerValue dividend, IntegerValue positive_divisor)
const LiteralIndex kNoLiteralIndex(-1)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue)
std::function< BooleanVariable(Model *)> NewBooleanVariable()
std::function< int64_t(const Model &)> Value(IntegerVariable v)
std::function< std::vector< IntegerEncoder::ValueLiteralPair >Model *)> FullyEncodeVariable(IntegerVariable var)
const IntegerVariable kNoIntegerVariable(-1)
std::function< IntegerVariable(Model *)> NewIntegerVariableFromLiteral(Literal lit)
IntegerVariable PositiveVariable(IntegerVariable i)
IntegerValue PositiveRemainder(IntegerValue dividend, IntegerValue positive_divisor)
DEFINE_INT_TYPE(ClauseIndex, int)
std::function< void(Model *)> Implication(const std::vector< Literal > &enforcement_literals, IntegerLiteral i)
std::function< void(Model *)> LowerOrEqual(IntegerVariable v, int64_t ub)
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
std::function< void(Model *)> ExcludeCurrentSolutionWithoutIgnoredVariableAndBacktrack()
std::function< void(Model *)> ImpliesInInterval(Literal in_interval, IntegerVariable v, int64_t lb, int64_t ub)
std::function< void(Model *)> Equality(IntegerVariable v, int64_t value)
std::function< bool(const Model &)> IsFixed(IntegerVariable v)
PositiveOnlyIndex GetPositiveOnlyIndex(IntegerVariable var)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
bool VariableIsPositive(IntegerVariable i)
std::function< IntegerVariable(Model *)> ConstantIntegerVariable(int64_t value)
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)
AffineExpression Negated() const
AffineExpression(IntegerVariable v, IntegerValue c, IntegerValue cst)
AffineExpression(IntegerValue cst)
IntegerLiteral GreaterOrEqual(IntegerValue bound) const
IntegerLiteral LowerOrEqual(IntegerValue bound) const
double LpValue(const absl::StrongVector< IntegerVariable, double > &lp_values) const
AffineExpression(IntegerVariable v, IntegerValue c)
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