Python z3py推送后型号错误,但在没有

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,

我尝试在增量模型上使用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,
 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我编辑并发布了整个源代码,您可以最小化此示例吗?当然,这种行为应该通过一个小得多的程序表现出来。有关如何发布堆栈溢出问题,请参见以下内容: