如何确定嵌套列表结构是否与另一个相同,但是元素已交换为新的

时间:2019-05-31 02:06:58

标签: python permutation

假设我们有两个嵌套列表:L1 = [[0, 1], [0, 2]]L2 = [[1, 2], [1, 3]]

问题是,一个列表中的整数与另一列表中的整数之间是否存在双射,从而将L1转换为L2?对于上面给出的L1L2,答案是肯定的。

双向:

  • 旧的0变成新的1
  • 旧的1变成新的2
  • 旧的2成为新的3

回想一下我们的嵌套列表L1 = [[0, 1], [0, 2]]。如果应用上述映射,则将得到L2 = [[1, 2], [1, 3]]。因此,foo(L1, L2)应该返回Truefoo是我们尝试实现的相等运算符的名称。

此外,顺序无关紧要。每个列表都应视为数学上的“集合”。

一些示例如下所示:

左列表:[[2, 1], [3, 1]]
右列表:[[1, 2], [1, 3]]:是 foo(left,right)返回True
为什么?
顺序没关系

左列表:[[2, 1], [3, 1]]
右键列表:[[1, 2], [3, 4]]
foo(left,right)返回False
为什么?
左侧列表中的两个整数是相同的,但右侧列表中的所有整数彼此都不相同。

left = [[2, 1], [3, 1]]
right = [[0, 1], [0, 1]]
foo(left, right)返回False
为什么?
右边的列表仅包含2个不同的整数(01)。左侧列表包含3个不同的整数(123

下面显示了一些更长的示例:

原始列表:[[0, 1], [0, 2], [1, 2], [1, 3], [0, 1, 2]]

A1:[[4, 1], [4, 0], [1, 0], [1, 3], [4, 1, 0]]:是

A2:[[4, 1], [4, 0], [1, 3], [1, 0], [4, 0, 1]]:是

B:[[1, 2], [3, 1], [2, 4], [1, 4], [2, 4, 1]]:是

C:[[3, 2], [5, 2], [5, 0], [0, 2], [5, 0, 2]]:是

D:[[5, 2], [5, 2], [3, 0], [0, 2], [5, 0, 2]]:错误

E:[[3, 0], [0, 3], [5, 0], [0, 2], [5, 0, 2]]:错误

示例A1的双射:

ORIGINAL  A
 0        4
 1        1
 2        0
 3        3    

A2只是A1

的重新排序

在示例B中,2和4与原始列表中的0和2扮演相同的角色。在两个列表中,1和3的角色相同。

在示例C中,0和5在原始列表中的作用与0和2相同,2在原始列表中的作用与1相同,而3在两个列表中的作用相同。 在示例D中,有两个相同的子列表([5,2]),而原始列表没有重复的子列表。 在示例E中,所有四个length-2子列表中都为0,而在原始列表中,所有四个length-2子列表中都没有数字。

这是我尝试获得的代码,但是当将低数字(如0)交换为列表中最大的数字之一(如4)时,它不起作用。当进行排序时,它无法识别4所起的作用与0相同。由于可以将小数转换为大数,因此无法进行排序。

def CheckUnique(configs, newconfig):
    sortednewconfig = sorted([sorted(i) for i in newconfig])
    presentnumbers = []
    canonicalnewconfig = []
    for sub in sortednewconfig:
        for i in sub:
            if i not in presentnumbers:
                presentnumbers.append(i)
    for sub in sortednewconfig:
        cansub = []
        for i in sub:
            cansub.append(presentnumbers.index(i))
        canonicalnewconfig.append(cansub)
    if canonicalnewconfig not in configs:
        return True
    else:
        return False

2 个答案:

答案 0 :(得分:1)

allanyzip一起使用:

>>> l = [[0, 1], [0, 2], [1, 2], [1, 3], [0, 1, 2]]
>>> l2 = [[4, 1], [4, 0], [1, 3], [1, 0], [4, 0, 1]]
>>> all([any(i in x for i in y) for x, y in zip(l, l2)])
True
>>> l3 = [[5, 2], [5, 2], [3, 0], [0, 2], [5, 0, 2]]
>>> all([any(i in x for i in y) for x, y in zip(l, l3)])
False
>>> 

答案 1 :(得分:1)

您正在尝试解决所谓的“ failure”的修改形式。现有的算法可以确定两个图是否同构,但是现有的算法都非常慢,特别是对于大型图。

图形”是带有点和线的图。

假设我们有两个嵌套列表:

L1 = [[0, 1], [0, 2], [1, 2], [1, 3], [0, 1, 2]]
L2 = [[4, 1], [4, 0], [1, 3], [1, 0], [4, 0, 1]] 

按照以下说明绘制图片L1

  • 对于子列表的每个元素,绘制一个点。例如考虑子列表 [0, 1]。它将得到两个点,一个0的点和一个1的点。
  • 如果点在同一点上,则围绕点簇绘制一个圆圈 子列表。
  • 如果两个点表示相同的整数,请在两个点之间画一条线。

graph isomorphism problem

然后,将每组点(子列表)压缩为一个点。

initial graph

您可以为嵌套列表L2绘制类似的图,问题是,在删除所有数字之后,L1和L2的两个图看起来是否相同?您可能需要交换周围的颜色(蓝色边缘变为红色,红色变为蓝色等)。此外,可能还需要移动点,直到看起来相同为止。

传统的图形同构问题具有连接所有相同颜色的点的线。您的问题与传统的问题稍有不同,因为您的边缘是彩色的。

我认为您可以摆脱单独的颜色,而只需用以前存在的颜色数量为每个边缘编号。然后,它变成一个“边缘加权图”

condensed graph

在Google上搜索“边缘加权图的图同构”。

您正在从事的工作非常困难 。我建议您在本地大学数学系的网站上查找可以联系的人。寻找职位为“图形理论家”的教授的电子邮件地址。与他们联系,并征求他们的意见。

就像我说的那样,您正在做的工作 极其 很困难。

我认为您可以按以下方法解决它:

  1. 为左侧列表构建边缘加权图
  2. 为右侧列表构建边缘加权图
  3. 确定两个图是否同构。