循环直到Python中复杂数据结构的稳定状态

时间:2011-11-08 14:05:41

标签: python

我有一个或多或少复杂的数据结构(集合字典列表),我在循环中执行一系列操作,直到数据结构达到稳定状态,即。不再改变了。执行计算所需的迭代次数因输入而异。

我想知道在这种情况下是否存在形成停止条件的既定方法。我能想到的最好的方法就是挑选数据结构,存储md5并检查它是否与上一次迭代有所不同。由于这比我的操作更昂贵,我每20次迭代只会这样做,但仍然感觉不对。

是否有更好或更便宜的方法来检查深度平等,以便我知道何时停止?

谢谢!

4 个答案:

答案 0 :(得分:4)

看看python-deep。它应该做你想要的,如果它不够快,你可以自己修改它。

这在很大程度上取决于比较操作的成本以及一次计算迭代的成本。比如,一次计算迭代需要c次,一次测试需要t次,终止的机会是p,那么最佳测试频率是:

(t * p) / c

假设是c < t,如果不是这样,那么你应该明确检查每个循环。

因此,您可以动态地跟踪ct并估算p(如果代码怀疑计算将要结束,可能会在代码中进行调整),您可以设置你的测试频率达到最佳值。

答案 1 :(得分:3)

我认为你唯一的选择是:

  1. 每次更新都会在从起始状态改变值时标记为“脏标志”。

  2. 进行整体结构分析(如您建议的pickle / md5组合)。

  3. 只需运行已知达到稳定状态的固定次数的迭代(可能运行太多次但没有检查终止条件的开销)。

  4. 选项1类似于Python本身对引用计数的作用。选项2类似于Python对垃圾收集器的作用。选项3在数值分析中很常见(即,计算平方根的除法和平均值为20次)。

答案 2 :(得分:2)

检查我的平等似乎不是正确的方法。如果您完全控制了您执行的操作,我将引入一个“modified”标志(布尔变量),在每次迭代开始时设置为false。每当您的某个操作修改(部分)数据结构时,它就会设置为true,并执行重复,直到修改在整个迭代过程中保持为“false”。

答案 3 :(得分:1)

我相信python等号运算符可以合理地有效地比较内置对象的组合。 我希望它比pickling + hashing更快,前提是列表相等的python测试:

def __eq__(a,b):
    if type(a) == list and type(b) == list:
        if len(a) != len(b):
            return False
        for i in range(len(a)):
            if a[i] != b[i]:
                return False
        return True
    #testing for other types goes here

由于函数在找到两个不匹配的元素后立即返回,因此在一般情况下它不需要遍历整个事物。与散列相比,散列需要迭代整个数据结构,即使在最好的情况下也是如此。

我将如何做到这一点:

import copy

def perform_a_bunch_of_operations(data):
    #take care to not modify the original data, as we will be using it later
    my_shiny_new_data = copy.deepcopy(data)
    #do lots of math here...
    return my_shiny_new_data

data = get_initial_data()
while(True):
    nextData = perform_a_bunch_of_operations(data)
    if data == nextData: #steady state reached
        break
    data = nextData

这样做的缺点是每次迭代都必须对数据进行深度复制,但它可能仍然比散列更快 - 您只能通过分析特定情况来确定。