假设我有一个二元运算符f :: "sT => sT => sT"
。我想定义f
,以便它为Klein四组实现一个4x4乘法表,如Wiki所示:
http://en.wikipedia.org/wiki/Klein_four-group
在这里,我所要做的就是创建一个包含16个条目的表。首先,我定义了四个这样的常量:
consts
k_1::sT
k_a::sT
k_b::sT
k_ab::sT
然后我定义我的函数来实现表中的16个条目:
k_1 * k_1 = k_1
k_1 * k_a = k_a
...
k_ab * k_ab = k_1
我不知道如何在Isar中进行任何类似于常规的编程,我在Isabelle用户列表中看到过,据说(某些)类似编程的结构在语言中被故意不再强调
前几天,我试图创建一个简单的,有人工作的函数,在源文件中找到if, then, else
的使用后,我找不到isar-ref.pdf中对这些命令的引用
在查看教程时,我看到definition
以直接的方式定义函数,除此之外,我只看到有关递归和归纳函数的信息,这需要datatype
和我的情况比这更简单。
如果留给我自己的设备,我想我会尝试为上面显示的4个常量定义一个datatype
,然后创建一些转换函数,这样我最终得到一个二元运算符f :: sT => sT => sT
。我尝试使用fun
时略微搞砸了一下,但事实并非如此简单。
fun
和inductive
更新:我在这里添加一些材料以回应评论,告诉我Programming and Proving是我找到答案的地方。看来我可能会误入理想的Stackoverflow格式。
我做了一些基本的实验,主要是fun
,还有inductive
。我相当快地放弃了归纳法。这是我从简单示例中得到的错误类型:
consts
k1::sT
inductive k4gI :: "sT => sT => sT" where
"k4gI k1 k1 = k1"
--"OUTPUT ERROR:"
--{*Proofs for inductive predicate(s) "k4gI"
Ill-formed introduction rule ""
((k4gI k1 k1) = k1)
Conclusion of introduction rule must be an inductive predicate
*}
我的乘法表不是归纳的,所以我没有看到inductive
是我应该花时间追逐的。
“模式匹配”似乎是一个关键的想法,所以我尝试了fun
。这里有一些非常混乱的代码试图使用只有标准函数类型的fun
:
consts
k1::sT
fun k4gF :: "sT => sT => sT" where
"k4gF k1 k1 = k1"
--"OUTPUT ERROR:"
--"Malformed definition:
Non-constructor pattern not allowed in sequential mode.
((k4gF k1 k1) = k1)"
我遇到了这种错误,我在Programming and Proving中读过这样的内容:
“通过基于数据类型构造函数的模式匹配,使用 fun 定义递归函数。
这一切都给新手一个fun
需要datatype
的印象。至于它的大哥function
,我不知道。
在这里,我只需要一个具有16个基本案例的递归函数,这将定义我的乘法表。
function
吗?在编辑此问题时,我记得过去的function
,而function
正在工作:
consts
k1::sT
function k4gF :: "sT => sT => sT" where
"k4gF k1 k1 = k1"
try
try的输出告诉我它可以证明(更新:我认为它实际上告诉我只有一个证明步骤可以证明。):
Trying "solve_direct", "quickcheck", "try0", "sledgehammer", and "nitpick"...
Timestamp: 00:47:27.
solve_direct: (((k1, k1) = (k1, k1)) ⟹ (k1 = k1)) can be solved directly with
HOL.arg_cong: ((?x = ?y) ⟹ ((?f ?x) = (?f ?y))) [name "HOL.arg_cong", kind "lemma"]
HOL.refl: (?t = ?t) [name "HOL.refl"]
MFZ.HOL⇣'eq⇣'is⇣'reflexive: (?r = ?r) [name "MFZ.HOL⇣'eq⇣'is⇣'reflexive", kind "theorem"]
MFZ.HOL_eq_is_reflexive: (?r = ?r) [name "MFZ.HOL_eq_is_reflexive", kind "lemma"]
Product_Type.Pair_inject:
(⟦((?a, ?b) = (?a', ?b')); (⟦(?a = ?a'); (?b = ?b')⟧ ⟹ ?R)⟧ ⟹ ?R)
[name "Product_Type.Pair_inject", kind "lemma"]
我不知道这意味着什么。我只知道function
因为试图证明不一致。我只知道它不会抱怨多少。如果像我这样使用function
是我如何定义乘法表,那么我很高兴。
尽管如此,作为一个议论类型,我没有在教程中了解function
。几个月前我在一本参考手册中了解到它,我仍然不太了解如何使用它。
我有一个function
我用auto
证明了,但幸运的是,这个功能可能并不好。这增加了function
的神秘感。 function
中有fun
的信息,比较function
和fun
。
但是,我没有看到function
或nat
的一个示例,它不使用递归数据类型,例如'a list
或{{1}}。也许我看起来不够努力。
很抱歉这是一个冗长的问题,但这并不是一个直接的问题,但是没有Isabelle的教程可以直接从A到B。
答案 0 :(得分:0)
下面,我不会坚持只回答问题"格式,但我回答了我自己的问题,所以我说的所有内容都会引起原始海报的兴趣。
这应该是我的最后一次更新。为了满足"简单的方法",有助于能够进行比较以查看低技术"方式可能是最好的方式。
我终于放弃尝试让我的主要类型与新类型一起工作,我只是在这样的datatype
中创建了一个Klein四组,结果的证明就在最后:< / p>
datatype AT4k = e4kt | a4kt | b4kt | c4kt
fun AOP4k :: "AT4k => AT4k => AT4k" where
"AOP4k e4kt y = y"
| "AOP4k x e4kt = x"
| "AOP4k a4kt a4kt = e4kt"
| "AOP4k a4kt b4kt = c4kt"
| "AOP4k a4kt c4kt = b4kt"
| "AOP4k b4kt a4kt = c4kt"
| "AOP4k b4kt b4kt = e4kt"
| "AOP4k b4kt c4kt = a4kt"
| "AOP4k c4kt a4kt = b4kt"
| "AOP4k c4kt b4kt = a4kt"
| "AOP4k c4kt c4kt = e4kt"
notation
AOP4k ("AOP4k") and
AOP4k (infixl "*" 70)
theorem k4o_assoc2:
"(x * y) * z = x * (y * z)"
by(smt AOP4k.simps(1) AOP4k.simps(10) AOP4k.simps(11) AOP4k.simps(12)
AOP4k.simps(13) AOP4k.simps(2) AOP4k.simps(3) AOP4k.simps(4) AOP4k.simps(5)
AOP4k.simps(6) AOP4k.simps(7) AOP4k.simps(8) AOP4k.simps(9) AT4k.exhaust)
结果是我现在满足于我的if-then-else
乘法函数。为什么?因为if-then-else
函数非常有助于simp
魔法。这种模式匹配本身并不起任何作用,更不用说我仍然需要弄清楚它的强制子类型部分。
这里是4x4乘法表的if-then-else
函数:
definition AO4k :: "sT => sT => sT" where
"AO4k x y =
(if x = e4k then y else
(if y = e4k then x else
(if x = y then e4k else
(if x = a4k y = c4k then b4k else
(if x = b4k y = c4k then a4k else
(if x = c4k y = a4k then b4k else
(if x = c4k y = b4k then a4k else
c4k)))))))"
由于一个嵌套的if-then-else
语句,当我运行auto
时,它会产生64个目标。我制作了16个simp
规则,其中一个规则适用于乘法表中的每个值,因此当我使用所有其他simp
规则运行auto时,auto
证明大约需要90毫秒。
像乘法表这样的小东西对于测试事物很重要,但是如果它会减慢我的THY速度,它会变得很有用,因为它会在一个需要永久消耗的大循环中完成。
(更新:上面我的问题属于&#34;我如何在Isabelle中进行基本编程,就像使用其他编程语言一样?&#34;在这里,我超越了一些具体问题,但我尝试保持我对一个初学者的评论,这个初学者试图在文档达到中级水平时学习Isabelle,至少在我看来是这样。
具体到我的问题是,我需要一个case
语句,这是许多编程语言的一个非常基本的特性。
今天在寻找case
声明时,我认为在文档中再进行一次搜索后,我会点击金币,这次是Isabelle - A Proof Assistant for
Higher-Order Logic。
在第5页上,它记录了case
语句,但在第18页上,它澄清了它仅对datatype
有用,我似乎确认了这样的错误:
definition k4oC :: "kT => kT => kT" (infixl "**" 70) where
"k4oC x y = (case x y of k1 k1 => k1)"
--{*Error in case expression:
Not a datatype constructor: "i130429a.k1"
In clause
((k1 k1) ⇒ k1)*}
这是一个例子,无论是专家还是初学者,都需要有一个教程来运行Isabelle的基本编程功能。
如果你说,&#34;有教程可以做到这一点。&#34;我说,&#34;不,没有,不在我看来&#34;。
这些教程强调了Isabelle的重要而复杂的功能,将其与人群分开。
该评论,但它的评论意味着与问题相关,&#34;我如何学习伊莎贝尔?&#34;,以及我上面的原始问题与之相关。< / p>
如果你不是剑桥大学,TUM或者NICTA的博士研究生,你学习伊莎贝尔的方式是你在6到12个月或更长时间内挣扎。如果在此期间您不放弃,您可以达到允许您欣赏中级指令的水平。经验可能会有所不同。
对于我来说,当我抽出时间通过它们时,3本书将带我进入下一级证明,让我离开auto
和metis
,
如果有人说,&#34;您通过参与冗长的评论和意见来滥用Stackoverflow答案格式。&#34;
我说,&#34;嗯,我要求在Isabelle做一些基本编程的好方法,在那里我希望有一些比一个大if-then-else
语句更复杂的东西。没有人提供任何接近我要求的东西。事实上,我是谁提供了模式匹配功能,我需要做的事情甚至没有接近记录。模式匹配是一个简单的概念,但由于递归函数的证明要求,不一定在Isabelle中。 (如果有一种简单的方法来替换下面的if-then-else
功能,甚至是case
声明方式,我当然想知道。)
话虽如此,我倾向于采取一些自由,而且目前这个页面只有36个观看次数,其中至少有10个来自我的浏览器。
Isabelle / HOL是一种强大的语言。我没有抱怨。它只是听起来像。)
只要知道某些事情是真是假就可以算很多,在这种情况下被告知function
可以使用非归纳类型。但是,我最终如何使用function
下面的内容并不是我在任何一篇Isabelle文档中看到过的结果,而且我需要这个关于强制性子类型的前SO问题:
What is an Isabelle/HOL subtype? What Isar commands produce subtypes?
我最终有两种方法可以完成乘法表的2x2部分。我将此链接到理论:ASCII friendly A_i130429a.thy,jEdit friendly i130429a.thy,PDF和folder。
这两种方式是:
simp
友好if-then-else
方式。定义需要0毫秒,证明需要155毫秒。function
的模式匹配方式。在这里,我可以在公共场合大声思考这种做事方式,但我不会。我知道我会使用我在这里学到的东西,但它绝对不是一个简单的乘法表函数的优雅解决方案,并且很明显一个人不得不尽一切努力创建一个使用模式匹配的基本功能。当然,也许我不必做所有这些。定义需要391ms,证明需要317ms。至于必须使用if-then-else
,Isabelle / HOL在基本编程语句方面功能不丰富,或者这些基本语句没有记录。 if-then-else
语句甚至不在Isar Reference Manual索引中。我认为,&#34;如果没有记录,也许有一个很好的,未记录的case
语句,如Haskell has&#34;。不过,我任何时候都会把伊莎贝尔带到哈斯克尔身上。
下面,我将解释A_i130429a.thy的不同部分。这有点琐碎,但并不完全,因为我还没有看到一个例子来教我如何做到这一点。
我从一个类型和四个常量开始,这些常量仍未定义。
typedecl kT
consts
k1::kT
ka::kT
kb::kT
kab::kT
值得注意的是,常量仍未定义。我遗漏了很多未定义的东西,这也是为什么我在文档和资源中找到好的例子以便用作我自己的模板的原因之一。
我做了一个测试,试图在非归纳数据类型上智能地使用function
,但它不起作用。使用我的if-then-else
函数,在我发现我没有限制我的函数域之后,我看到这个函数的问题也在于域。每个function k4f0
x
都希望k1
为ka
或x
,这显然不是真的。
function k4f0 :: "kT => kT" where
"k4f0 k1 = k1"
| "k4f0 ka = ka"
apply(auto)
apply(atomize_elim)
--"goal (1 subgoal):
1. (!! (x::sT). ((x = k1) | (x = ka)))"
我放弃并用if-then-else
定义了一个丑陋的函数。
definition k4o :: "kT => kT => kT" (infixl "**" 70) where
"k4o x y =
(if x = k1 & y = k1 then k1 else
(if x = k1 & y = ka then ka else
(if x = ka & y = k1 then ka else
(if x = ka & y = ka then k1 else (k1)
))))"
declare k4o_def [simp add]
困难的部分试图证明我的功能k4o
的相关性。但这只是因为我没有限制域名。我在声明中加入了一个含义,auto
魔法开始了,fastforce
魔法也存在,并且更快,所以我使用它。
abbreviation k4g :: "kT set" where
"k4g == {k1, ka}"
theorem
"(x \<in> k4g & y \<in> k4g & z \<in> k4g) --> (x ** y) ** z = x ** (y ** z)"
by(fastforce)(*155ms*)
魔术让我开心,然后我有动力尝试用function
和模式匹配来完成它。由于最近有关强制性子类型的SO答案,与上述相关,我想出了如何使用typedef
修复域名。我不认为这是一个完美的解决方案,但我确实学到了一些东西。
typedef kTD = "{x::kT. x = k1 | x = ka}"
by(auto)
declare [[coercion_enabled]]
declare [[coercion Abs_kTD]]
function k4f :: "kTD => kTD => kT" (infixl "***" 70) where
"k4f k1 k1 = k1"
| "k4f k1 ka = ka"
| "k4f ka k1 = ka"
| "k4f ka ka = k1"
by((auto),(*391ms*)
(atomize_elim),
(metis (lifting, full_types) Abs_kTD_cases mem_Collect_eq),
(metis (lifting, full_types) Rep_kTD_cases Rep_kTD_inverse mem_Collect_eq),
(metis (lifting, full_types) Rep_kTD_cases Rep_kTD_inverse mem_Collect_eq),
(metis (lifting, full_types) Rep_kTD_cases Rep_kTD_inverse mem_Collect_eq),
(metis (lifting, full_types) Rep_kTD_cases Rep_kTD_inverse mem_Collect_eq))
termination
by(metis "termination" wf_measure)
theorem
"(x *** y) *** z = x *** (y *** z)"
by(smt
Abs_kTD_cases
k4f.simps(1)
k4f.simps(2)
k4f.simps(3)
k4f.simps(4)
mem_Collect_eq)(*317ms*)
答案 1 :(得分:0)
定义“有限”函数的或多或少方便的语法是函数更新语法:对于函数f
,f(x := y)
表示函数%z. if z = x then y else f z
。如果要更新多个值,请用逗号分隔:f(x1 := y1, x2 := y2)
。
因此,例如0
,1
和未定义的其他函数可以写成:
undefined (0 := undefined(0 := 0, 1 := 1),
1 := undefined(0 := 1, 1 := 2))
定义有限函数的另一种可能性是从对列表中生成它;例如map_of
。使用f xs y z = the (map_of xs (y,z))
,上述函数可以写为
f [((0,0),0), ((0,1),1), ((1,0),1), ((1,1),1)]
(实际上,它的功能并不完全相同,因为它在定义的域之外可能会有不同的行为)。