Isabelle 一类非平凡列表函数的归纳
下面是一个数学练习(摘自-俄语): 共有100枚外观上无法区分的硬币,分为三种类型:金、银和铜(每种类型至少出现一次)。据了解,黄金各重3克,白银各重2克,铜各重1克。如何在两个没有重量的平板秤上确定重量不超过101磅的所有硬币的类型 (注:我猜这个练习是错误的,最多需要102磅。不过这并不重要) 解决办法如下:Isabelle 一类非平凡列表函数的归纳,isabelle,theorem-proving,Isabelle,Theorem Proving,下面是一个数学练习(摘自-俄语): 共有100枚外观上无法区分的硬币,分为三种类型:金、银和铜(每种类型至少出现一次)。据了解,黄金各重3克,白银各重2克,铜各重1克。如何在两个没有重量的平板秤上确定重量不超过101磅的所有硬币的类型 (注:我猜这个练习是错误的,最多需要102磅。不过这并不重要) 解决办法如下: 从硬币列表中逐个取出硬币,并将每枚硬币与前一枚硬币进行比较 如果硬币的重量相同,那么我们将它们分配给一组,并继续称重 如果我们发现一枚硬币cj比前一枚重,则转至步骤2 如果我们发现一
- 如果硬币的重量相同,那么我们将它们分配给一组,并继续称重
- 如果我们发现一枚硬币cj比前一枚重,则转至步骤2
- 如果我们发现一个比前一个轻的硬币ci,那么继续称量硬币,试图找到一个比ci重的硬币cj
- 如果我们找到了一个更轻的硬币,然后c0>ci>cj,我们知道这些硬币的重量:3>2>1。转至步骤3
- 如果我们发现一枚硬币ck比cj重,那么ci
- 如果我们发现ck比cj轻,那么比较ci和ck
- 如果ci
- 如果ci>ck,则ci、cj、ck的权重为2、3、1
- 如果ci=ck,则将ci+ck与cj进行比较
- 如果ci+ck
- 如果ci+ck>cj,则ci、cj、ck的权重为2、3、2
- 如果ci+ck=cj,则ci、cj、ck的权重为1、2、1
- 如果我们发现ck比cj轻,那么比较ci和ck
- 较轻的硬币是铜的
- 同样的硬币是银的
- 重一些的硬币是金子
lemma weigh_coins_ok:
"weigh_coins cs = Some ws ⟹
ws = map coin_weight cs"
proof (induct cs)
case Nil
then show ?case by simp
next
case (Cons c cs)
then show ?case
qed
我不能诱导过多的cs,因为我需要证明这一点
weigh_coins (c # cs) = Some ws ⟹ ∃ws. weigh_coins cs = Some ws
它站不住了。我可以为[CC,SC,GC]
确定权重,但不能为[SC,GC]
确定权重
另一种方法是在特殊情况下证明这些引理:
[CC, CC, ...] @ [SC, SC, ...] @ [GC, GC, ...] @ ...
[CC, CC, ...] @ [GC, GC, ...] @ [SC, SC, ...] @ ...
[SC, SC, ...] @ [GC, GC, ...] @ [CC, CC, ...] @ ...
...
然后证明案件清单是详尽无遗的
例如:
lemma weigh_coins_length:
"cs = [CC] @ replicate n CC @ [SC, GC] ⟹
weigh_coins cs = Some ws ⟹
length cs = length ws"
apply (induct n arbitrary: cs ws)
apply (auto simp: weigh_def gen_weights_def std_weigh_def)[1]
datatype strategy =
Return "coin list"
| Weigh "nat list" "nat list" "comp ⇒ strategy" ― ‹Weigh coins based on positions›
definition "select indexes coins ≡ map (nth coins) indexes"
fun runStrategy where
"runStrategy coins _ (Return r) = Some r"
| "runStrategy coins 0 _ = None"
| "runStrategy coins (Suc n) (Weigh xs ys cont) = (
if distinct xs ∧ distinct ys ∧ set xs ∩ set ys = {} then
runStrategy coins n (cont (weigh (select xs coins) (select ys coins)))
else None)"
lemma "∃strategy. ∀coins.
length coins = 100 ∧ (∀c. c ∈ set coins)
⟶ runStrategy coins 101 strategy = Some coins"
然而,我甚至不能证明这个引理
问题是:
n+2次的weight
函数引理,其中n
是硬币数,如何表述
确定重量
,查找重量
,称量硬币
对于每个递归函数,尝试在不使用递归的情况下表示输入和结果之间的关系(而使用量词)。为前面的函数证明的属性必须足够强,以证明后面的函数的属性。
此外,该属性不应修复任何参数。例如,最初总是使用j=0
调用find\u
,但该属性应适用于j
的所有值,以便在导入过程中使用
另外,还要尝试制定并证明您描述中的高级步骤:例如,显示此函数可以找到一枚银币或两枚铜币
关于问题2:
我会试图以一种不可能作弊的方式来陈述这个问题。例如:
lemma weigh_coins_length:
"cs = [CC] @ replicate n CC @ [SC, GC] ⟹
weigh_coins cs = Some ws ⟹
length cs = length ws"
apply (induct n arbitrary: cs ws)
apply (auto simp: weigh_def gen_weights_def std_weigh_def)[1]
datatype strategy =
Return "coin list"
| Weigh "nat list" "nat list" "comp ⇒ strategy" ― ‹Weigh coins based on positions›
definition "select indexes coins ≡ map (nth coins) indexes"
fun runStrategy where
"runStrategy coins _ (Return r) = Some r"
| "runStrategy coins 0 _ = None"
| "runStrategy coins (Suc n) (Weigh xs ys cont) = (
if distinct xs ∧ distinct ys ∧ set xs ∩ set ys = {} then
runStrategy coins n (cont (weigh (select xs coins) (select ys coins)))
else None)"
lemma "∃strategy. ∀coins.
length coins = 100 ∧ (∀c. c ∈ set coins)
⟶ runStrategy coins 101 strategy = Some coins"
在这里,runStrategy最多调用weight
101次,并且该策略无法了解有关硬币的任何信息,除了传递到weight
延续部分的比较结果