ortools cp-sat IntVar整数变量Long越界情况分类源码分析精讲
文章目录
一、最大最小值越界
1.结论
1.整数变量范围必须在[kint64min + 2, kint64max - 1]内。即越界情况
(1)如果整数变量的下界值< kint64min + 2( -9223372036854775806);
(2)如果整数变量的上界值> kint64max - 1( 9223372036854775806);。
2.报错
var #4 domain do not fall in [kint64min + 2, kint64max - 1]. name: "9223372036854775807" domain: 9223372036854775807 domain: 9223372036854775807
3.校验intvar变量的取值范围函数源码
在内部,我们经常对定义域取反,并且我们还希望具有大于变量定义域的最小值/最大值的哨兵值, 因此定义域必须在[kint64min + 2, kint64max - 1]范围内。
函数ValidateIntegerVariable
作用是验证整数变量的定义域是否有效。函数接受一个CpModelProto
类型的模型和一个整数变量索引v
作为参数,并返回一个std::string
类型的结果。
3.1首先
获取模型中索引为v
的整数变量的定义域信息。如果定义域为空,则返回一个包含错误信息的字符串,指示变量没有定义域。如果定义域的大小为奇数,则返回一个包含错误信息的字符串,指示定义域大小不正确。如果定义域格式无效(例如存在重叠的区间或区间边界不按照升序排列),则返回一个包含错误信息的字符串。
3.2接下来
函数检查定义域的范围是否在有效范围内。根据注释,定义域必须在[kint64min + 2, kint64max - 1]范围内。如果定义域的最小值小于std::numeric_limits<int64_t>::min() + 2
或最大值大于std::numeric_limits<int64_t>::max() - 1
,则返回一个包含错误信息的字符串。
3.2最后
函数检查定义域的范围是否过大,即上界和下界之差超过了int64_t
的表示范围。如果下界小于0且下界加上std::numeric_limits<int64_t>::max()
仍然小于上界,说明定义域太大,可能会导致溢出。函数返回一个包含错误信息的字符串。
如果以上所有检查都通过,则返回一个空字符串,表示整数变量的定义域有效。
std::string ValidateIntegerVariable(const CpModelProto& model, int v) {
const IntegerVariableProto& proto = model.variables(v);
if (proto.domain_size() == 0) {
return absl::StrCat("变量 #", v,
" 没有定义域:", ProtobufShortDebugString(proto));
}
if (proto.domain_size() % 2 != 0) {
return absl::StrCat("变量 #", v, " 的定义域大小为奇数:",
ProtobufShortDebugString(proto));
}
if (!DomainInProtoIsValid(proto)) {
return absl::StrCat("变量 #", v, " 的定义域格式无效:",
ProtobufShortDebugString(proto));
}
// 在内部,我们经常对定义域取反,并且我们还希望具有大于变量定义域的最小值/最大值的哨兵值,
// 因此定义域必须在[kint64min + 2, kint64max - 1]范围内。
const int64_t lb = proto.domain(0);
const int64_t ub = proto.domain(proto.domain_size() - 1);
if (lb < std::numeric_limits<int64_t>::min() + 2 ||
ub > std::numeric_limits<int64_t>::max(