质因数分解的存在证明(教育)

Proof of existence of prime factorization (Educational)

我正在尝试写一个数字素因数分解存在的证明。它是为了教育,所以每个函数都被定义,我们尽量不使用 Isabelle 内置函数。这是我的代码:

(* addition*)
primrec suma::"nat ⇒ nat ⇒ nat" where
"suma 0 n = 0" |
"suma (Suc x) n = Suc (suma x n)"

primrec pred::"nat ⇒ nat" where
"pred 0 = 0" |
"pred (Suc x) = x"

(* substraction *)
primrec resta::"nat ⇒ nat ⇒ nat" where
"resta m 0 = m" |
"resta m (Suc x) = pred (resta m x)"

primrec mult::"nat ⇒ nat ⇒ nat" where
"mult 0 m = 0" |
"mult (Suc x) m = suma m (mult x m)"

lemma less_pred [simp]: "(x < y) ⟶ (pred x < y)"
proof (induct x)
case 0 then show ?case by simp
next
case (Suc x) then show ?case by simp
qed

lemma less_n_pred [simp]: "∀n::nat. (n ≠ 0) ⟶ (pred n < n)"
proof
fix n::nat show "n ≠ 0 ⟶ pred n < n" by (induct n) simp_all
qed

lemma less_resta [simp]: "(m > 0 ∧ n > 0) ⟶ (resta m n < m)"
proof (induct n)
case 0 then show ?case by simp_all
next
case (Suc x) then show ?case by force
qed

fun divi::"nat ⇒ nat ⇒ nat" where
"divi m n = (if n = 0 then
                undefined
            else
              if m = 0 
                then 0 
              else Suc (divi (resta m n) n))"

fun modulo::"nat ⇒ nat ⇒ nat" where
"modulo m n = (if n = 0 then
                undefined
            else
              if m < n 
                then m 
              else modulo (resta m n) n)"

definition divide::"nat ⇒ nat ⇒ bool" where
"divide m n = (modulo n m = 0)"

primrec numTo :: "nat ⇒ nat list" where
"numTo 0 = []" |
"numTo (Suc x) = (Suc x)#(numTo x)" 

primrec filter:: "'a list ⇒ ('a ⇒ bool) ⇒ 'a list" where
"filter [] p = []" |
"filter (x#xs) p = (if p x then x#(filter xs p) else filter xs p)"

definition divisores::"nat ⇒ nat list" where
"divisores n = (filter (numTo n) (λm. divide m n))"

definition is_prime::"nat ⇒ bool" where
"is_prime n = (length (divisores n) = 2)"

primrec all_prime::"nat list ⇒ bool" where
"all_prime [] = True" |
"all_prime (x#xs) = (is_prime x ∧ all_prime xs)"

primrec prod_list::"nat list ⇒ nat" where
"prod_list [] = 1" |
"prod_list (x#xs) = mult x (prod_list xs)"

lemma mult_num: "∀n::nat. n>1 ∧ ¬ is_prime n ⟶ (∃x y::nat. x < n ∧ y < n ∧ mult x y = n)"
proof
fix n::nat
(* This lemma might be useful? *)

theorem exists_prime_factor: "∀n::nat. (n > 1 ⟶ (∃xs::nat list. prod_list xs = n ∧ all_prime xs))"
proof
  fix n::nat
  show "(n > 1 ⟶ (∃xs::nat list. prod_list xs = n ∧ all_prime xs))"
  proof (induct n rule: less_induct)
 (* How can i prove this? *)

如何证明定理 exists_prime_factor: ∀n::nat. (n > 1 ⟶ (∃xs::nat list. prod_list xs = n ∧ all_prime xs))?

预先感谢您的帮助。

一个简短的回答是,您在开始定义 suma 时犯了一个基本错误。应该是这个(我猜的):

primrec suma::"nat ⇒ nat ⇒ nat" where
  "suma 0 n = n" |
  "suma (Suc x) n = Suc (suma x n)"

我的长篇回答是关于如何使用 valuenitpicksledgehammer 来查看您是否在正确的轨道上。

如果您无法证明某事,可以快速尝试 sledgehammer。如果 sledgehammer returns 什么都没有,那么尝试 nitpick 是个好主意。

如果nitpick找到一个反例,这很好地表明你的猜想是错误的,虽然没有gua运行tee。 Underspecified 由于 undefinedTHESOME 的定义可能导致这种情况,或者未定义 primrec 的所有情况。

使用 value 快速检查您的功能

使用 value 是我试图解决问题的最终结果,但没有完全理清您的所有逻辑。

value "mult 2 2" (* Suc (Suc 0) *)

从那里,它终于看到了显而易见的东西。

使用 value 查看您的函数是否正常工作,尽管这需要代码生成器可以简化 value 输入。

使用nitpick,免费

对于这样的事情,我想看看 sledgehammer 是否可以变魔术。

首先,最好去掉外部量词,像这样:

theorem exists_prime_factor: 
  "n > 1 --> (∃xs::nat list. prod_list xs = n ∧ all_prime xs)"
  apply(induct n, auto)
  sledgehammer
  oops

sledgehammer returns什么都没有时,则猜想不成立,或者需要你帮忙

Nitpick 给了我 n = 2 的反例,但它说它 可能是虚假的 ,而你在定义中使用了 undefined,这可以搞砸了 nitpick.

最终,我 运行 nitpick 在你的 lemma mult_num 上,它给了我 n = 4.

的反例

要尝试的一件事是证明你的定理的否定,这肯定证明你的定理是错误的。我试图证明这一点:

theorem
  "(x >= 4) | (y >= 4) | ~(mult x y = 4)"

最后,我说,"Hmmm, lets try something simple":

value "mult 2 2"

那是返回 2,这终于让我明白了。

未定义可能不是你想的那样

我专门在寻找会弄乱 nitpick 的东西,其中之一就是 undefined 的使用,例如您在此处的函数:

fun divi::"nat ⇒ nat ⇒ nat" where
  "divi m n = (if n = 0 then undefined
               else if m = 0 then 0 
               else Suc (divi (resta m n) n))"

这是 value 无法帮助您的示例。它不能简化这个:

value "divi 3 0" (* divi (Suc (Suc (Suc 0))) 0  *)

如果您遵循过去对 Isabelle/HOL 术语的讨论,一些专家更愿意将 undefined 称为 underspecified

这里,这个定理无法证明:

theorem "divi n 0 ~= (1::nat)"
  apply(induct n, auto)
oops

挑剔找反例:

theorem "divi n 0 ~= (1::nat)"
  nitpick (*
  Nitpick found a counterexample:

  Free variable:
    n = 1
*)
oops

但是,这是与此相同的反例:

theorem "divi n 0 = (1::nat)"
  nitpick
oops

为什么会这样?因为 undefined::nat 是一个 nat。如果你从未定义它,比如用公理,那么你不能说 nat 等于什么,尽管它必须等于某个唯一的 nat.

44个怎么样?

theorem "(divi n 0 = 44) <-> undefined = (44::nat)"
  by(simp)

看来n = 1023456.

的可能性无限小
theorem "(divi n 0 = 1023456) <-> undefined = (1023456::nat)"
  by(simp)

后果?可以开出无限多的笑话,微不足道的幽默。