使用跟踪变量提高此代码的效率?

时间:2014-09-30 22:26:23

标签: algorithm invariants proof-of-correctness

我编写了下面的代码大纲,基本上是对一个数组(a)求和,其中每个元素乘以一个值x ^ i:

y = a(0)
i = 0
{y = sum from i=0 to (n-1) a(i) * x^i AND 0 <= n <= a.length} //Invariant

while (i < (n-1))
{y = sum from i=0 to (n-1) a(i) * x^i AND 0 <= n <= a.length AND i < (n-1)}
y = y + a(i)*x^i
i = i + 1
end while

{y = sum from i=0 to (n-1) a(i) * x^i} //Postcondition

请注意,我不希望编译代码 - 这只是代码应该如何工作的合理概述。我需要通过使用跟踪变量来提高代码的效率,因此,链接不变以将所述变量与其余代码桥接起来。这是我被困的地方。在这种情况下追踪什么是有用的?我已经考虑过在每次迭代时都保留和值,但是我不确定这是否有效。如果我能弄明白要追踪什么,我很确定将它与空间联系起来是微不足道的。谁能看到我的算法如何通过跟踪变量得到改善?

2 个答案:

答案 0 :(得分:1)

你的不变逻辑有一个一分一秒的问题。这是一个跟踪部分动力操作的修正版本。

// Precondition: 1 <= n <= a.length

// Invariant:
{ 0 <= i < n AND xi = x^i AND y = sum(j = 0..i) . a(j) * x^j }

// Establish invariant at i = 0:
//   xi = x^0 = 1 AND y = sum(j=0..0) . a(j) * x^j = a(0) * x^0 = a(0) 
i = 0;   
xi = 1; 
y = a(0);

while (i < n - 1) {

  i = i + 1;            // Break the invariant
  xi = xi * x;          // Re-establish it
  y = y + a(i) * xi 
}

// Invariant was last established at i = n-1, so we have post condition:
{ y = sum(j = 0..n-1) . a(j) * x^j }

计算多项式的更常见和数值稳定的方法是使用Horner的规则

y = 0
for i = n-1 downto 0 do y = y * x + a(i)

答案 1 :(得分:0)

所以你似乎想要最终得到这个:

(a(0)*x^0) + (a(1)*x^1) + ... + (a(n-1)*x^(n-1))

是吗?

我可以看到提高性能的唯一方法是^操作比*操作更昂贵。在这种情况下,您可以随时跟踪x^n变量,将x乘以每次迭代的值。

事实上,在这种情况下,你可以从数组的末尾开始,然后向后工作,每次乘以x,产生:

(((...((a(n-1)*x+a(n-2))*x+...)+a(2))*x+a(1))*x)+a(0)

理论上这比每次重新计算x ^ i要快一些,但它不会更快算法。它可能不会快一个数量级。