这是我遇到的问题。我有一个评估者列表,I_1,I_2 ......等,彼此之间存在依赖关系。像I_1这样的东西 - > I_2(读取,I_2取决于I_1的结果)。没有循环依赖。
每个共享接口bool eval(),double value()。比如说I_1-> eval()会更新I_1的结果,可以通过I_1-> value()返回。并且eval()返回的布尔值告诉我结果是否已更改,如果是,则需要更新所有依赖于I_1的I_js。
现在说I_1已更新结果,如何运行尽可能少的eval()以保持所有I_js最新?
答案 0 :(得分:0)
你需要像l_1中的广度优先搜索,省略搜索从eval()返回的节点的后代表示它们没有改变,并考虑到在评估所有节点之前不应评估节点它直接依赖的节点。排除这种情况的一种方法是在每个节点上保留未评估的直接依赖性计数,减少依赖于刚刚评估的节点的所有节点的计数。在每个阶段,如果尚未评估的节点必须存在,则必须至少有一个不依赖于未评估节点的节点。如果不是,您可以通过从一个节点到它依赖的节点等来生成无限量的未评估节点列表,并且我们知道依赖图中没有循环。
在https://en.wikipedia.org/wiki/Breadth-first_search处有广度优先搜索的伪代码。
答案 1 :(得分:0)
我只是有一个这样的嵌套循环:
first do a tree-walk from I_1, marking it and all descendants as out-of-date
make a list of those descendants
anything_changed = true
while anything_changed
anything_changed = false
for each formula in the descendant list
if no predecessors of that formula in the descendant list are out of date
re-evaluate the formula and assert that it is not out of date
anything_changed = true
看,它粗糙但正确。 那么如果它有点像二次大O呢? 如果公式的数量不是太大,和/或评估每个公式的成本不是太小,和/或如果不是高频率,那么性能应该不是问题。
答案 2 :(得分:0)
有效的解决方案是建立两种关系。如果I_2
取决于I_1
,那么您将I_1 --influences--> I_2
和I2 --depends on--> I_1
作为关系。
您基本上需要能够有效地计算I_X
所依赖的过时评估的数量(让我们称之为D(I_X)
)
然后,您执行以下操作:
Do a BFS with the --influences--> relation, storing all reachable I_X
Store the reachable I_X in a data structure that sorts them according to their D(I_X) , e.g. a Priority Queue
// finding the D(I_X) could be integrated into the DFS and require little additional calculation time
while (still nodes to update):
Pop and re-evaluate the I_X with the lowest D(I_X) value (e.g. the first I_X from the Queue) (*)
Update the D(I_Y) value for all I_Y with I_X --influences--> I_Y
(i.e. lower it by 1)
Update the sorting/queue to reflect the new D(I_Y) values
(*)第一个元素应始终具有D(I_X) == 0
,否则,您可能具有循环依赖
上面的算法使用相当多的时间来查找要更新和排序的节点,但是它获得的优势是它只会重新评估每I_X
次。
答案 3 :(得分:0)
如果可以,我会添加从父母到其受抚养子女的链接,因此更新将变为: -
change_value ()
{
evaluate new_value based on all parents
if (value != new_value)
{
value = new_value
for each child
child->change_value ()
}
}
当然,您需要应对Child(n)是Child(m)的父母的案例
实际上,考虑一下,它可能会起作用,但不会是对change_value的最小调用