我有一个或多或少复杂的数据结构(集合字典列表),我在循环中执行一系列操作,直到数据结构达到稳定状态,即。不再改变了。执行计算所需的迭代次数因输入而异。
我想知道在这种情况下是否存在形成停止条件的既定方法。我能想到的最好的方法就是挑选数据结构,存储md5并检查它是否与上一次迭代有所不同。由于这比我的操作更昂贵,我每20次迭代只会这样做,但仍然感觉不对。
是否有更好或更便宜的方法来检查深度平等,以便我知道何时停止?
谢谢!
答案 0 :(得分:4)
看看python-deep。它应该做你想要的,如果它不够快,你可以自己修改它。
这在很大程度上取决于比较操作的成本以及一次计算迭代的成本。比如,一次计算迭代需要c
次,一次测试需要t
次,终止的机会是p
,那么最佳测试频率是:
(t * p) / c
假设是c < t
,如果不是这样,那么你应该明确检查每个循环。
因此,您可以动态地跟踪c
和t
并估算p
(如果代码怀疑计算将要结束,可能会在代码中进行调整),您可以设置你的测试频率达到最佳值。
答案 1 :(得分:3)
我认为你唯一的选择是:
每次更新都会在从起始状态改变值时标记为“脏标志”。
进行整体结构分析(如您建议的pickle / md5组合)。
只需运行已知达到稳定状态的固定次数的迭代(可能运行太多次但没有检查终止条件的开销)。
选项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
这样做的缺点是每次迭代都必须对数据进行深度复制,但它可能仍然比散列更快 - 您只能通过分析特定情况来确定。