仅计算一次引用公式的算法

时间:2014-12-16 09:11:21

标签: php algorithm formula

我正在寻找一个很好的算法来解决以下问题。

我有以下VARIABLES和FORMULAS列表(var的结果是所有公式的总和):

var1, result=10
  - 5+5=10

var2, result=15
  - var1+5

var3, result=30
  - var1+var2+5

现在我正在寻找一种计算所有参考文献的好方法。如果我正在更改var1并且结果现在是15,我必须计算所有引用的var1。首先我遇到了var2和recalc var2,如果var2的结果发生变化,我必须将所有引用的公式重新计算为var2。因此我会recalc var3两次(var2改变,var1改变)......

有没有解决方案在这种情况下不对两次计算var3?

THX!

2 个答案:

答案 0 :(得分:3)

是的,你可以确保你只使用一个(最多)重新计算每个变量,使用没有循环依赖的事实(变量x无需y才能计算,同时y也需要x)。

这是通过将问题建模为graph来完成的,其中所有变量都是顶点,“所需”关系是有向边。 (因此,如果变量x“需要计算变量y,则存在边(y,x)}。

现在,由于No-Cyclic依赖,这实际上是Directed Acyclic Graph,您可以topological sort(这在预处理中只能执行一次)。请注意,在您的情况下,图表很可能已经排序,正弦值是按时间顺序排列的事件,按时间顺序排列是拓扑排序。

对图形进行拓扑排序(如果需要),以及变量何时更改:

Upon variable change:
1. Mark all changed variables
2. From first variable to last (according to topological sort), for each variable x:
      2.1. If there is some dependency `(y,x)` on the graph such that `y` is marked:
           2.1.1. mark x
           2.1.2. recalculate x

很容易看出,根据这种方法,每个变量最多计算一次。

答案 1 :(得分:1)

保留需要重新计算的变量/公式列表。使用此列表可以查看所有依赖项是否都是最新的。 如果不是这种情况,则应推迟更新变量。

回到您的示例,然后说var1更改。

第一步是将var放入列表中并检查所有依赖变量/公式。这些是var2var3,因此也将它们放在列表中。

接下来检查var2的依赖变量/公式(当你把它放在列表中时),这是var3,它已经在列表中,所以保留它。上次检查var3(您也添加了它),没有任何内容取决于var3,所以您已经完成了。 (注意递归行为!)

第二步是更新您的值。因此,找到一个具有所有依赖关系的变量/公式。只有var1没有依赖关系,所以从列表中弹出它并计算其值。

接下来在列表中找到另一个变量/公式,var3仍然依赖于var2(仍然/也在列表中),因此只有var2适合处理。 因此,从列表中弹出var2并计算其值。

继续处理列表,直到它为空。

假设您没有循环依赖关系:所有内容只计算一次!