【问题标题】:Find contradiction in list在列表中查找矛盾
【发布时间】:2017-03-20 09:19:03
【问题描述】:

我有很多列表,我想找出是否有与其他列表相矛盾的列表。 一个列表不会被他们自己冲突,所有的关系都只有'>''<'

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"]

在上述情况下,list3list1 矛盾,因为 "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"]

在这种情况下,list5list4 矛盾,因为 "d" 不能同时大于 9 和小于 8。

【问题讨论】:

  • 变量是否总是位于相同的索引上?
  • 代码在哪里,你试过了吗?
  • 抱歉不清楚,实际上,变量会改变它们在不同列表中的位置
  • @jimmy15923:列表是否有时会与自身发生冲突,例如list1=["a&lt;1","a&gt;2"]?此外,所有关系&lt;&gt; 吗?请考虑重写您的问题以更好地说明问题。现在它有很多开放的结局。
  • @WillemVanOnsem 不,他们自己不会冲突列表。

标签: python list logic


【解决方案1】:

您可以简单地为每个包含上限和下限的变量维护一个列表。如果变量没有上限或下限,则可以使用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]。接下来,我们通过更新与约束相对应的索引来更新边界('&gt;' 为 0,'&lt;' 为 1)。我们最后检查边界是否仍然可能。就是这样,我们返回True。否则我们返回False。从出现此类绑定错误的那一刻起,我们就知道这两个列表存在冲突。

现在我们仍然需要处理列表并相应地更新管理器。因此我们开发了一个正则表达式:

(\w+)\s*(<|>)\s*(-?\d+)

所以这里我们假设每个字符串的格式为\w+(变量名),后跟'&lt;''&gt;',最后是值-?\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

【讨论】:

  • 我想知道是哪个变量冲突了,怎么办?我试过 if la[1]
  • @jimmy15923:所有变量?还是第一个失败的?
  • 感谢您的回复!我已经给出了答案。 if la[1] != None and la[0]!= None and la[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 + l2l1 + l3l2 + l3 三种组合。您还应该注意,对于大型列表,性能可能会变差。

【讨论】:

  • 这正是我试图做的,但无济于事。你知道为什么simplify(And(Rel(a, 4, '&lt;'),Rel(a, 5, '&gt;'))) 不是False 同情吗?
  • 猜测 simplify 不会尝试解决这个显然没有解决方案的关系,而只是试图简化它.
猜你喜欢
  • 1970-01-01
  • 2017-11-06
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-03
  • 2014-10-30
  • 1970-01-01
相关资源
最近更新 更多