达夫尼(Dafny)建议,乘以奇数并不总是得出奇数结果

时间:2020-11-01 16:19:17

标签: dafny

我有一个数字序列,并根据数字的奇数执行操作。它最终沸腾到一个变量中只有奇数个数,这导致不变式失败,因为它坚持认为数字不是奇数。

要检查它,我做了这个。在这里,只要数字为奇数,它就会尝试将其相乘。除非我忽略了某些内容,否则将两个奇数相乘应始终会导致另一个奇数(因为它应为(m+1)*(n+1))。 dafny承认数字为奇数时,将乘法视为断言。

if A[i]%2 == 0 {
  ... // not important skip for now
} else {
  assert A[i]%2 == 1;
  assert (A[i] * A[i])%2 == 1;
  ... // do something with it, lets say multiply
}

有解决这个问题的方法吗?
数组本身包含整数(偶数和奇数)。
(这是在while周期内执行的操作)。

1 个答案:

答案 0 :(得分:0)

我们想展示以下引理。

lemma odd_mul_odd(a: int, b: int)
requires a % 2 == 1
requires b % 2 == 1
ensures (a * b) % 2 == 1

在Dafny中做了一些数学证明后,我了解到a == (a/b)*b + (a%b)是它可以轻松证明的一个公理。

因此,我将尝试基于以下逻辑进行证明:

  • 为某些x写a = 2x + 1
  • 将b = 2y + 1写入y
  • 写(a * b)= 4xy + 2x + 2y + 1 = 2(2xy + x + y)+1
  • 因此(a * b)%2 == 1

这是在达夫尼,

lemma odd_mul_odd(a: int, b: int)
requires a % 2 == 1
requires b % 2 == 1
ensures (a * b) % 2 == 1
{
  var x := a / 2;
  var y := b / 2;

  calc {
    a * b;
    {   
      assert a == 2*x + 1;
      assert b == 2*y + 1;
    }   
    (2*x + 1) * (2*y + 1); 
    4*x*y + 2*x + 2*y + 1;
    2*(2*x*y + x + y) + 1;
  }

  calc {
    (a * b) % 2;
    (2*(2*x*y + x + y) + 1) % 2;
    1;  
  }
}

不幸的是,在达夫尼,这些数学证明有点令人痛心。我唯一的建议是自由使用calc语句,一次只做一步。

相关问题