证明在Coq中终止

时间:2013-10-22 00:56:53

标签: coq termination

如何证明size_prgm的终止?我试过了,但是无法想出一个完善的关系来传递给Fix

Inductive Stmt : Set :=
| assign: Stmt
| if': (list Stmt) -> (list Stmt) -> Stmt.

Fixpoint size_prgm (p: list Stmt) : nat := 
  match p with
  | nil  => 0
  | s::t => size_prgm t +
            match s with
            | assign  => 1
            | if' b0 b1 => S (size_prgm b0 + size_prgm b1)
            end
  end.

2 个答案:

答案 0 :(得分:3)

终止oracle比过去好多了。使用sum_with定义函数fold_left并将其递归到size_prgm的递归调用非常有效。

Require Import List.

Inductive Stmt : Set :=
| assign: Stmt
| if': (list Stmt) -> (list Stmt) -> Stmt.

Definition sum_with {A : Type} (f : A -> nat) (xs : list A) : nat :=
  fold_left (fun n a => n + f a) xs 0.

Fixpoint size_prgm (p: Stmt) : nat := 
  match p with
  | assign    => 1
  | if' b0 b1 => sum_with size_prgm b1 + sum_with size_prgm b0
end.

答案 1 :(得分:1)

简短回答,因为我现在没有太多时间(我会稍后再回复你): 这是一个非常普通(而且很愚蠢)的问题,每个Coq用户都必须经历一天。

如果我没记错的话,这个问题有两个“通用”解决方案,还有很多非常具体的解决方案。对于前两位:

  1. 构建一个内部修复点:我真的不记得如何正确地做到这一点。
  2. 使用相互递归类型:代码的问题在于您在list Stmt类型中使用Stmt,而Coq无法计算您想到的归纳原则。但你可以使用像

    这样的时间
    Inductive Stmt : Set :=
      | assign : Stmt
      | if': list_Stmt -> list_Stmt -> Stmt
    with list_Stmt : Set :=
      | Nil_Stmt : list_Stmt
      | Cons_Stmt : Stmt -> list_Stmt -> list_Stmt.
    
  3. 现在使用此类型编写您的函数,并在此类型与原始Stmt类型之间进行双射。

    您可以尝试浏览Coq-Club邮件列表,这类主题是反复出现的。

    希望它有点帮助, V