如何使用排除的中间物证明信鸽原理?

时间:2019-05-15 09:29:51

标签: coq

Lemma remove {A} (x : A) xs (p : In x xs) :
  exists xs', (forall x', x' <> x -> In x' xs -> In x' xs') /\ (length xs = S (length xs')).
Proof.
induction xs.
- inversion p.
- destruct p.
  + subst x0.
    exists xs.
    split.
    * intros x' neq pin.
      destruct pin.
      -- contradict neq. symmetry. assumption.
      -- assumption.
    * reflexivity.
  + destruct (IHxs H) as [xs' pxs']. clear IHxs.
    destruct pxs' as [p1 plen]. rename x0 into x'.
    exists (x' :: xs').
    split.
    * intros x'' neq pin. 
      destruct pin.
      -- subst x'. left. reflexivity.
      -- right. apply p1. assumption. assumption.
    * simpl.
      rewrite -> plen.
      reflexivity. 
Qed.

Theorem pigeonhole_principle: forall (X:Type) (l1  l2:list X),
  excluded_middle ->
  AllIn l1 l2 ->
  length l2 < length l1 ->
  repeats l1.
Proof.
induction l1; simpl; intros l2 ex_mid Hin Hlen.
- inversion Hlen.
- apply repeats_rest.
  destruct (remove x l2) as [l2' Hl2].
  + apply Hin. left. reflexivity.
  + destruct Hl2 as [Hmap Hlen'].
    rewrite Hlen' in Hlen.
    clear Hlen'.
    apply (IHl1 l2').
    1 : { assumption. }
    2 : { revert Hlen. unfold lt. intros. omega. }
    clear Hlen IHl1.
    revert Hin.
    unfold AllIn.
    intros.
    apply Hmap.
    2 : { apply Hin. right. assumption. }
1 subgoal
X : Type
x : X
l1, l2 : list X
ex_mid : excluded_middle
l2' : list X
Hmap : forall x' : X, x' <> x -> In x' l2 -> In x' l2'
Hin : forall u : X, In u (x :: l1) -> In u l2
u : X
H : In u l1
______________________________________(1/1)
u <> x

我发现网上有各种解决鸽洞原理的方法。上面的内容改编自Kovacs,但在他的证明中,他证明了不存在重复项,而是像SF练习中那样重复。

明显的区别是,我无法在此处证明u <> x的目标,因为以这种形式说明问题时信息较少。

由于这个问题既棘手又是可选的,并且存在现有的解决方案-我已经进行了两天的研究,所以有人可以向我描述我需要做的一个高层计划

我不是在寻找解决方案,但我希望中间被排除的解决方案很优雅,因为Coq证明without the excluded middle只是一堆重写和了解aq的源代码程序远不能理解它的作用。对该原则的大多数解释只是描述了什么,这不足以弥合我的直觉差距。

我从来没有见过经典的法则在起作用-似乎知道某事是可决定的并不会给我带来很多好处,而且我发现很难理解它们的意义。在这种情况下尤其如此,因此我对查看其目的将更感兴趣。

1 个答案:

答案 0 :(得分:1)

我在通过SF(软件基金会)工作时寻找答案时遇到了这个问题,但我自己证明了这一点。我将使用exclude_middle提供SF版鸽洞原理的草图。要证明的语句是,如果列表l1中的所有元素都在l2中,并且length l2小于length l1,则l1包含重复的元素。

SF提出的证据始于对l1的归纳。我将忽略简单的空白案例。在归纳情况下,破坏l2l2为空的情况很简单;我们考虑另一种情况。

现在,由于对l1的归纳和对l2的破坏,您要证明的陈述是关于具有第一个成员的列表的,所以我们将它们称为x1::l1x2::l2。您的成员资格假设现在看起来像:x1::l1中的所有元素都在x2::l2中。

但是首先,让我们使用排除的中间语来声明x1中的l1x1中的l1。如果x1中的l1,那么我们可以证明x1::l1有重复。因此,我们可以假设x1不在l1中。

足以满足归纳情况,即存在与l2'长度相同的l2,以使l1的所有元素都在l2'中。

现在考虑x1::l1上的隶属度假设,并将forall变量引入为x

根据假设,我们知道x1中的x2::l2。现在考虑l2',其中l2'x2::l2,其中一个x1实例被删除(使用in_split)。现在,由于x1不在l1中,我们可以得出结论,l1的所有成员也都在l2'中,而不是被删除的元素。然后,这满足归纳中的隶属度假设,并且一些与长度的争吵使我们length l2 = length l2',从而满足了长度假设。因此,我们得出结论:l1包含重复,因此也包含x1::l1

编辑:以前,我还对x1中的x2 = x1l2以及x是否进行了案例分析= {{1}中的x2x,并以更直接的方式解决了特殊情况。不需要,一般情况下也涵盖了它们。