あなたの 2 番目のプロパティを考えると、排他的またはより高いアリティでのあなたの定義は、「これらの命題の正確に 1 つが真である」(「これらの命題の奇数個が真である」または「これらの命題の少なくとも 1 つが真であり、少なくとも 1 つは偽である」などの一般化の可能性があります)。
この排他的 or は結合プロパティではありません。つまり、アリティの高い xor を xor(A1,…,An)=xor(A1,xor(A2,…)) として定義することはできません。グローバル定義が必要です。これは、型コンストラクターが引数のリスト (または他のデータ構造ですが、リストが最も明白な選択肢です) を受け取る必要があることを意味します。
Inductive xor : list Prop -> Prop := …
ここで、合理的な選択肢が 2 つあります。第一原理から帰納的に xor の定義を作成するか、リスト述語を呼び出します。リストの述語は、「この述語に一致するリストに一意の要素があります」になります。標準リスト ライブラリはこの述語を定義しておらず、定義するのは xor を定義するよりも少し難しいため、帰納的に xor を構築します。
引数はリストなので、ケースを分類してみましょう:
- 空のリストの xor は常に false です。
(cons A L)
次の 2 つの条件のいずれかが満たされている場合
、リストの xorは true です。
- A は真であり、L のどの要素も真ではありません。
- A は false で、L の要素の 1 つだけが true です。
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.
証明したいプロパティは、反転プロパティの単純な結果です: 構築された型が与えられた場合、可能性を分解します ( がある場合、それは aまたは axor
のいずれかです)。これが最初の手動証明です。2番目は非常に似ています。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)