Isabelle 非终止归纳谓词
它说的很好 […]与递归函数相比,没有终止要求 用于归纳定义。(pdf第40页)Isabelle 非终止归纳谓词,isabelle,induction,non-termination,Isabelle,Induction,Non Termination,它说的很好 […]与递归函数相比,没有终止要求 用于归纳定义。(pdf第40页) 这是否意味着有归纳定义,其中可能有一个无限深的派生树 这种非终止派生(最好是具有无限高度的派生)的示例是什么?你如何“构建”这些 这些规则的归纳原则如何仍然合理 不,你需要共导谓词 不存在 如果你看归纳原理,你会发现它们有一个额外的前提。例如,“偶数n”。这意味着,在你应用归纳原理之前,你需要知道你手头有一个有限的导数 不,你需要共导谓词 不存在 如果你看归纳原理,你会发现它们有一个额外的前提。例如,“偶数n”。这
拉尔斯已经回答了这个问题,但我想进一步讨论他提到的共导谓词。这些确实允许您拥有“无限深的派生树”,对应于codatatypes本质上是“可能无限的数据类型” 一个很好的例子是来自
~~/src/HOL/Library/stream
的流类型:
codatatype 'a stream = SCons 'a "'a stream" (infixr "##" 65)
这是一个无限列表(请注意,与例如Haskell列表不同,此流类型必须无限长,就像您在Haskell中编写的datatype stream a=SCons a(stream a)
一样,尽管Haskell样式的“潜在无限”列表也可能是直接的,参见AFP中的惰性列表)
例如,您可以定义其值来自给定集合的所有流的集合。您可以将其定义为streams A={s.sset s⊆ A}
,但在Isabelle中,它的定义如下:
coinductive_set streams :: "'a set ⇒ 'a stream set" for A :: "'a set"
where "⟦a ∈ A; s ∈ streams A⟧ ⟹ a ## s ∈ streams A"
另一个可能更简单的例子是流上的共导“for all element”谓词:
coinductive sall :: "('a ⇒ bool) ⇒ 'a stream ⇒ bool" for P :: "'a ⇒ bool" where
"P x ⟹ sall P xs ⟹ sall P (x ## xs)"
至于如何构造这样一个无限派生树的问题,也就是说,显示一个共归纳谓词包含某个值,你必须通过共归纳来实现这一点。例如,我们可以证明如果px
保持不变,那么sall P(sconst x)
保持不变,其中sconst x
只是无限重复的值x
:
lemma sconst_reduce: "sconst x = x ## sconst x"
by (subst siterate.code) simp_all
lemma sall_sconst: "P x ⟹ sall P (sconst x)"
proof (coinduction rule: sall.coinduct)
assume "P x"
thus "∃y ys. sconst x = y ## ys ∧ P y ∧ (ys = sconst x ∧ P x ∨ sall P ys)"
by (subst sconst_reduce) auto
qed
拉尔斯已经回答了这个问题,但我想进一步讨论他提到的共导谓词。这些确实允许您拥有“无限深的派生树”,对应于codatatypes本质上是“可能无限的数据类型”
一个很好的例子是来自~~/src/HOL/Library/stream
的流类型:
codatatype 'a stream = SCons 'a "'a stream" (infixr "##" 65)
这是一个无限列表(请注意,与例如Haskell列表不同,此流类型必须无限长,就像您在Haskell中编写的datatype stream a=SCons a(stream a)
一样,尽管Haskell样式的“潜在无限”列表也可能是直接的,参见AFP中的惰性列表)
例如,您可以定义其值来自给定集合的所有流的集合。您可以将其定义为streams A={s.sset s⊆ A}
,但在Isabelle中,它的定义如下:
coinductive_set streams :: "'a set ⇒ 'a stream set" for A :: "'a set"
where "⟦a ∈ A; s ∈ streams A⟧ ⟹ a ## s ∈ streams A"
另一个可能更简单的例子是流上的共导“for all element”谓词:
coinductive sall :: "('a ⇒ bool) ⇒ 'a stream ⇒ bool" for P :: "'a ⇒ bool" where
"P x ⟹ sall P xs ⟹ sall P (x ## xs)"
至于如何构造这样一个无限派生树的问题,也就是说,显示一个共归纳谓词包含某个值,你必须通过共归纳来实现这一点。例如,我们可以证明如果px
保持不变,那么sall P(sconst x)
保持不变,其中sconst x
只是无限重复的值x
:
lemma sconst_reduce: "sconst x = x ## sconst x"
by (subst siterate.code) simp_all
lemma sall_sconst: "P x ⟹ sall P (sconst x)"
proof (coinduction rule: sall.coinduct)
assume "P x"
thus "∃y ys. sconst x = y ## ys ∧ P y ∧ (ys = sconst x ∧ P x ∨ sall P ys)"
by (subst sconst_reduce) auto
qed
谢谢我熟悉共导入(至少从编程的角度来看)。但“与递归函数相比,归纳定义没有终止要求”意味着什么?例如,如果没有办法分歧,为什么要费心这么说?我想这是关于函数
和提供显式终止证明的区别,但我不确定。如果使用函数
而不提供终止证明,则得到的结果基本相同。所有规则(归纳、简化)都有一个类似的附加假设。例如,当你有一个带有循环的编程语言的语义时,你可以把它的语义写成一个归纳的(程序p
运行于状态s
终止于状态s'
),但是,由于可能存在非终止性,您无法使用函数
轻松地将其写下来。一种看待它的方法是,inclusive
为非终止“免费”提供结果false
,而如果您编写了一个做同样事情的函数,您必须自己识别这些情况并主动返回false
。谢谢。我熟悉共导入(至少从编程的角度来看)。但“与递归函数相比,归纳定义没有终止要求”意味着什么?例如,如果没有办法分歧,为什么要费心这么说?我想这是关于函数
和提供显式终止证明的区别,但我不确定。如果使用函数
而不提供终止证明,则得到的结果基本相同。所有规则(归纳、简化)都有一个类似的附加假设。例如,当你有一个带有循环的编程语言的语义时,你可以把它的语义写成一个归纳的(程序p
运行于状态s
终止于状态s'
),但是,由于可能存在非终止性,您无法使用函数
轻松地将其写下来。一种看待它的方式是