使用 Isabelle 证明(命令式)算法的正确性和终止

发布于 2025-01-13 11:30:07 字数 1442 浏览 0 评论 0原文

我是一名本科生,试图证明欧几里德 gcd 和欧几里德扩展 gcd 算法的命令式版本的正确性和终止性。我使用IMP语言来实现第一个,并使用霍尔逻辑来证明正确性和终止:

lemma "⊢{λs. s ''a'' = n ∧ s ''b'' = m ∧ n > 0 ∧ m > 0 ∧ (gcd (s ''a'') (s ''b'') = gcd (n) (m))}
        WHILE (Or (Less (V ''b'') (V ''a'')) (Less (V ''a'') (V ''b'')))
        DO (IF (Less (V ''b'') (V ''a'')) THEN
               (''a'' ::= Sub (V ''a'') (V ''b''))
            ELSE
               (''b'' ::= Sub (V ''b'') (V ''a'')))
        {λs. s ''a'' = gcd (s ''A'') (s ''B'')}"
  apply (rule While'[where P = "λs. s ''a'' = n ∧ s ''b'' = m ∧ 0 < n ∧ 0 < m ∧ gcd (s ''a'') (s ''b'') = gcd n m"])
  apply auto
    apply (rule Assign')
    apply auto
    prefer 2
    apply (rule Assign')
  apply auto

剩余的子目标是:

proof (prove)
goal (3 subgoals):
 1. ⋀s. 0 < s ''a'' ⟹ m = s ''b'' ⟹ n = s ''a'' ⟹ s ''a'' < s ''b'' ⟹ False
 2. ⋀s. 0 < s ''b'' ⟹ m = s ''b'' ⟹ n = s ''a'' ⟹ s ''b'' < s ''a'' ⟹ False
 3. ⋀s. n = s ''a'' ⟹ m = s ''a'' ⟹ 0 < s ''a'' ⟹ s ''b'' = s ''a'' ⟹ s ''a'' = gcd (s ''A'') (s ''B'')

并且我现在不知道如何完成证明。这里的gcd函数是GCD库中的默认gcd。我还尝试了 Arith2 库中的这个定义:

definition cd :: "[nat, nat, nat] ⇒ bool"
  where "cd x m n ⟷ x dvd m ∧ x dvd n"

definition gcd :: "[nat, nat] ⇒ nat"
  where "gcd m n = (SOME x. x>0 ∧ cd x m n & (∀y.(cd y m n) ⟶ y dvd x))"

我写的正确吗?我应该如何继续?我应该使用这些定义还是应该自己编写 gcd 函数的递归版本?这种做法正确吗?

I'm an undergraduate student trying to prove correctness and termination of imperative version of Euclidean gcd and Euclidean extended gcd algorithm. I used IMP language to implement the first one and Hoare logic to prove correctness and termination:

lemma "⊢{λs. s ''a'' = n ∧ s ''b'' = m ∧ n > 0 ∧ m > 0 ∧ (gcd (s ''a'') (s ''b'') = gcd (n) (m))}
        WHILE (Or (Less (V ''b'') (V ''a'')) (Less (V ''a'') (V ''b'')))
        DO (IF (Less (V ''b'') (V ''a'')) THEN
               (''a'' ::= Sub (V ''a'') (V ''b''))
            ELSE
               (''b'' ::= Sub (V ''b'') (V ''a'')))
        {λs. s ''a'' = gcd (s ''A'') (s ''B'')}"
  apply (rule While'[where P = "λs. s ''a'' = n ∧ s ''b'' = m ∧ 0 < n ∧ 0 < m ∧ gcd (s ''a'') (s ''b'') = gcd n m"])
  apply auto
    apply (rule Assign')
    apply auto
    prefer 2
    apply (rule Assign')
  apply auto

remaining sub goals are:

proof (prove)
goal (3 subgoals):
 1. ⋀s. 0 < s ''a'' ⟹ m = s ''b'' ⟹ n = s ''a'' ⟹ s ''a'' < s ''b'' ⟹ False
 2. ⋀s. 0 < s ''b'' ⟹ m = s ''b'' ⟹ n = s ''a'' ⟹ s ''b'' < s ''a'' ⟹ False
 3. ⋀s. n = s ''a'' ⟹ m = s ''a'' ⟹ 0 < s ''a'' ⟹ s ''b'' = s ''a'' ⟹ s ''a'' = gcd (s ''A'') (s ''B'')

and I don't now how to finish the proof. The gcd function here is default gcd from GCD library. I also tried this definition from Arith2 library:

definition cd :: "[nat, nat, nat] ⇒ bool"
  where "cd x m n ⟷ x dvd m ∧ x dvd n"

definition gcd :: "[nat, nat] ⇒ nat"
  where "gcd m n = (SOME x. x>0 ∧ cd x m n & (∀y.(cd y m n) ⟶ y dvd x))"

Is what I wrote correct and how should I continue? Should I use these definitions instead or should I write recursive version of gcd function myself? Is this approach correct?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

戴着白色围巾的女孩 2025-01-20 11:30:08

首先,你在一个地方有一个类型,在这里你谈论 s ''A''s ''B'' 而不是 s ' 'a''s ''b''。但这当然不是您要问的问题。

这里的问题是前提条件太强,无法使用 WHILE 规则。它包含条件 s ''a'' = ns ''b'' = m,这显然不能作为循环不变式,因为循环修改了变量 ab,因此在一次循环迭代之后,条件 s ''a'' = ns ' 之一'b'' = m 将不再成立。

你需要找出一个比你现在拥有的弱的适当的不变量。您要做的就是踢出 s ''a'' = ns ''b'' = m。然后你的证明就通过了。

然后,您可以使用 strengthen_pre 规则恢复您实际想要显示的语句。

因此,证明的开始看起来像这样:

lemma "⊢{λs. s ''a'' = n ∧ s ''b'' = m ∧ n ≥ 0 ∧ m ≥ 0 ∧ (gcd (s ''a'') (s ''b'') = gcd (n) (m))}
        WHILE (Or (Less (V ''b'') (V ''a'')) (Less (V ''a'') (V ''b'')))
        DO (IF (Less (V ''b'') (V ''a'')) THEN
               (''a'' ::= Sub (V ''a'') (V ''b''))
            ELSE
               (''b'' ::= Sub (V ''b'') (V ''a'')))
        {λs. s ''a'' = gcd (s ''a'') (s ''b'')}"
  apply (rule strengthen_pre) 
  defer
   apply (rule While'[where P = "λs. s ''a'' ≥ 0 ∧ s ''b'' ≥ 0 ∧ gcd (s ''a'') (s ''b'') = gcd n m"])

为了避免这种尴尬的手动使用strengthen_pre,IMP的其他版本允许直接在算法本身中注释WHILE循环的不变量,以便VCG(验证条件生成器)可以自动为您提供所有需要证明的内容,而无需手动应用霍尔规则。

附录:但请注意,您的后置条件也存在问题:

{λs. s ''a'' = gcd (s ''a'') (s ''b'')}

这不是你想要显示的!这只是意味着执行后a的值是ab值的GCDafter执行。这也恰好是正确的,因为 ab 在算法完成后始终相等 - 但您真正想知道的是 a< 的值/code>执行后等于ab执行前的GCD,即等于gcd n m.因此,您必须将后置条件更改为

{λs. s ''a'' = gcd nm}

First of all, you have a type in one place, where you talk about s ''A'' and s ''B'' instead of s ''a'' and s ''b''. But that is of course not the problem you were asking about.

The problem here is that the precondition is too strong to work with the WHILE rule. It contains the conditions s ''a'' = n and s ''b'' = m, which clearly do not work as a loop invariant since the loop modifies the variables a and b, so after one loop iteration, one of the conditions s ''a'' = n and s ''b'' = m will no longer hold.

You need to figure out a proper invariant that is weaker than what you have now. What you have to do is to kick out the s ''a'' = n and s ''b'' = m. Then your proof goes through.

You can then recover the statement you actually want to show with the strengthen_pre rule.

So the start of your proof would look something like this:

lemma "⊢{λs. s ''a'' = n ∧ s ''b'' = m ∧ n ≥ 0 ∧ m ≥ 0 ∧ (gcd (s ''a'') (s ''b'') = gcd (n) (m))}
        WHILE (Or (Less (V ''b'') (V ''a'')) (Less (V ''a'') (V ''b'')))
        DO (IF (Less (V ''b'') (V ''a'')) THEN
               (''a'' ::= Sub (V ''a'') (V ''b''))
            ELSE
               (''b'' ::= Sub (V ''b'') (V ''a'')))
        {λs. s ''a'' = gcd (s ''a'') (s ''b'')}"
  apply (rule strengthen_pre) 
  defer
   apply (rule While'[where P = "λs. s ''a'' ≥ 0 ∧ s ''b'' ≥ 0 ∧ gcd (s ''a'') (s ''b'') = gcd n m"])

To avoid this awkward manual use of strengthen_pre, other versions of IMP allow annotating the invariants of WHILE loops directly in the algorithm itself, so that a VCG (verification condition generator) can automatically give you all the things you have to prove and you don't have to apply Hoare rules manually.

Addendum: Note however that there is also a problem with your postcondition:

{λs. s ''a'' = gcd (s ''a'') (s ''b'')}

This is not what you want to show! This just means that the value of a after the execution is the GCD of the values of a and b after the execution. This also happens to be true because a and b are always equal after the algorithm has finished – but what you really want to know is that the value of a after the execution is equal to the GCD of a and b before the execution, i.e. equal to gcd n m. You therefore have to change your postcondition to

{λs. s ''a'' = gcd n m}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文