在软件基金会中IndProp.v
要求一个人证明鸽笼原则,并且可以使用排除中间,但是提到它并不严格必要。我一直试图在没有EM的情况下证明它,但我的大脑似乎是经典的连接。
我很高兴看到完整的证据,但请避免“明确地”发布,以免破坏软件基础课程的练习。
该定义使用两个归纳谓词In
和repeats
。
Require Import Lists.List.
Import ListNotations.
Section Pigeon.
Variable (X:Type).
Implicit Type (x:X).
Fixpoint In x l : Prop := (*** In ***)
match l with
| nil => False
| (x'::l') => x' = x \/ In x l'
end.
Hypothesis in_split : forall x l, In x l -> exists l1 l2, l = l1 ++ x :: l2.
Hypothesis in_app: forall x l1 l2, In x (l1++l2) <-> In x l1 \/ In x l2.
Inductive repeats : list X -> Prop := (*** repeats ***)
repeats_hd l x : In x l -> repeats (x::l)
| repeats_tl l x : repeats l -> repeats (x::l).
Theorem pigeonhole_principle_NO_EM: (*** pigeonhole ***)
forall l1 l2,
length l2 < length l1 -> (* There are more pigeons than nests *)
(forall x, In x l1 -> In x l2) -> (* All pigeons are in some nest *)
repeats l1. (* Thus, some pigeons share nest *)
Proof.
(* ??? *)
答案 0 :(得分:5)
我将描述导致我找到解决方案的思维过程,以防万一。我们可以应用归纳,并且可以简单地简化为l1 = a::l1'
,l2 = a::l2'
。现在l1'
是a::l2'
的子集。我受过EM训练的直觉是下列之一:
a
位于l1'
。a
不在l1'
。在后一种情况下,l1'
的每个元素都在a::l2'
中,但与a
不同,因此必须位于l2'
中。因此l1'
是l2'
的子集,我们可以应用归纳假设。
不幸的是,如果In
不可判定,则上述内容无法直接形式化。特别是如果对于给定类型不能判定相等,则很难证明元素是不相等的,因此很难证明像~(In a l1')
这样的否定语句。但是,我们想用这个否定陈述来证明一个积极的陈述,即
forall x, In x l1' -> In x l2'
通过类比,假设我们想要证明
P \/ Q
Q -> R
------
P \/ R
上述直观的论证就像从P \/ ~P
开始,在第二种情况下使用~P -> Q -> R
。我们可以使用直接证据来避免EM。
对列表l1'
进行量化会使这更加复杂,但我们仍然可以使用以下引理构建直接证明,这可以通过归纳证明。
Lemma split_or {X} (l : list X) (P Q : X -> Prop) :
(forall x, In x l -> (P x \/ Q x)) ->
(exists x, In x l /\ P x) \/ (forall x, In x l -> Q x).
最后请注意,直观的归类原则也可以通过以下方式形式化,当类型具有不可判定的平等时,无法证明这一点(注意结论中有否定的陈述):
Definition pigeon2 {X} : Prop := forall (l1 l2 : list X),
length l2 < length l1 ->
(exists x, In x l1 /\ ~(In x l2)) \/ repeats l1.
答案 1 :(得分:2)
可能的建设性证据如下:
我们通过pigeonhole_principle_NO_EM
上的归纳来证明l1
。由于长度约束,只有非空的情况才有可能。所以,假设l1 = x :: l1'
。现在,检查l1'
是否有某些f : (forall x, In x l1 -> In x l2)
元素被x
映射到与x'
相同的成员资格证明。如果存在x = x'
个元素,那么l1
会跟随l2'
,因此会重复x
。如果没有这样的元素,那么我们可以通过从l2
删除l2'
映射到的元素来获取f' : forall x, In x l1' -> In x l2'
,并将归纳假设应用于var socket = io.connect('http://localhost:8080', {
transports: [
'websocket',
'polling'
]
});
和相应的public static string AdjustString(string str, List<string> userInput)
{
int i = 0;
foreach (var input in userInput)
{
var searchedSubstring = $"[{i}]";
str = str.Replace(searchedSubstring, input);
i++;
}
return str;
}
static void UsgeExample()
{
var newString = AdjustString("[0][1][2]123[3]",
new List<string> {"A", "B", "C", "D"});
}
功能。
这就是它,但我注意到,实际上使用给定的定义来形式化这个证明并不容易,因为我们需要证明异构或依赖的等式,因为我们必须比较可能不同元素的成员证明。
关于总体上掌握建设性证据的问题,一个重要的技能或习惯总是在研究我们拥有什么样的数据,而不仅仅是我们所知道的那种逻辑事实。在这种情况下,成员资格证明实际上是指向列表的索引,捆绑在一起,证明指向的元素等于某些值。如果会员证明没有说明确切元素的位置,那么这种证据就不可能有建设性。