这里提到的树具有在所有子树(包括整个树)上的属性,根的内容具有最高优先级;但是没有在兄弟节点上指定顺序
树的定义如下:
Inductive tree : Set :=
| nil : tree
| cons : tree->nat->tree->tree.
我想使用coq合并两棵树。假设两个树是(cons l1 n1 r1)和(cons l2 n2 r2),如果n1&lt; = n2然后我合并l1和r1作为子树并创建新树((merge l1 r1)n1(cons l2 n2 r2) ))。当n2 <= n1时,可以使用类似的处理 以下是合并的定义:
Fixpoint merge (t1 t2 : tree) : tree.
destruct t1 as [ | l1 n1 r1].
apply t2.
destruct t2 as [ | l2 n2 r2].
apply (cons l1 n1 r1).
destruct (le_le_dec n1 n2).
apply (cons (merge l1 r1) n1 (cons l2 n2 r2)).
apply (cons (cons l1 n1 r1) n2 (merge l2 r2)).
Defined.
问题是coq认为上面的定义是不正确的。但实际上合并功能最终会终止。
我知道coq需要减少修复点的参数。但是如何用两个递减的参数来处理函数呢?
引理le_le_dec仅用于案例分析:
Lemma le_le_dec : forall x y, {x <= y}+{y <= x}.
Proof.
intros x y.
destruct (nat_delta x y) as [xy | yx].
destruct xy as [n e]. left. apply le_delta. exists n. assumption.
destruct yx as [n e]. right. apply le_delta. exists n. assumption.
Qed.
引理le_delta和nat_delta如下:
Lemma le_delta: forall n m, n <= m <-> exists x, (x + n = m).
Proof.
intros n m.
split.
intros e. induction e as [ |m les IHe].
exists 0. simpl. reflexivity.
destruct IHe as [x e]. exists (S x). simpl. rewrite e. reflexivity.
intros e. destruct e as [x e]. revert e. revert m.
induction x as [ | x IHx].
intros m e. simpl in e. rewrite e. apply le_n.
intros m e. destruct m as [ | m].
discriminate e.
apply (le_S n m).
apply (IHx m).
inversion e. reflexivity.
Qed.
Lemma nat_delta : forall x y, {n | n+x=y} + {n | n+y=x}.
Proof.
intros x y. induction x as [ | x IHx].
left. exists y. simpl. rewrite <- (plus_n_O y). reflexivity.
destruct IHx as [xy | yx].
destruct xy as [n e]. destruct n as [ | n].
right. exists (S 0). rewrite <- e. simpl. reflexivity.
left. exists n. rewrite <- plus_n_Sm. rewrite <- e. simpl. reflexivity.
destruct yx as [n e].
right. exists (S n). simpl. rewrite e. reflexivity.
Qed.
修复点的错误消息是:
Error:
Recursive definition of merge is ill-formed.
In environment
merge : tree -> tree -> tree
t1 : tree
t2 : tree
l1 : tree
n1 : nat
r1 : tree
l2 : tree
n2 : nat
r2 : tree
l : n2 <= n1
Recursive call to merge has principal argument equal to "l2" instead of
one of the following variables: "l1" "r1".
Recursive definition is:
"fun t1 t2 : tree =>
match t1 with
| nil => t2
| cons l1 n1 r1 =>
match t2 with
| nil => cons l1 n1 r1
| cons l2 n2 r2 =>
let s := le_le_dec n1 n2 in
if s
then cons (merge l1 r1) n1 (cons l2 n2 r2)
else cons (cons l1 n1 r1) n2 (merge l2 r2)
end
end".
答案 0 :(得分:2)
您必须在任何递归调用中使用相同的单独递减参数。试试这个:
Fixpoint merge (t1 t2 : tree) : tree.
destruct t1 as [ | l1 n1 r1].
apply t2.
destruct t2 as [ | l2 n2 r2].
apply (cons l1 n1 r1).
destruct (le_le_dec n1 n2).
apply (cons (cons l2 n2 r2) n1 (merge l1 r1)).
apply (cons (merge l1 r1) n2 (cons l2 n1 r2)).
Defined.
我不确定这种程序的属性是否会被保留,但如果您不确定是否可以尝试证明它们的存在。
如果您只是编写它而不是证明您的函数存在,那么您可以使用Function
代替Fixpoint
来证明您的函数在不改变其结构的情况下终止。
此外,我在尝试提取le_le_dec
时出错。我认为这是因为le_le_dec
在逻辑方面更多。为什么不将n1
和n2
与返回bool
的函数进行比较,并对结果进行案例分析?
你也可以试试这个:
Fixpoint meas (t1: tree): nat :=
match t1 with
| nil => O
| cons t2 _ t3 => S ((meas t2) + (meas t3))
end.
Fixpoint less_eq (n1 n2: nat): bool :=
match n1, n2 with
| O, O => true
| O, S _ => true
| S _, O => false
| S n3, S n4 => less_eq n3 n4
end.
Program Fixpoint merge (t1 t2: tree) {measure ((meas t1) + (meas t2))}: tree :=
match t1 with
| nil => t2
| cons l1 n1 r1 =>
match t2 with
| nil => cons l1 n1 r1
| cons l2 n2 r2 =>
match less_eq n1 n2 with
| false => cons (cons l1 n1 r1) n2 (merge l2 r2)
| true => cons (merge l1 r1) n1 (cons l2 n2 r2)
end
end
end.
然后你需要输入Next Obligation.
,并证明一些东西。
答案 1 :(得分:0)
您可能需要考虑将第一个树中的元素逐个插入到第二个树中。因此,您可以使用两个递归函数合并两个树。