我是定理证明和伊莎贝尔的新手。我试图在Isabelle中证明一个关于列表的简单(?)定理。
这是理论:
theory Scratch
imports
Main
Option
String
begin
fun list_difference :: "string list => string list => nat"
where
"list_difference [] [] = 0"
| "list_difference [] x = length x"
| "list_difference x [] = length x"
| "list_difference (x#d1) (y#d2) = (if (x=y) then list_difference d1 d2 else (1 + list_difference d1 d2))"
fun modify :: "string list ⇒ nat ⇒ string list"
where
"modify list n = list[n:=''somethingnew'']"
这些是支持性的引理
lemma diff_zero [simp]:
shows "list_difference somelist somelist = 0"
apply(induct_tac somelist, auto)
done
lemma sub1 [simp]:
shows "modify [] 0 = []"
apply(auto)
done
lemma diff_zero_basecase [simp]:
shows "list_difference somelist (modify somelist 0) <= 1"
apply(induct_tac somelist, auto)
done
这是我试图证明的原始定理
(*Description : modify will change only one or zero elements.. so diff should be <= 1*) <br>
lemma modification_lemma [simp]:
shows "list_difference somelist (modify somelist index) ≤ 1"
apply(induct_tac somelist, auto)
apply(cases index, auto)
oops
我如何着手证明这个定理?
我的另一个问题是如何在试图证明定理时从这些情况出发?我尝试过遵循Isabelle教程,但我无法得到关于此的一般建议。
答案 0 :(得分:0)
我给你一个证明,并解释我用来获得结果的一些基本技巧,但却以一种相当无意义的方式。其他人可能希望提供一个解释,让您更好地理解主题:涉及nat
和list
的归纳。
我缩短了一些标识符,我将整个理论放在下面。公式中基本上有两个需要证明的自由变量ls
和idx
。
所以,为了证明目标,在尝试的时候,我做了很多我接下来要展示的内容,或者是一些变体,cases
可能induct
:
(*MINDLESS_TECHNIQUE_1*)
apply(induct ls, auto)
apply(induct idx, auto)
在某个时刻,auto
需要花费很长时间,这意味着由于您拥有simp
规则,这可能会导致循环不良。
我删除了simp
规则并仅在需要的地方插入它们,这样就摆脱了auto
循环。
这是第一个进步点,它让我进入MINDLESS_TECHNIQUE_2,将证明目标分解为lemma
,与MINDLESS_TECHNIQUE_1一起使用,以及Sledgehammer。
此时,对于modification_lemma
,在使用上述apply
后,我有3个证明目标,我使用Sledgehammer来证明其中的两个。然后我打破了第3个证明目标,如下所示,这可以通过by(induct ls, auto)
轻松证明。
更新:使用亚历山大的提示与上面的爆发引理达到相同的证明目标,我在下面的源代码中添加了一个证明,我打开了两个绑定变量。它仍然是一个丑陋的解决方案,所以也许有一种比结束变量更好的方法。
像我一样使用auto
或simp_all
,我无法盲目地使用by(induct ls, auto)
获得最终结果的原因是因为变量idx
和ls
受到所有元!!
的约束。如果没有自动工具可以进行校对工作(我猜),它们需要打开,这会使事情变得非常混乱。
theory c2
imports Main Option String
begin
fun list_diff :: "string list => string list => nat" where
"list_diff [] [] = 0"
|"list_diff [] x = length x"
|"list_diff x [] = length x"
|"list_diff (x#d1) (y#d2) =
(if (x=y) then list_diff d1 d2 else (1 + list_diff d1 d2))"
fun modify :: "string list => nat => string list" where
"modify ls n = ls[n := ''abc'']"
lemma diff_zero:
"list_diff ls ls = 0"
by(induct_tac ls, auto)
lemma sub1:
"modify [] 0 = []"
by(auto)
lemma diff_zero_basecase:
"list_diff ls (modify ls 0) <= 1"
by(induct_tac ls, auto simp add: diff_zero)
(*****************************************************************************)
lemma the_mindless_result_of_eliminating_simp_rules_and_breaking_out_goals:
"(!!a ls. list_diff ls (ls[idx := ''abc'']) <= Suc 0 ==>
list_diff (a # ls)
(case idx of 0 => ''abc'' # ls | Suc j => a # ls[j := ''abc'']) <= Suc 0)
==> list_diff ls (ls[Suc idx := ''abc'']) <= Suc 0 ==>
list_diff ls (ls[idx := ''abc'']) <= Suc 0"
by(induct ls, auto)
lemma modification_lemma:
"list_diff ls (modify ls idx) <= 1"
apply(induct ls, auto)
apply(induct idx, auto)
apply(metis diff_zero le0)
apply(metis diff_zero) (*The goal I broke out to the above lemma.*)
by (metis the_mindless_result_of_eliminating_simp_rules_and_breaking_out_goals)
(*****************************************************************************)
(*Update: After the third 'apply', I can't mindlessly do 'by(induct ls, auto)',
because variables 'ls' and 'idx' are bound by '!!. If I use 'auto' like I
did, and I don't want to break out the proof goal, I need to unwrap the
variables 'idx' and 'ls, as shown below.*)
lemma unwrapping_variables:
"list_diff ls (modify ls idx) <= 1"
apply(induct ls, simp_all)
apply(induct idx, simp_all)
apply(simp_all add: diff_zero)
proof-
fix idx
show "!!ls. ((!!a ls. list_diff ls (ls[idx := ''abc'']) <= Suc 0 ==>
list_diff (a # ls)
(case idx of 0 => ''abc'' # ls | Suc j => a # ls[j := ''abc'']) <= Suc 0)
==> list_diff ls (ls[Suc idx := ''abc'']) <= Suc 0 ==>
list_diff ls (ls[idx := ''abc'']) <= Suc 0)"
proof-
fix ls
show "(!!a ls. list_diff ls (ls[idx := ''abc'']) <= Suc 0 ==>
list_diff (a # ls)
(case idx of 0 => ''abc'' # ls | Suc j => a # ls[j := ''abc'']) <= Suc 0)
==> list_diff ls (ls[Suc idx := ''abc'']) <= Suc 0 ==>
list_diff ls (ls[idx := ''abc'']) <= Suc 0"
by(induct ls, auto)
qed
qed
thm unwrapping_variables
end