This should be an easy question. I’m new with Coq.
I want to define the exclusive or in Coq (which to the best of my knowledge is not predefined). The important part is to allow for multiple propositions (e.g. Xor A B C D).
I also need the two properties:
(Xor A1 A2 ... An)/\~A1 -> Xor A2... An
(Xor A1 A2 ... An)/\A1 -> ~A2/\.../\~An
I’m currently having trouble defining the function for an undefined number of variables. I tried to define it by hand for two, three, four and five variables (that’s how many I need). But then proving the properties is a pain and seems very inefficient.
Given your second property, I assume that your definition of exclusive or at higher arities is “exactly one of these propositions is true” (and not “an odd number of these propositions is true” or “at least one of these propositions is true and at least one is false”, which are other possible generalizations).
This exclusive or is not an associative property. This means you can’t just define higher-arity xor as xor(A1,…,An)=xor(A1,xor(A2,…)). You need a global definition, and this means that the type constructor must take a list of arguments (or some other data structure, but a list is the most obvious choice).
You now have two reasonable choices: build your definition of xor inductively from first principles, or invoke a list predicate. The list predicate would be “there is a unique element in the list matching this predicate”. Since the standard list library does not define this predicate, and defining it is slightly harder than defining xor, we’ll build xor inductively.
The argument is a list, so let’s break down the cases:
(cons A L)is true iff either of these two conditions is met:This means we need to define an auxiliary predicate on lists of propositions,
nand, characterizing the lists of false propositions. There are many possibilities here: fold the/\operator, induct by hand, or call a list predicate (again, not in the standard list library). I’ll induct by hand, but folding/\is another reasonable choice.The properties you want to prove are simple corollaries of inversion properties: given a constructed type, break down the possibilities (if you have a
xor, it’s either axor_tor axor_f). Here’s a manual proof of the first; the second is very similar.Another set of properties you’re likely to want is the equivalences between
nandand the built-in conjunction. As an example, here’s a proof thatnand (A::nil)is equivalent to~A. Proving thatnand (A::B::nil)is equivalent to~A/\~Band so on are merely more of the same. In the forward direction, this is once more an inversion property (analyse the possible constructors of thenandtype). In the backward direction, this is a simple application of the constructors.You’re also likely to need substitution and rearrangement properties at some point. Here are a few key lemmas that you may want to prove (these shouldn’t be very difficult, just induct on the right stuff):
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)