Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion 基于重复除法的有充分根据的递归_Recursion_Idris_Induction_Totality - Fatal编程技术网

Recursion 基于重复除法的有充分根据的递归

Recursion 基于重复除法的有充分根据的递归,recursion,idris,induction,totality,Recursion,Idris,Induction,Totality,假设我有一些自然数d≥ 2和n>0;在这种情况下,我可以从n中分离出d,得到n=m*dk,其中m不能被d整除 );所以我想我应该为导致m的步骤创建一个数据类型: 并编写一个递归函数,计算给定的d和n对的步骤: total lemma: x * y `GT` 0 -> x `GT` 0 lemma {x = Z} LTEZero impossible lemma {x = Z} (LTESucc _) impossible lemma {x = (S k)} prf = LTESucc LT

假设我有一些自然数d≥ 2和n>0;在这种情况下,我可以从n中分离出d,得到n=m*dk,其中m不能被d整除

);所以我想我应该为导致m的
步骤创建一个数据类型:

并编写一个递归函数,计算给定的
d
n
对的
步骤

total lemma: x * y `GT` 0 -> x `GT` 0
lemma {x = Z} LTEZero impossible
lemma {x = Z} (LTESucc _) impossible
lemma {x = (S k)} prf = LTESucc LTEZero

steps : (d : Nat) -> {auto dValid: d `GTE` 2} -> (n : Nat) -> {auto nValid: n `GT` 0} -> Steps d {dValid} n
steps Z {dValid = LTEZero} _ impossible
steps Z {dValid = (LTESucc _)} _ impossible
steps (S d) {dValid} n {nValid} with (divMod n d)
  steps (S d) (q * S d) {nValid} | MkDivMod q Z _ = Step (steps (S d) {dValid} q {nValid = lemma nValid})
  steps (S d) (S rem + q * S d) | MkDivMod q (S rem) remSmall = Base (S rem) (LTESucc LTEZero) remSmall q
但是,
步骤
不被接受为总数,因为没有明显的理由说明递归调用是有根据的(在
q
n
之间没有结构关系)

但我也有一个功能

total wf : (S x) `LT` (S x) * S (S y)
有一个无聊的证据


我可以在步骤的定义中使用
wf
来向Idris解释
步骤是全部的吗?

这里有一种方法可以使用有充分根据的递归来完成你的要求。不过,我相信有更好的办法。在接下来的内容中,我将使用标准的
LT
函数,它允许我们实现我们的目标,但是我们需要克服一些障碍

不幸的是,
LT
是一个函数,而不是类型构造函数或数据构造函数,这意味着我们无法定义
LT
的类型类。以下代码是此情况的解决方法:

total
accIndLt : {P : Nat -> Type} ->
         (step : (x : Nat) -> ((y : Nat) -> LT y x -> P y) -> P x) ->
         (z : Nat) -> Accessible LT z -> P z
accIndLt {P} step z (Access f) =
  step z $ \y, lt => accIndLt {P} step y (f y lt)

total
wfIndLt : {P : Nat -> Type} ->
        (step : (x : Nat) -> ((y : Nat) -> LT y x -> P y) -> P x) ->
        (x : Nat) -> P x
wfIndLt step x = accIndLt step x (ltAccessible x)
我们需要一些处理小于关系的辅助引理,这些引理可以在gist(
Order
module)中找到。这是我最近开始的个人图书馆的一个子集。我确信helper引理的证明可以最小化,但这不是我的目标

导入
Order
模块后,我们可以解决这个问题(我稍微修改了原始代码,修改它或编写一个包装器以获得原始类型并不困难):

我在模块的函数之后建模了
步骤

完整代码可用


警告:总计检查器(从Idris 0.99版本开始,发行版)不接受
步骤
作为总计。它最近得到了修复,并解决了我们的问题(我用Idris 0.99-git:17f0899c测试了它)。

你的意思是
m+d^k
?@AndrásKovács:不,我的意思是在
m*d^k
中,所有
d
都在
d^k
组件中,因此
m
不再可以被
d
整除。
total
accIndLt : {P : Nat -> Type} ->
         (step : (x : Nat) -> ((y : Nat) -> LT y x -> P y) -> P x) ->
         (z : Nat) -> Accessible LT z -> P z
accIndLt {P} step z (Access f) =
  step z $ \y, lt => accIndLt {P} step y (f y lt)

total
wfIndLt : {P : Nat -> Type} ->
        (step : (x : Nat) -> ((y : Nat) -> LT y x -> P y) -> P x) ->
        (x : Nat) -> P x
wfIndLt step x = accIndLt step x (ltAccessible x)
total
steps : (n : Nat) -> {auto nValid : 0 `LT` n} -> (d : Nat) -> Steps (S (S d)) n
steps n {nValid} d = wfIndLt {P = P} step n d nValid
  where
    P : (n : Nat) -> Type
    P n = (d : Nat) -> (nV : 0 `LT` n) -> Steps (S (S d)) n

    step : (n : Nat) -> (rec : (q : Nat) -> q `LT` n -> P q) -> P n
    step n rec d nV with (divMod n (S d))
      step (S r + q * S (S d)) rec d nV | (MkDivMod q (S r) prf) =
        Base (S r) (LTESucc LTEZero) prf q
      step (Z + q * S (S d))       rec d nV | (MkDivMod q Z     _) =
        let qGt0 = multLtNonZeroArgumentsLeft nV in
        let lt = multLtSelfRight (S (S d)) qGt0 (LTESucc (LTESucc LTEZero)) in
        Step (rec q lt d qGt0)