我有很多名单,我想找到是否与其他人相矛盾。
列表不会与他们自己发生冲突,所有关系仅为'>'
和'<'
:
list1 = ["a<4", "b<3", "c<3", "d<6"]
list2 = ["b<6", "a<1", "c<5", "d<2"]
list3 = ["a>7", "c<2", "b>1", "d<8"]
在上述情况下,list3
与list1
相矛盾,因为"a"
不能同时大于7且小于4。
另一个例子
list4 = ["a<4", "b<3", "c>2", "d<8"]
list5 = ["b<6", "a<6", "c<5", "d>9"]
list6 = ["a>2", "b>1", "d<8", "c<9"]
在这种情况下,list5
与list4
相矛盾,因为"d"
不能同时大于9且小于8。
答案 0 :(得分:2)
您可以简单地为每个包含上限和下限的变量维护一个列表。如果变量没有上限或下限,则可以使用None
。
每次评估约束时,都会相应地更新列表,当下限大于上限时,我们知道存在冲突。
现在我们只需要几个部分:
变量管理器可以如下工作:
def update_variables(var_dict,variable,constraint,value):
la = var_dict.get(variable)
if la is None:
la = [None,None]
var_dict[variable] = la
if constraint == '>' and (la[0] is None or value > la[0]):
la[0] = value
elif constraint == '<' and (la[1] is None or value < la[1]):
la[1] = value
return la[0] is None or la[1] is None or la[0] < la[1]
首先,我们检查变量是否已经是字典的一部分。如果不是,我们添加[None,None]
。接下来,我们通过更新与约束对应的索引来更新边界('>'
为0,'<'
为1)。我们最后检查是否仍然可以绑定。就是这种情况,我们返回True
。否则我们返回False
。从这种绑定错误的那一刻起,我们就知道这两个列表是冲突的。
现在我们仍然需要处理列表并相应地更新管理器。因此我们开发了一个正则表达式:
(\w+)\s*(<|>)\s*(-?\d+)
因此,我们假设每个字符串都具有格式\w+
(变量的名称),后跟'<'
或'>'
,最后是值-?\d+
。每次我们从列表中获取此类字符串,解析它,更新管理器并检查配置是否仍然有效。所以这看起来像:
import re
def conflict(lista,listb):
manager = {}
rgx = re.compile(r'(\w+)\s*(<|>)\s*(-?\d+)')
for listi in (lista,listb):
for constraint in listi:
mat = rgx.match(constraint)
if mat:
var,con,val = mat.groups()
val = int(val)
if not update_variables(manager,var,con,val):
return True # the lists are conflicting
else:
raise Exception('Could not parse constraint "%s"'%constraint)
return False # the lists do not conflict
这会产生:
>>> conflict(list3,list1)
True
>>> conflict(list1,list1)
False
>>> conflict(list1,list2)
False
>>> conflict(list1,list3)
True
>>> conflict(list2,list3)
True
答案 1 :(得分:2)
你可以试试SymPy。
from sympy.solvers import solve
from sympy import symbols
from sympy.parsing.sympy_parser import parse_expr
a, b, c, d = symbols('a b c d')
list1 = ["a<4", "b<3", "c<3", "d<6"]
list2 = ["b<6", "a<1", "c<5", "d<2"]
list3 = ["a>7", "c<2", "b>1", "d<8"]
l1 = [parse_expr(eq) for eq in list1]
l2 = [parse_expr(eq) for eq in list2]
l3 = [parse_expr(eq) for eq in list3]
print(solve(l1 + l2))
print(solve(l1 + l3))
print(solve(l2 + l3))
列表中的字符串将使用parse_expr
解析为不等式。然后,您必须将列表与+
连接起来,并尝试一次解决8个不等式。如果你得到False
,那么这是不可能的,因此你有一个矛盾。否则,您可以获得a, b, c, d
的正确值的表达式,以实现不等式。所以你可以这样写:
def contradiction(l_i, l_j):
s = solve(l_i + l_j)
if s==False: return True
else: return False
当然,如果你有很多字符串列表,那么你必须找到一种方法来组合所有列表,就像我在这里手动一样,因为只有三种组合l1 + l2
,l1 + l3
和{{ 1}}。此外,您应该注意,对于大型列表,性能可能会变差。