这应该是一个简单的问题。我是Coq的新手。
我想定义独占或Coq(据我所知,这不是预定义的)。重要的是允许多个命题(例如Xor A B C D)。
我还需要两个属性:
(Xor A1 A2 ... An)/\~A1 -> Xor A2... An
(Xor A1 A2 ... An)/\A1 -> ~A2/\.../\~An
我目前无法为未定义数量的变量定义函数。我试着手动定义两个,三个,四个和五个变量(这就是我需要的数量)。但后来证明这些属性是一种痛苦,而且看起来非常低效。
答案 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。
参数是一个列表,所以让我们分解案例:
(cons A L)
的xor为真:
这意味着我们需要在命题列表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)