在 Isabelle 中定义常量之间的函数

Defining functions between constants in Isabelle

我是一名刚开始习惯伊莎贝尔的数学家,一些本应非常简单的事情结果却令人沮丧。如何定义两个常量之间的函数?比如,函数 f: {1,2,3} \to {1,2,4} 映射 1 到 1、2 到 4 和 3 到 2?

我想我成功地将集合定义为常量 t1 和 t2,但(我猜是因为它们不是数据类型)我不能尝试

    definition f ::"t1 => t2" where 
"f 1 = 1" |
"f 2 = 4" | 
"f 3 = 2"

我相信这个困难背后一定存在根本性的误解,所以我感谢任何指导。

您的问题涉及多个方面。

首先,要使某些东西快速运行,请使用 fun 关键字而不是 definition,如下所示:

fun test :: "nat ⇒ nat" where
  "test (Suc 0) = 1" |
  "test (Suc (Suc 0)) = 4" |
  "test (Suc (Suc (Suc 0))) = 2" |
  "test _ = undefined"

您不能使用 definition 关键字直接在定义的头部对任何参数进行模式匹配,而可以使用 fun。另请注意,我已将重载的数字文字(1、2、3 等)替换为模式匹配中 nat 数据类型(0Suc)的构造函数。

另一种方法是坚持使用 definition,但使用 case 语句将函数参数的案例分析推入定义主体,如下所示:

definition test2 :: "nat ⇒ nat" where
  "test2 x ≡
     case x of
       (Suc 0) ⇒ 1
     | (Suc (Suc 0)) ⇒ 4
     | (Suc (Suc (Suc 0))) ⇒ 2
     | _ ⇒ undefined"

请注意像 test2 这样的定义在默认情况下不会被简化器展开,如果您想扩展 [=] 的出现,您需要手动将定理 test2_def 添加到简化器的简化集22=] 在证明中。

您还可以使用 typedef 定义与您的两个三元素集相对应的新类型(您不能直接将集合用作类型),但我个人会坚持使用 nat.

编辑:要使用 typedef,请执行以下操作:

typedef t1 = "{x::nat. x = 1 ∨ x = 2 ∨ x = 3}"
  by auto

definition test :: "t1 ⇒ t1" where
  "test x ≡
     case (Rep_t1 x) of
     | Suc 0 ⇒ Abs_t1 1
     | Suc (Suc 0) ⇒ Abs_t1 4
     | Suc (Suc (Suc 0)) ⇒ Abs_t1 2"

不过,我自己并没有真正使用过 typedef,因此这可能不是使用它的最佳方式,其他人可能会建议一些其他方式。 typedef 所做的是通过为新类型识别一组非空居民,从现有类型中开辟出一个新类型。此处由 auto 结束的证明义务只是为了证明新类型的定义集确实是非空的,在这种情况下,我将自然数的三元素集分割成一个新类型,称为 t1,因此证明相当简单。创建了两个新常量,Abs_t1Rep_t1,它们允许您在自然类型和新类型之间来回移动。如果你在 typedef 命令后加上 print_theorems,你会看到 Isabelle 自动为你生成的关于 t1 的几个新定理。