Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.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
如何处理Coq中程序定点生成的非常大的术语?_Coq - Fatal编程技术网

如何处理Coq中程序定点生成的非常大的术语?

如何处理Coq中程序定点生成的非常大的术语?,coq,Coq,我试图在Coq函数中定义并证明它是正确的,该函数可以有效地区分两个排序列表。由于它并不总是在结构上较小的项上递归(第一个或第二个列表较小),Fixpoint不会接受它,因此我尝试使用Program Fixpoint 当尝试使用策略siml或program\u siml证明函数的属性时,Coq花费数分钟计算,然后产生一个巨大的术语,数百行。我想知道我是否使用了程序固定点错误的方法,或者在推理时是否应该使用其他策略而不是简化 我还想知道这样在params中包含正确性所需的属性是否是一种好的做法,或者

我试图在Coq函数中定义并证明它是正确的,该函数可以有效地区分两个排序列表。由于它并不总是在结构上较小的项上递归(第一个或第二个列表较小),
Fixpoint
不会接受它,因此我尝试使用
Program Fixpoint

当尝试使用策略
siml
program\u siml
证明函数的属性时,Coq花费数分钟计算,然后产生一个巨大的术语,数百行。我想知道我是否使用了
程序固定点
错误的方法,或者在推理时是否应该使用其他策略而不是简化

我还想知道这样在params中包含正确性所需的属性是否是一种好的做法,或者最好有一个单独的包装函数,将正确性属性作为params,并使此函数只将两个列表区分开来

请注意,我确实尝试定义了一个更简单的
make_diff
,它只将l1和l2作为参数,并固定了类型
a
和关系
R
,但当应用
程序\u siml
siml
策略时,这仍然产生了一个巨大的术语

*编辑:我的包括(尽管此处可能不需要全部包括):

守则:

Definition is_decidable (A : Type) (R : relation A) := forall x y, {R x y} + {~(R x y)}.
Definition eq_decidable (A : Type) := forall (x y : A), { x = y } + { ~ (x = y) }.

Inductive diff (X: Type) : Type :=
  | add : X -> diff X
  | remove : X -> diff X 
  | update : X -> X -> diff X.

Program Fixpoint make_diff (A : Type) 
    (R : relation A)
    (dec : is_decidable A R)
    (eq_dec : eq_decidable A)
    (trans : transitive A R) 
    (lt_neq : (forall x y, R x y -> x <> y))
    (l1 l2 : list A)
     {measure (length l1 + length l2) } : list (diff A) :=
  match l1, l2 with
  | nil, nil => nil
  | nil, (new_h::new_t) => (add A new_h) :: (make_diff A R dec eq_dec trans lt_neq nil new_t)
  | (old_h::old_t), nil => (remove A old_h) :: (make_diff A R dec eq_dec trans lt_neq old_t nil)
  | (old_h::old_t) as old_l, (new_h::new_t) as new_l => 
    if dec old_h new_h 
      then (remove A old_h) :: make_diff A R dec eq_dec trans lt_neq old_t new_l
      else if eq_dec old_h new_h 
        then (update A old_h new_h) :: make_diff A R dec  eq_dec trans lt_neq old_t new_t
        else  (add A new_h) :: make_diff A R dec eq_dec trans lt_neq old_l new_t 
  end.
Next Obligation.
Proof.
  simpl.
  generalize dependent (length new_t).
  generalize dependent (length old_t).
  auto with arith.
Defined.
Next Obligation.
Proof.
  simpl.
  generalize dependent (length new_t).
  generalize dependent (length old_t).
  auto with arith.
Defined.
定义是可判定的(A:Type)(R:relationa):=forall xy,{rxy}+{~(rxy)}。
定义eq_可判定(A:Type):=forall(xy:A),{x=y}+{~(x=y)}。
感应差异(X:类型):类型:=
|添加:X->diff X
|移除:X->diff X
|更新:X->X->diff X。
程序固定点制造差异(A:类型)
(R:关系A)
(dec:is_可判定为R)
(等式决定:等式决定A)
(trans:transitive A R)
(lt_neq:(对于所有x y,R x y->x y))
(l1 l2:列表A)
{度量(长度l1+长度l2)}:列表(差异A):=
将l1、l2与
|零,零=>零
|无,(新的:新的)=>(添加新的):(使不同的R-dec-eq-dec-trans-lt\n无新的)
|(old_h::old_t),nil=>(删除一个old_h):(使R dec eq_dec trans lt_neq old_t nil)
|(old_h::old_t)与old_l一样,(new_h::new_t)与new_l一样=>
如果dec old\u h new\u h
然后(删除旧的)::将旧的与新的区别开来
否则,如果等式为“旧”或“新”
然后(更新旧的新的)::使不同的数据均衡转换为新的数据
其他(添加一个新的)::使差异化为相等值,转换为旧值或新值
结束。
下一项义务。
证明。
简单。
广义相关(新长度)。
广义相关(长度旧\u t)。
自动与算术。
定义
下一项义务。
证明。
简单。
广义相关(新长度)。
广义相关(长度旧\u t)。
自动与算术。
定义

