Python z3py推送后型号错误,但在没有
我尝试在增量模型上使用Z3,但得到了一个奇怪的模型 当代码包含Python z3py推送后型号错误,但在没有,python,z3,z3py,Python,Z3,Z3py,我尝试在增量模型上使用Z3,但得到了一个奇怪的模型 当代码包含 s.push() [some calcution to get constant 4 and 3 in below lines] s.add(ans6==4) s.add(ans9==3) 结果表明,这个模型是不正确的 [ans0 = 2, ans1 = 3, ans2 = 1, **ans6 = 2,** ans8 = 2, ans7 = 1, **ans9 = 1,** ans4 = 1, ans5 = 3,
s.push()
[some calcution to get constant 4 and 3 in below
lines]
s.add(ans6==4)
s.add(ans9==3)
结果表明,这个模型是不正确的
[ans0 = 2,
ans1 = 3,
ans2 = 1,
**ans6 = 2,**
ans8 = 2,
ans7 = 1,
**ans9 = 1,**
ans4 = 1,
ans5 = 3,
ans3 = 3]
但是,如果我添加s.add(ans6==4)以及
s、 将(ans9==3)piror添加到s.push(),模型正确为unsat
是bug还是我用错了Z3?我认为它可能表示为软约束,但文档没有提到
完整资料来源如下:
#!/usr/bin/env python
# coding: utf-8
from z3 import *
# ten multiple choices
ans = [Int('ans%d' % (i)) for i in range(10)]
letters = {}
for i in range(5):
letters[i] = "0ABCD"[i]
choice_a = 1
choice_b = 2
choice_c = 3
choice_d = 4
choice_shitty = 999
choices = [choice_a, choice_b, choice_c, choice_d]
s = Solver()
for i in range(10):
s.add(Or(ans[i] == choice_a, ans[i] == choice_b, ans[i] == choice_c, ans[i] == choice_d))
#2
s.add(Or(And(ans[1] == choice_a, ans[4] == choice_c),
And(ans[1] == choice_b, ans[4] == choice_d),
And(ans[1] == choice_c, ans[4] == choice_a),
And(ans[1] == choice_d, ans[4] == choice_b)))
#3
s.add(Or(And(ans[2] == choice_a, And(ans[2] != ans[5], ans[5] == ans[1], ans[1] == ans[3])),
And(ans[2] == choice_b, And(ans[5] != ans[2], ans[2] == ans[1], ans[1] == ans[3])),
And(ans[2] == choice_c, And(ans[1] != ans[2], ans[2] == ans[5], ans[5] == ans[3])),
And(ans[2] == choice_d, And(ans[3] != ans[5], ans[2] == ans[5], ans[5] == ans[1]))))
#4
s.add(Or(And(ans[3] == choice_a, ans[0] == ans[4]),
And(ans[3] == choice_b, ans[1] == ans[6]),
And(ans[3] == choice_c, ans[0] == ans[8]),
And(ans[3] == choice_d, ans[5] == ans[9])))
#5
s.add(Or(And(ans[4] == choice_a, ans[4] == ans[7]),
And(ans[4] == choice_b, ans[4] == ans[3]),
And(ans[4] == choice_c, ans[4] == ans[8]),
And(ans[4] == choice_d, ans[4] == ans[6])))
#6
s.add(Or(And(ans[5] == choice_a, And(ans[1] == ans[3], ans[3] == ans[7])),
And(ans[5] == choice_b, And(ans[0] == ans[5], ans[5] == ans[7])),
And(ans[5] == choice_c, And(ans[2] == ans[9], ans[9] == ans[7])),
And(ans[5] == choice_d, And(ans[4] == ans[8], ans[8] == ans[7]))))
#7
#8
s.add(Or(And(ans[7] == choice_a, Not(Or(ans[0] - ans[6] == 1, ans[0] - ans[6] == -1))),
And(ans[7] == choice_b, Not(Or(ans[0] - ans[4] == 1, ans[0] - ans[4] == -1))),
And(ans[7] == choice_c, Not(Or(ans[0] - ans[1] == 1, ans[0] - ans[1] == -1))),
And(ans[7] == choice_d, Not(Or(ans[0] - ans[9] == 1, ans[0] - ans[9] == -1)))))
#9
s.add(Or(And(ans[8] == choice_a, Or(And((ans[0] == ans[5]), Not(ans[5] == ans[4])),
And(Not(ans[0] == ans[5]), (ans[5] == ans[4])))),
And(ans[8] == choice_b, Or(And((ans[0] == ans[5]), Not(ans[9] == ans[4])),
And(Not(ans[0] == ans[5]), (ans[9] == ans[4])))),
And(ans[8] == choice_c, Or(And((ans[0] == ans[5]), Not(ans[1] == ans[4])),
And(Not(ans[0] == ans[5]), (ans[1] == ans[4])))),
And(ans[8] == choice_d, Or(And((ans[0] == ans[5]), Not(ans[8] == ans[4]))),
And(Not(ans[0] == ans[5]), (ans[8] == ans[4])))))
#10
# max - min count
#for c in s.assertions():
# print (c)
#s.check()
#print (s.model())
#s.add(ans[6] == 4)
#s.add(ans[9] == 3)
result = []
while True:
if s.check() == unsat:
print ("no solution or search done(?)")
print ("RESULT FOUND = ", len(result))
break
elif s.check() == sat:
m = s.model()
#print (m)
# prevent next model from using the SAME assignment as a previous model
block = []
for cond in m:
clause = cond()
block.append(clause != m[cond])
#print(block)
# special case: #7和#10
s.push()
cnt = {}
for c in choices:
cnt[c] = sum([1 for a in ans if m[a] == c])
mincnt_choice = min(cnt, key=cnt.get)
maxcnt_choice = max(cnt, key=cnt.get)
mincnt = cnt[mincnt_choice]
maxcnt = cnt[maxcnt_choice]
diff = maxcnt - mincnt
print ('ANSWER LETTER COUNTS: ', cnt, 'MIN: ', letters[mincnt_choice], 'MAX: ', letters[maxcnt_choice])
print ('DIFF for #10:', diff)
#7
if mincnt_choice == choice_a:
s.add(ans[6] == choice_c)
elif mincnt_choice == choice_b:
s.add(ans[6] == choice_b)
elif mincnt_choice == choice_c:
s.add(ans[6] == choice_a)
elif mincnt_choice == choice_d:
s.add(ans[6] == choice_d)
else:
# impossible
s.add(ans[6] == choice_shitty)
#10
if diff == 3:
s.add(ans[9] == choice_a)
elif diff == 2:
s.add(ans[9] == choice_b)
elif diff == 4:
s.add(ans[9] == choice_c)
elif diff == 1:
s.add(ans[9] == choice_d)
else:
# impossible
s.add(ans[9] == choice_shitty)
for c in s.assertions():
print (c)
if s.check() == unsat:
print ("#7/#10 constraint failed\n")
s.pop()
s.add(Or(block))
elif s.check() == sat:
print ('SOLUTION: -------------------\n')
print (m)
#for i in range(10):
# sys.stdout.write (str(i+1)+". "+letters[int(str(m[ans[i]]))]+"\n")
#print ("\n")
result.append(m)
# prevent next model from using the SAME assignment as a previous model
block = []
for cond in m:
clause = cond()
block.append(clause != m[cond])
s.pop()
s.add(Or(block))
else:
print ("exception")
else:
print ("exception")
如果没有办法重现这个问题,就不可能回答可能出现的问题。请发布一个最小的重复案例,以便堆栈溢出读者可以指出可能的错误。z3不太可能推错。您的代码可能在做一些古怪的事情,但如果不看到实际的可复制问题,就不可能说出来。@alias我编辑并发布了整个源代码,您可以最小化此示例吗?当然,这种行为应该通过一个小得多的程序表现出来。有关如何发布堆栈溢出问题,请参见本文:如果没有重现此问题的方法,就不可能回答可能出现的问题。请发布一个最小的重复案例,以便堆栈溢出读者可以指出可能的错误。z3不太可能推错。您的代码可能在做一些古怪的事情,但如果不看到实际的可复制问题,就不可能说出来。@alias我编辑并发布了整个源代码,您可以最小化此示例吗?当然,这种行为应该通过一个小得多的程序表现出来。有关如何发布堆栈溢出问题,请参见以下内容: