Python z3-意外输出/不确定输出的含义

Python z3-意外输出/不确定输出的含义,python,z3,z3py,Python,Z3,Z3py,我问了一下,得到了一封信。然而,我不得不扩展这个答案来处理大量数据(下面的代码)。然而,在这样做的过程中,我得到了一个我不理解的输出 有时候,我会得到一个unsat,有时候我会得到sat,因为s.check();有时运行s.check()和s.model()需要很长时间,其他时间则需要几秒钟。然而,我不明白的是,当我得到这样的输出时: [else -> Or(Var(0) == 7, Var(0) == 13, Var(0) == 43, Var(0) == 20

我问了一下,得到了一封信。然而,我不得不扩展这个答案来处理大量数据(下面的代码)。然而,在这样做的过程中,我得到了一个我不理解的输出

有时候,我会得到一个
unsat
,有时候我会得到
sat
,因为
s.check()
;有时运行
s.check()
s.model()
需要很长时间,其他时间则需要几秒钟。然而,我不明白的是,当我得到这样的输出时:

[else ->
 Or(Var(0) == 7,
    Var(0) == 13,
    Var(0) == 43,
    Var(0) == 20,
    Var(0) == 26,
    Var(0) == 16,
    Var(0) == 45,
    Var(0) == 21,
    Var(0) == 36,
    Var(0) == 5,
    Var(0) == 6,
    Var(0) == 35,
    Var(0) == 50,
    Var(0) == 28,
    Var(0) == 10,
    Var(0) == 27,
    Var(0) == 34,
    Var(0) == 14,
    Var(0) == 51,
    Var(0) == 48,
    Var(0) == 47,
    Var(0) == 19)]
[else ->
 Or(Var(0) == 22, Var(0) == 15, Var(0) == 8, Var(0) == 24)]
[else ->
 Or(Var(0) == 44, Var(0) == 17, Var(0) == 46, Var(0) == 11)]
[else ->
 Or(Var(0) == 49,
    Var(0) == 42,
    Var(0) == 9,
    Var(0) == 31,
    Var(0) == 12,
    Var(0) == 18,
    Var(0) == 23,
    Var(0) == 34)]
我不确定
else->…
是什么意思,而且每个集合中的变量平衡都是关闭的(更不用说没有变量
44
)。我将感谢任何帮助。完整代码如下

in_var_list = []
in_var_list.append(("var 1", 4, [3]))
in_var_list.append(("var 2", 3, [3, 4, 5, 6]))
in_var_list.append(("var 3", 3, [3, 4, 5, 6]))
in_var_list.append(("var 4", 4, [4, 5, 6], ["var 3"]))
in_var_list.append(("var 6", 4, [4, 5, 6], ["var 3"]))
in_var_list.append(("var 7", 3, [4, 5, 6], ["var 4"]))
in_var_list.append(("var 8", 3, [3, 4]))
in_var_list.append(("var 9", 3, [5]))
in_var_list.append(("var 10", 3, [6], ["var 9"]))
in_var_list.append(("var 11", 3, [3, 5]))
in_var_list.append(("var 12", 3, [3, 4, 5, 6]))
in_var_list.append(("var 13", 3, [4]))
in_var_list.append(("var 14", 3, [3]))
in_var_list.append(("var 15", 3, [5]))
in_var_list.append(("var 16", 3, [5, 6]))
in_var_list.append(("var 17", 4, [3, 4, 5, 6]))
in_var_list.append(("var 18", 3, [3, 4, 5, 6]))
in_var_list.append(("var 19", 3, [3, 4, 5, 6]))
in_var_list.append(("var 20", 3, [4, 5, 6], ["var 2"]))
in_var_list.append(("var 21", 3, [5, 6], ["var 2", "var 1"]))
        #variable name, variable size, possible sets, prerequisites

in_set_list = [(3, 18), (4, 18), (5, 18), (6, 18)]
            #set name, max set size

from z3 import *

s = Solver()

allElems = {vari[0]: Int(vari[0]) for vari in in_var_list}
s.add(Distinct(list(allElems.values())))

#Python 3.6 - dictionaries are ordered
#split into sets
allSets = {c_set[0]: Const(str(c_set[0]), SetSort(IntSort())) for c_set in in_set_list}

#Generic requirement: Every element belongs to some set:
for e in allElems.values():
    belongs = False;
    for x in allSets.values():
        belongs = Or(belongs, IsMember(e, x))
    s.add(belongs)

#capacity requirements
for c_set in in_set_list:
  c_set_size = Int(c_set[1])
  s.add(SetHasSize(allSets[c_set[0]], c_set_size))
  s.add(c_set_size <= c_set[1])

#vari set requirements
for vari in in_var_list:
  set_mem_list = []
  for c_set in vari[2]:
    set_mem_list.append(IsMember(allElems[vari[0]], allSets[c_set]))
  s.add(Or(set_mem_list))

#pre-set requirements
vari_dict = {vari[0]: vari for vari in in_var_list}
for vari in in_var_list:
  try: #may not include preset
    for prereq in in_var_list[3]:
      for i, c_set in enumerate(in_set_list):
        if c_set[0] in vari_dict[prereq][2]:
          imps = []
          for subc_set in in_set_list[i+1:]:
            imps.append(IsMember(allElems[vari[0]], allSets[subc_set]))
          s.add(Implies(IsMember(allElems[prereq], allSets[c_set[0]], Or(imps))))
          s.add(Not(IsMember(allElems[prereq], allSets[in_set_list[-1]])))
  except:
    pass

r = s.check()
print(r)
if r == sat:
  modout = s.model()
else:
  raise ValueError('unsat - too many constraints, cannot fit all variables as given')

vari_out = {modout[allElems[vari]]: vari for vari in allElems}
print(vari_out)

set_out = dict()
for s in allSets:
  set_out[s] = modout[allSets[s]].as_list()

rets = dict()
for s in allSets:
  rets[s] = []
  for c in (set_out)[s][0].children():
    try:
      rets[s].append(vari_out[c.children()[1]])
    except:
      pass
print(rets)

"""# print results"""

from pprint import pprint
pprint(rets)
在变量列表中=[]
在变量列表中追加((“变量1”,4,[3]))
在变量列表中追加((“变量2,3,4,5,6]))
在变量列表中追加((“变量3,3,3,4,5,6]))
在变量列表中追加((“变量4,4,4,5,6],“变量3”))
在变量列表中追加((“变量6,4,4,5,6],“变量3”))
在变量列表中追加((“变量7,3,4,5,6],“变量4”))
在变量列表中追加(((“变量8,3,4]))
在变量列表中追加((“变量9”,3,[5]))
在变量列表中追加((“变量10”,3,[6],“变量9”))
在变量列表中追加((“变量11,3,5]))
在变量列表中追加((“变量12,3,4,5,6]))
在变量列表中追加((“变量13”,3,[4]))
在变量列表中追加((“变量14”,3,[3]))
在变量列表中追加((“变量15”,3,[5]))
在变量列表中追加((“变量16,3,5,6]))
在变量列表中追加((“变量17,4,3,4,5,6]))
在变量列表中追加((“变量18,3,4,5,6]))
在变量列表中追加(((“变量19,3,4,5,6]))
在变量列表中追加((“变量20,3,4,5,6],“变量2”))
在变量列表中追加((“变量21,3,[5,6],“变量2”,“变量1”))
#变量名称、变量大小、可能的集合、先决条件
在集合列表中=[(3,18)、(4,18)、(5,18)、(6,18)]
#集合名称,最大集合大小
从z3进口*
s=解算器()
等位基因={vari[0]:Int(vari[0]),用于变量in_var_list}
s、 添加(不同的(列表(allegems.values()))
#Python3.6-字典是有序的
#分成几组
allSets={c_集[0]:c_集列表中c_集的常量(str(c_集[0]),SetSort(IntSort()))
#一般要求:每个元素都属于某个集合:
对于等位基因中的e.ms.values():
属于=假;
对于Allset.values()中的x:
归属=或(归属,IsMember(e,x))
s、 添加(属于)
#容量要求
对于集合列表中的集合:
c_集大小=Int(c_集[1])
s、 添加(设置大小(所有集[c_集[0]],c_集[U大小))

s、 添加(c_set_size您的约束显然不可满足,因为所有可变权重之和高于所有最大设置权重之和。不幸的是,通常没有简单的方法从Z3获得约束不可满足原因的解释

与本文和中的示例相比,当前的示例似乎相当简单,而且应该运行得相当快,即使对于更多类似的约束也是如此。我没有检查您的实现细节,但可能有某种原因允许变量变得非常高(而不是约束到4个给定集).在这种情况下,Z3将产生许多在后期被拒绝的可能性

为了获得更一致的行为,每次运行都重新启动Python可能会有所帮助(我在PyCharm的控制台中进行测试,每次都重新启动控制台)

根据教程中的示例,我将如下处理约束。为了获得一个令人满意的示例,在每个所需的集合大小中添加4

in_var_list=[([var 1,4,3]),([var 2,3,4,5,6]),([var 3,3,3,4,5,6]),([var 4,4,4,5,6],[var 3],([var 6,4,5,6],[var 3,4,5,6]),([var 7,3,4,4],[var 8,3,3,4],[var 9,3,5],[var 10,3,6],[var 9],[var 3,4],[var 3,4],[var 3],[var 3,5],[var 3],[4,5],[var 3],[4],[var 3],[4],[4],[4],[4],[4],[var],[4],[4],[4],[4](“风险值14,4,3],(“风险值15,4,5],(“风险值16,4,5,6],(“风险值17,4,4,5,6”),(“风险值18,4,3,4,5,6],(“风险值19,4,3,4,5,6”),(“风险值20,4,4,5,6],(“风险值21,4,5,6],“风险值2”,“风险值1”)。#变量名称,变量大小,可能的集合,前提条件
在集合列表中=[(3,18)、(4,18)、(5,18)、(6,8)]集合名称,最大集合大小
从z3导入Int、Solver或和、Sum、If、sat
#将空列表添加到长度为3的元组
in_var_list=[tup if len(tup)==4 else(*tup,[])表示in_var_list中的tup]
打印(“所有权重之和:”,和([在变量列表中的权重,))
打印(“最大权重之和:”,和([max\usize for uu,max\usize in u set\u list]))
s=解算器()
v={varname:Int(varname)表示varname,*.\in\u var\u list}
对于名称、重量、位置集、变量列表中的预请求:
s、 添加(或([v[name]==p表示pos_集合中的p])#每个变量应位于其可能的集合中
s、 添加(并且([v[r]s、 添加(名称、权重、变量列表中的总和([If(v[name]==snum,weight,0)])如果你能发布一个最小的可复制示例,堆栈溢出效果最好。请参阅此处以获取指导原则:尽量将你的程序减少到显示问题的最小值,你将获得关于如何继续的更好指导。而且,很可能,你将解决过程中面临的问题,这将是非常有教育意义的。祝你好运!@ali因为我很难最小化代码,因为相同的代码在多次运行时会给出不同的结果。我只是尝试重新运行它,得到了4个“else”子句,而不是2个“else”和2个“lambda”“子句。这是预期的吗?我该如何克服它?z3内部使用随机数;因此,如果有多个可用的模型,则每次运行程序时可能会得到不同的模型。(虽然
sat
问题不应变成
unsat
问题,反之亦然。这将是一个错误。)首先,我要减少变量的数量:不是21个变量,而是从几个变量开始,并确保有一个可靠的程序
sum of all weights: 74
sum of max weights: 62

assignments: {'var 1': 3, 'var 2': 4, 'var 3': 3, 'var 4': 4, 'var 6': 5, 'var 7': 5, 'var 8': 3, 'var 9': 5, 'var 10': 6, 'var 11': 3, 'var 12': 4, 'var 13': 4, 'var 14': 3, 'var 15': 5, 'var 16': 5, 'var 17': 5, 'var 18': 4, 'var 19': 3, 'var 20': 6, 'var 21': 6}
set 3: ['var 1', 'var 3', 'var 8', 'var 11', 'var 14', 'var 19'] desired size: 18, effective size: 22
set 4: ['var 2', 'var 4', 'var 12', 'var 13', 'var 18'] desired size: 18, effective size: 19
set 5: ['var 6', 'var 7', 'var 9', 'var 15', 'var 16', 'var 17'] desired size: 18, effective size: 22
set 6: ['var 10', 'var 20', 'var 21'] desired size: 8, effective size: 11