在这种特殊情况下,我们可以去掉
程序固定点
,使用简单的
固定点
。由于在每次递归调用时,我们在第一个列表的尾部或第二个列表的尾部调用
make_diff
,因此我们可以按如下方式嵌套两个定点函数。(我在这里使用了
部分
机制,以避免传递太多相同的参数)


对于遇到的任何人来说,现在更好的选择是插件,它最终将取代函数和程序固定点。

一些观察结果:(1)我认为你可以用
固定点来实现它(我试图演示如何实现)。(2)如果你去掉了未使用的参数(
trans
lt\u neq
Program Fixpoint
工作得更快。@AntonTrunov谢谢,我不知道这样做是可行的。如果你把它作为答案添加,我会接受它,它可能比要点中的寿命更长。好了,完成了!我稍微刷了一下代码。请同时添加你包含的库。弄清楚你包含了哪些库是一件痛苦的事。基于在nton的注释和回答中,您可以尝试从递归中删除所有在所有递归调用中相同的参数。这里,只有
l1
l2
不同。所有其他参数都可以从递归函数中删除。然后您可以将它们放入包装函数或使用节机制。但是这个答案是正确的吗问题?插件是否生成较小的术语?@AntonTrunov插件生成较小的重写规则,可用于推理,而不是siml/program\u siml.+1如果您在答案中添加注释(可能还有
make\u diff
的代码示例),也会很好。
Definition is_decidable (A : Type) (R : relation A) := forall x y, {R x y} + {~(R x y)}.
Definition eq_decidable (A : Type) := forall (x y : A), { x = y } + { ~ (x = y) }.

Inductive diff (X: Type) : Type :=
  | add : X -> diff X
  | remove : X -> diff X 
  | update : X -> X -> diff X.

Program Fixpoint make_diff (A : Type) 
    (R : relation A)
    (dec : is_decidable A R)
    (eq_dec : eq_decidable A)
    (trans : transitive A R) 
    (lt_neq : (forall x y, R x y -> x <> y))
    (l1 l2 : list A)
     {measure (length l1 + length l2) } : list (diff A) :=
  match l1, l2 with
  | nil, nil => nil
  | nil, (new_h::new_t) => (add A new_h) :: (make_diff A R dec eq_dec trans lt_neq nil new_t)
  | (old_h::old_t), nil => (remove A old_h) :: (make_diff A R dec eq_dec trans lt_neq old_t nil)
  | (old_h::old_t) as old_l, (new_h::new_t) as new_l => 
    if dec old_h new_h 
      then (remove A old_h) :: make_diff A R dec eq_dec trans lt_neq old_t new_l
      else if eq_dec old_h new_h 
        then (update A old_h new_h) :: make_diff A R dec  eq_dec trans lt_neq old_t new_t
        else  (add A new_h) :: make_diff A R dec eq_dec trans lt_neq old_l new_t 
  end.
Next Obligation.
Proof.
  simpl.
  generalize dependent (length new_t).
  generalize dependent (length old_t).
  auto with arith.
Defined.
Next Obligation.
Proof.
  simpl.
  generalize dependent (length new_t).
  generalize dependent (length old_t).
  auto with arith.
Defined.
Require Import Coq.Lists.List.
Import ListNotations.
Require Import Coq.Relations.Relations.

Section Make_diff.

Variable A : Type.
Variable R : relation A.
Variable dec : is_decidable A R.
Variable eq_dec : eq_decidable A.
Variable trans : transitive A R.
Variable lt_neq : forall x y, R x y -> x <> y.

Fixpoint make_diff (l1 l2 : list A) : list (diff A) :=
  let fix make_diff2 l2 :=
  match l1, l2 with
  | nil, nil => nil
  | nil, new_h::new_t => (add A new_h) :: make_diff2 new_t
  | old_h::old_t, nil => (remove A old_h) :: make_diff old_t nil
  | old_h::old_t, new_h::new_t =>
    if dec old_h new_h 
    then (remove A old_h) :: make_diff old_t l2
    else if eq_dec old_h new_h 
         then (update A old_h new_h) :: make_diff old_t new_t
         else (add A new_h) :: make_diff2 new_t
  end
  in make_diff2 l2.

End Make_diff.
(* make the first 2 arguments implicit *)    
Arguments make_diff [A R] _ _ _ _.

Require Import Coq.Arith.Arith.

Compute make_diff lt_dec Nat.eq_dec [1;2;3] [4;5;6].
(* = [remove nat 1; remove nat 2; remove nat 3; add nat 4; add nat 5; add nat 6] 
      : list (diff nat) *)