Z3 将至少一个从1到N的赋值的约束写入Sat解算器中的一组变量

Z3 将至少一个从1到N的赋值的约束写入Sat解算器中的一组变量,z3,smt,Z3,Smt,我是在sat解算器的背景下提出这个问题的。 假设我有100个整数变量x1,x2,x3。。。x100在1到N之间随机分配一个值。我想确保x1到x100中至少有一个变量的值应为1到N 现在我想在sat解算器约束中对这个问题进行编码。因为在编写约束时,我不知道值N,所以很难按照下面的方式编写代码- (assert (x1 = 0 or x2 = 0 or ... x100 = 0)) (assert (x1 = 1 or x2 = 1 or ... x100 = 1)) (assert (x1 = 2

我是在sat解算器的背景下提出这个问题的。 假设我有100个整数变量
x1,x2,x3。。。x100
1到N之间随机分配一个值
。我想确保
x1到x100
中至少有一个变量的值应为
1到N

现在我想在sat解算器约束中对这个问题进行编码。因为在编写约束时,我不知道值
N
,所以很难按照下面的方式编写代码-

(assert (x1 = 0 or x2 = 0 or ... x100 = 0))
(assert (x1 = 1 or x2 = 1 or ... x100 = 1))
(assert (x1 = 2 or x2 = 2 or ... x100 = 2))
...
(assert (x1 = N or x2 = N or ... x100 = N))
假设,在最后,我断言N的值为2,那么上述约束将不起作用。此外,出于性能原因,我不想使用数组或未解释的函数

更新:

简言之,限制条件如下:

  • N<100
  • (假设N=20),那么有20个变量,可能是从x_1到x_100的任意一个,它们是不同的。因此,该约束将确保为从1到N的每个值分配至少一个变量
  • 其余变量(100-N)的值可能相互重叠

  • 有人能给我一些建议吗?

    使用
    distinct
    谓词。请看:

    我会写

    (assert (or (and (> x1 0) (<= x1 n))
                (and (> x2 0) (<= x2 n))
                ...same for x3 thru x99...
                (and (> x100 0) (<= x100 n))))
    

    (断言(或(和(>x10)(x20)(x100)(将Kyle的答案与distinct结合起来如何,最多n个x_i变量(随机选择)

    这将给出如下模型(对于N=50和100 x_i变量):

    这里有一个Z3Py脚本实现了这一点,假设可以约束前N个索引,而不是随机索引(并且使用x的函数而不是常数,因此写入速度更快):

    接下来是对一组随机索引执行此操作的代码,但您不能在上运行此操作Z3Py@Rise,因为它不允许使用导入,所以您必须在本地运行它

    from random import *
    from z3 import *
    
    x = Function('x', IntSort(), IntSort())
    
    M = 100
    N = 50
    
    s = Solver()
    idxs = sample(xrange(M),N) # get N random ids from sequence {1,...M}
    print idxs
    
    distinctlist = []
    for i in range(M):
      s.add(And(x(i) >= 1, x(i) <= N))
      if i in idxs:
        distinctlist.append(x(i))
    
    print distinctlist
    
    s.add(Distinct(distinctlist))
    
    print "checking..."
    
    r = s.check()
    print r
    if r == sat:
      print s.model()
    
    来自随机导入的
    *
    从z3进口*
    x=函数('x',IntSort(),IntSort())
    M=100
    N=50
    s=解算器()
    idxs=sample(xrange(M),N)#从序列{1,…M}中获取N个随机id
    打印IDX
    distinctlist=[]
    对于范围内的i(M):
    
    s、 加(和(x(i)>=1,x(i)使用
    distinct
    谓词将确保每个变量都有唯一的值。但是,如果N小于100,则一些变量
    具有相等的值。因此我认为,使用
    distinct
    谓词将不起作用。这是真的,我就是这么做的。但是,这并不能确保至少有一个变量s设置在1到n之间。想象一下,如果所有变量x1到x100都被赋值为1,它就满足了条件。然而,我希望至少有一个变量的每个值都在1到n之间。多亏了这个奇妙的答案。然而,我认为这仍然不是解决方案。这是因为,我可以看到,你强制x1到x_50是不同的,其余的都是不同的不在乎。不过,我可能想知道,我不知道哪些是不同的,哪些是相同的。我认为这种编码是不可能的。非常感谢!@Raj,我想你需要重写你的问题。我们似乎都不知道完整的约束是什么。我在que中添加了一个小摘要stion。我认为在断言中,您必须以某种方式约束x_I,以便获得分配的所有值。您可以使用此解决方案和随机生成的ID向量(某种程度上)不确定地分配将被约束的索引。您可以使用python的
    random.sample来实现这一点(xrange(M),N)
    ,它从序列{1,…M}中获取N个随机ID。这里是Z3Py中的一个链接(但请注意,您必须在本地运行此脚本,因为Z3Py不允许使用导入,这需要python随机库):这不是我想要的。不过,我将接受它作为答案。谢谢!
    from random import *
    from z3 import *
    
    x = Function('x', IntSort(), IntSort())
    
    M = 100
    N = 50
    
    s = Solver()
    idxs = sample(xrange(M),N) # get N random ids from sequence {1,...M}
    print idxs
    
    distinctlist = []
    for i in range(M):
      s.add(And(x(i) >= 1, x(i) <= N))
      if i in idxs:
        distinctlist.append(x(i))
    
    print distinctlist
    
    s.add(Distinct(distinctlist))
    
    print "checking..."
    
    r = s.check()
    print r
    if r == sat:
      print s.model()