【发布时间】:2022-08-08 10:50:20
【问题描述】:
我想断言一个数字的最高位是一个特定的值,但我实际上并不知道数字的长度。如果它是最低有效数字,我知道我可以使用 python mod (%) 来检查它。但是由于位数未知,我不确定如何在 z3 中检查它。
例如,我可能知道最左边的数字是 9,例如 9x、或 9xx、或 9xxx 等。
非常感谢提前
我想断言一个数字的最高位是一个特定的值,但我实际上并不知道数字的长度。如果它是最低有效数字,我知道我可以使用 python mod (%) 来检查它。但是由于位数未知,我不确定如何在 z3 中检查它。
例如,我可能知道最左边的数字是 9,例如 9x、或 9xx、或 9xxx 等。
非常感谢提前
执行此操作的通用方法是转换为字符串并检查第一个字符是否匹配:
from z3 import *
s = Solver()
n = Int('n')
s.add(SubString(IntToStr(n), 0, 1) == "9")
r = s.check()
if r == sat:
m = s.model()
print("n =", m[n])
else:
print("Solver said:", r)
这打印:
n = 9
请注意,IntToStr 期望其参数为非负数,因此如果您需要支持负数,则必须编写额外的代码来适应它。有关详细信息,请参阅https://smtlib.cs.uiowa.edu/theories-UnicodeStrings.shtml。
在旁边虽然这将实现您想要的一般性,但它可能不是编码此约束的最有效方式。由于它通过字符串,生成的约束可能会导致性能问题。如果您的号码有上限,则明确编码可能会更有效。例如,如果您知道您的号码小于 1000,我会将其编码为(伪代码):
n == 9 || n >= 90 && n <= 99 || n >= 900 && n <= 999
等等,直到你覆盖了你需要的范围。这将导致更简单的约束并且总体上表现更好。请注意,即使您不知道确切的长度,但它有一个上限,这也会起作用。但是,当然,这完全取决于您要达到的目标以及您对数字本身的了解。
【讨论】: