如何在Coq中定义Xor并证明其属性

时间:2011-07-20 15:40:46

标签: xor coq

这应该是一个简单的问题。我是Coq的新手。

我想定义独占或Coq(据我所知,这不是预定义的)。重要的是允许多个命题(例如Xor A B C D)。

我还需要两个属性:

(Xor A1 A2 ... An)/\~A1 -> Xor A2... An
(Xor A1 A2 ... An)/\A1 -> ~A2/\.../\~An

我目前无法为未定义数量的变量定义函数。我试着手动定义两个,三个,四个和五个变量(这就是我需要的数量)。但后来证明这些属性是一种痛苦,而且看起来非常低效。

2 个答案:

答案 0 :(得分:4)

好吧,我建议你从Xor开始获得2个参数并证明它的属性。

然后,如果你想概括它,你可以定义Xor获取参数列表 - 你应该 能够使用你的2参数Xor定义它并证明它的属性。

我可以提供更多细节,但我认为自己做这件事更有趣,让我知道它是怎么回事:)。

答案 1 :(得分:3)

鉴于你的第二个属性,我认为你对独家或更高级别的定义是“这些命题中的一个是真的”(而不是“这些命题的奇数是真的”或“这些命题中的至少一个”是真的,至少有一个是假的“,这是其他可能的概括。”

此独占或非关联属性。这意味着你不能只将高阶xor定义为xor(A1,...,An)= xor(A1,xor(A2,...))。您需要一个全局定义,这意味着类型构造函数必须采用参数列表(或其他一些数据结构,但列表是最明显的选择)。

Inductive xor : list Prop -> Prop := …

您现在有两个合理的选择:从第一原则中归纳地构建xor的定义,或者调用列表谓词。列表谓词将是“匹配此谓词的列表中有一个唯一元素”。由于标准列表库没有定义这个谓词,并且定义它比定义xor稍微困难,我们将归纳为xor。

参数是一个列表,所以让我们分解案例:

  • 空列表的xor始终为false;
  • 如果满足以下两个条件中的任何一个,则列表(cons A L)的xor为真:
    • A为真,L的所有元素均为真;
    • A是假的,L的一个元素恰好是真的。

这意味着我们需要在命题列表nand上定义辅助谓词,以表征虚假命题列表。这里有很多可能性:折叠/\运算符,手动导入,或调用列表谓词(再次,不在标准列表库中)。我会手工导入,但折叠/\是另一个合理的选择。

Require Import List.
Inductive nand : list Prop -> Prop :=
  | nand_nil : nand nil
  | nand_cons : forall (A:Prop) L, ~A -> nand L -> nand (A::L).
Inductive xor : list Prop -> Prop :=
  | xor_t : forall (A:Prop) L, A -> nand L -> xor (A::L)
  | xor_f : forall (A:Prop) L, ~A -> xor L -> xor (A::L).
Hint Constructors nand xor.

您要证明的属性是反转属性的简单推论:给定构造类型,分解可能性(如果您有xor,则它是xor_t或者xor_f)。这是第一个的手动证明;第二个是非常相似的。

Lemma xor_tail : forall A L, xor (A::L) -> ~A -> xor L.
Proof.
  intros. inversion_clear H.
    contradiction.
    assumption.
Qed.

您可能需要的另一组属性是nand与内置连接之间的等价关系。例如,这是nand (A::nil)等同于~A的证明。证明nand (A::B::nil)等同于~A/\~B等等只是更加相同。在向前方向上,这又是一个反转属性(分析nand类型的可能构造函数)。在向后的方向上,这是构造函数的简单应用。

Lemma nand1 : forall A, nand (A::nil) <-> ~A.
Proof.
  split; intros.
    inversion_clear H. assumption.
    constructor. assumption. constructor.
Qed.

您可能在某些时候也需要替换和重新排列属性。以下是一些您可能想要证明的关键引理(这些应该不是很困难,只需引入正确的东西):

  • forall A1 B2 L, (A1<->A2) -> (xor (A1::L) <-> xor (A2::L))
  • forall K L1 L2, (xor L1 <-> xor L2) -> (xor (K++L1) <-> xor (K++L2))
  • forall K A B L, xor (K++A::B::L) <-> xor (K::B::A::L)
  • forall K L M N, xor (K++L++M++N) <-> xor (K++M++L++N)