当函数返回1时,函数返回0,从而消除了parantheses

时间:2017-02-18 19:42:57

标签: isabelle

考虑以下Isabelle的最小工作示例,我在其中定义了两个不同的函数func1和func2,它们应该模拟Eulers Totient函数。
 奇怪的是,这种不明确的定义是错误的,只是通过引入∈ℕ导致正确但无法解释的定义,只是略微改变了定义。
 (我在代码中穿插的确切问题,因为这可能使我所指的更清楚。)

 theory T
    imports
    Complex_Main
    "~~/src/HOL/Number_Theory/Number_Theory"
    begin

(* Part I*)

definition func1 :: "nat ⇒ nat"
  where "func1 n = card {m.  m≤n ∧ coprime n m}" 

lemma func1_equals : "func1 1 = 2" (* This equation is obviously false...*)
  by (auto simp: func1_def)

    (* Question 1: Why is this proof correct according to Isabelle? *)

(* Part II*)    

definition func2  :: "nat ⇒ nat"
  where "func2 n = card {m. m∈ℕ ∧  m≤n ∧(coprime n m)}" 
(* Slightly changed definition by incorporating ∈ℕ*) 

lemma func2_equals : "func2 1 = 1"
  apply (auto simp: func2_def)
 (* Unproved subgoal <<card {m ∈ ℕ. m ≤ Suc 0} = Suc >> looks more promising *)
    oops

    (* Question 2: Which proof method should I use to prove the last lemma? 
Interestingly, sledgehammer runs out of time...*)
    Question 3: Analogous to Q2 but for func2 4 = 2 ? The difference now is that
the preliminary <<apply (auto simp: func2_def)>> rewrites to a slightly 
different subgoal. *)

end

是否有更优雅的方法来定义Euler totient函数?

1 个答案:

答案 0 :(得分:0)

您的两个定义是等效的:

lemma "func1 n = func2 n"
  by (simp add: func1_def func2_def Nats_def)

你得到2而不是1的原因是一个微妙的,是你在形式化数学定义时遇到的问题的一个完美例子:Isabelle中的自然数包含0,所以如果你评价{{1}你查看不大于1 - 0和1的数字 - 并检查它们中的哪一个是互质的1.自func1 1所有gcd 0 n = n以来,你发现n0与1互为,因此结果为2。

Euler的totient函数只计算小于1整数,它们与n是互质的,所以你的定义应该更像这样:

n

如果要生成代码,可以使用以下代码方程式:

definition totient :: "nat ⇒ nat" where
  "totient n = card {k ∈ {0<..n}. coprime k n}"

然后你可以这样做:

lemma totient_code [code]: "totient n = card (Set.filter (λk. coprime k n) {0<..n})"
  by (simp add: totient_def Set.filter_def)

请注意,虽然我认为在Isabelle中使用的函数非常好,但我不确定这对于初学者来说是最好的思考,因为涉及集合的基数和这些事情的证据可能会涉及到一些。了解系统的一个好方法是Nipkow和Klein的免费bok Concrete Semantics。该书中的示例和练习更多的是计算机科学/编程导向,但材料更适合初学者,更适合交互式定理证明,因为证明往往不那么混乱,需要较少的系统经验。

顺便说一句,value "map (int ∘ totient) [1..<10]" (* Output: "[1, 1, 2, 2, 4, 2, 6, 4, 6]" :: "int list" *) 无法证明sledgehammer的原因是因为结果是func2 1 = 1而不是2。您可以通过执行1或将UNIV添加到simp集来展开ℕ的定义(对于自然数,基本上只是unfolding Nats_def)来证明与Nats_def