Raf*_*tro 5 recursion coq totality
为了通过一个良好的关系理解递归,我决定实现扩展的欧几里得算法。
扩展的欧几里得算法适用于整数,因此我需要一些关于整数的良好依据。我尝试使用中的关系Zwf,但没有任何效果(我需要查看更多示例)。我认为使用该函数映射Z起来会更容易,然后将其用作关系即可。我们的朋友来帮助我。所以这是我做的:natZ.abs_natNat.ltwf_inverse_image
Require Import ZArith Coq.ZArith.Znumtheory.
Require Import Wellfounded.
Definition fabs := (fun x => Z.abs_nat (Z.abs x)). (* (Z.abs x) is a involutive nice guy to help me in the future *)
Definition myR (x y : Z) := (fabs x < fabs y)%nat.
Definition lt_wf_on_Z := (wf_inverse_image Z nat lt fabs) lt_wf.
Run Code Online (Sandbox Code Playgroud)
扩展的欧几里得算法如下所示:
Definition euclids_type (a : Z) := forall b : Z, Z * Z * Z.
Definition euclids_rec : (forall x : Z, (forall y : Z,(myR y x) -> euclids_type y) -> euclids_type x).
unfold myR, fabs.
refine (fun a rec b => if (Z_eq_dec a 0) then (b, 0, 1)
else let '(g, s, t) := rec (b mod a ) _ a
in (g, t - (b / a) * s, s)
).
apply Zabs_nat_lt. split. apply Z.abs_nonneg. apply Z.mod_bound_abs. assumption.
Defined.
Definition euclids := Fix lt_wf_on_Z _ euclids_rec.
Run Code Online (Sandbox Code Playgroud)
现在让我们看看它是否有效:
Compute (euclids 240 46). (* Computation takes a long time and results in a huge term *)
Run Code Online (Sandbox Code Playgroud)
我知道如果某些定义不透明,可能会发生这种情况,但是我的所有定义都以结尾Defined.。Okey,其他东西是不透明的,但是呢?如果是库定义,那么我认为在我的代码中重新定义它不会很酷。
我决定Program Fixpoint尝试一下,因为我从未使用过。看到我可以复制并粘贴程序,我感到很惊讶。
Program Fixpoint euclids' (a b: Z) {measure (Z.abs_nat (Z.abs a))} : Z * Z * Z :=
if Z.eq_dec a 0 then (b, 0, 1)
else let '(g, s, t) := euclids' (b mod a) a in
(g, t - (b / a) * s, s).
Next Obligation.
apply Zabs_nat_lt. split. apply Z.abs_nonneg. apply Z.mod_bound_abs. assumption.
Defined.
Run Code Online (Sandbox Code Playgroud)
甚至更惊讶地看到它运行良好:
Compute (euclids' 240 46). (* fast computation gives me (2, -9, 47): Z * Z * Z *)
Run Code Online (Sandbox Code Playgroud)
什么是不透明的euclids,是不是在euclids'?以及如何euclids工作?
好吧,还有一些不透明的东西,但是什么呢?
wf_inverse_image是不透明的,它所依赖的引理也是如此:Acc_lemma和Acc_inverse_image。如果你把这三个设置为透明euclids将会计算。
良好发现性的证据基本上是您进行结构递归的参数,因此它必须是透明的。
以及如何开展
euclids工作?
幸运的是,您不必推出上述标准定义的自己的透明版本,因为其中的well_founded_ltof引理Coq.Arith.Wf_nat已经是透明的,因此我们可以重用它:
Lemma lt_wf_on_Z : well_founded myR.
Proof. exact (well_founded_ltof Z fabs). Defined.
Run Code Online (Sandbox Code Playgroud)
就是这样!修复lt_wf_on_Z其余代码后即可正常工作。