Isabelle 一类非平凡列表函数的归纳

Isabelle 一类非平凡列表函数的归纳,isabelle,theorem-proving,Isabelle,Theorem Proving,下面是一个数学练习(摘自-俄语): 共有100枚外观上无法区分的硬币,分为三种类型:金、银和铜(每种类型至少出现一次)。据了解,黄金各重3克,白银各重2克,铜各重1克。如何在两个没有重量的平板秤上确定重量不超过101磅的所有硬币的类型 (注:我猜这个练习是错误的,最多需要102磅。不过这并不重要) 解决办法如下: 从硬币列表中逐个取出硬币,并将每枚硬币与前一枚硬币进行比较 如果硬币的重量相同,那么我们将它们分配给一组,并继续称重 如果我们发现一枚硬币cj比前一枚重,则转至步骤2 如果我们发现一

下面是一个数学练习(摘自-俄语):

共有100枚外观上无法区分的硬币,分为三种类型:金、银和铜(每种类型至少出现一次)。据了解,黄金各重3克,白银各重2克,铜各重1克。如何在两个没有重量的平板秤上确定重量不超过101磅的所有硬币的类型

(注:我猜这个练习是错误的,最多需要102磅。不过这并不重要)

解决办法如下:

  • 从硬币列表中逐个取出硬币,并将每枚硬币与前一枚硬币进行比较
    • 如果硬币的重量相同,那么我们将它们分配给一组,并继续称重
    • 如果我们发现一枚硬币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
  • 将其余硬币与银币(或两枚铜币)进行比较
    • 较轻的硬币是铜的
    • 同样的硬币是银的
    • 重一些的硬币是金子
  • 如果在步骤1中,我们首先发现了较轻的硬币,而不是较重的硬币,那么我们需要将第一枚较重的硬币与一枚银币进行比较,以确定它们的重量(可能是第102次称重,具体取决于一套硬币)
  • 下面是一个硬币清单的示例:

    c0 ci cj ck 3 3 2 2 2 3 3 1 1 2 1 3 |_| |___| |_| i j k 但是,我不知道如何在一般情况下证明:

    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
    延续部分的比较结果