我能得到一个简单的解释为什么这个证明努力失败吗?在我的研究中,我试图识别生成的整数列表中的简单模式。下面的生成器生成一个交替的0和1s列表。我想证明偶数索引处的项目是0。
val evenb : nat -> bool
let rec evenb n =
match n with
| 0 -> true
| 1 -> false
| n -> evenb (n - 2)
val nth_item : ls: list nat {length ls > 0} -> n: nat {n < length ls} -> nat
let rec nth_item ls n =
match ls with
| [h] -> h
| h :: t -> if n = 0 then h else nth_item t (n - 1)
val gen_01 : lng: nat {lng >= 2 && evenb lng} -> ls: list nat {length ls = lng}
let rec gen_01 lng =
match lng with
| 2 -> [0; 1]
| _ -> [0; 1] @ gen_01 (lng - 2)
let rec lemma_01 (lng: nat {lng >= 2 && evenb lng}) :
Lemma (forall (n: nat {n <= lng - 2 && evenb n}) . (nth_item (gen_01 lng) n) = 0) =
match lng with
| 2 -> ()
| _ -> lemma_01 (lng - 2)FStar返回“无法证明后条件”。我很感谢你对此方法的任何帮助。
发布于 2020-05-22 06:01:00
F*还应该报告一个次要错误位置,指向后置条件中无法证明的连接符--在这种情况下,它只是nth_item (gen_01 lng) n = 0目标。
诊断这种情况的一种方法是一次考虑证据的一个分支。例如,如果在第二个分支中添加一个admit();,那么您将看到第一个分支很容易证明。所以,问题出在归纳案例上。你没有足够强的归纳假设来证明你想要的性质。
这里有一个证据..。可能还有很多其他的。
首先,我证明了这一点:
let rec access_2n (l:nat{l >= 2 && evenb l}) (n:nat{2 * n < l})
: Lemma (ensures nth_item (gen_01 l) (2 * n) = 0)
= match n with
| 0 -> ()
| _ -> access_2n (l - 2) (n - 1)注意对l, n的归纳,这样长度和访问索引就一起减少了。
这几乎是你想要证明的财产,说明略有不同。为了把它按你想要的方式按摩,我做了这个:
首先,一个算术解释evenb的引理:
编辑:我添加了一个open FStar.Mul,将*符号带入乘法的范围。
open FStar.Mul
let rec evenb_is_even (n:nat{evenb n})
: Lemma (2 * (n / 2) = n)
= match n with
| 0 -> ()
| _ -> evenb_is_even (n - 2)然后证明一些非常类似的引理,但是对于一个显式的n。
let lemma_01_aux (lng: nat {lng >= 2 && evenb lng}) (n:nat{n <= lng - 2 && evenb n})
: Lemma (nth_item (gen_01 lng) n = 0)
= access_2n lng (n / 2); evenb_is_even n最后,使用一个将引理转化为量化后条件的库来对n进行普遍量化。
let lemma_01 (lng: nat {lng >= 2 && evenb lng})
: Lemma (forall (n: nat {n <= lng - 2 && evenb n}) . (nth_item (gen_01 lng) n) = 0)
= FStar.Classical.forall_intro_2 lemma_01_auxhttps://stackoverflow.com/questions/61938833
复制相似问题