在 coq 中由 属性 定义
Definition by property in coq
我在形式化以下形式的定义时遇到问题:定义一个整数,使得 属性 成立。
假设我正式定义了 属性:
Definition IsGood (x : Z) : Prop := ...
现在我需要一个表格的定义:
Definition Good : Z := ...
假设我证明了带有 属性 的整数存在并且是唯一的:
Lemma Lemma_GoodExistsUnique : exists! (x : Z), IsGood x.
是否有使用 IsGood
和 Lemma_GoodExistsUnique
定义 Good
的简单方法?
因为 属性 是在整数上定义的,所以似乎不需要额外的公理。无论如何,我看不出添加诸如选择公理之类的内容如何有助于定义。
此外,我在形式化以下形式的定义时遇到了问题(我怀疑这与我上面描述的问题有关,但如果不是这样请指出):对于每个 x
,存在y
,并且这些y
对于不同的x
是不同的。例如,如何使用 IsGood
:
定义有 N
个不同的好整数
Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) := ...?
在现实世界的数学中,这样的定义时有发生,所以如果 Coq 旨在适用于实用数学,那么形式化应该不难。
第一个问题的简短回答是:一般来说,这是不可能的,但在您的特定情况下,是的。
在 Coq 的理论中,命题(即 Prop
s)及其证明具有非常特殊的地位。特别是,通常不可能编写提取存在证明见证的选择运算符。这样做是为了使理论与某些公理和原则兼容,例如证明无关性,即给定命题的所有证明彼此相等。如果您希望能够做到这一点,您需要将此选择运算符作为附加公理添加到您的理论中,如 standard library.
但是,在某些特定情况下, 可以从抽象的存在证明中提取见证,而无需重复使用任何其他公理。特别是,当所讨论的 属性 是可判定的时,可以对可数类型(例如 Z
)执行此操作。例如,您可以使用 Ssreflect 库中的 choiceType
接口来准确获取您想要的内容(查找 xchoose
函数)。
话虽如此,我通常建议 反对 以这种方式做事,因为它会导致不必要的复杂性。直接定义 Good
可能更容易,而不求助于存在性证明,然后单独证明 Good
具有所寻求的 属性.
Definition Good : Z := (* ... *)
Definition IsGood (z : Z) : Prop := (* ... *)
Lemma GoodIsGood : IsGood Good.
Proof. (* ... *) Qed.
Lemma GoodUnique : forall z : Z, IsGood z -> z = Good.
如果你绝对想用存在性证明来定义 Good
,你也可以改变 Lemma_GoodExistsUnique
的证明以在 Type
中使用连接词而不是 Prop
,因为它允许您使用 proj1_sig
函数直接提取 witness:
Lemma Lemma_GoodExistsUnique : {z : Z | Good z /\ forall z', Good z' -> z' = z}.
Proof. (* ... *) Qed.
关于你的第二个问题,是的,和第一点有点关系。再一次,我建议你写下一个函数 y_from_x
,类型为 Z -> Z
,它将在给定 x
的情况下计算 y
,然后分别证明这个函数涉及输入和输出以特定的方式。然后,您可以通过证明 y_from_x
是单射的来说 y
对于不同的 x
是不同的。
另一方面,我不确定你的最后一个例子与第二个问题有什么关系。如果我正确理解你想做什么,你可以这样写
Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) :=
exists zs : list Z,
Z.of_nat (length zs) = N
/\ NoDup zs
/\ Forall IsGood zs.
这里,Z.of_nat : nat -> Z
是从自然数到整数的规范注入,NoDup
是断言列表不包含重复元素的谓词,Forall
是更高的- order predicate 断言给定的谓词(在本例中为 IsGood
)包含列表的所有元素。
最后一点,我建议不要对只能涉及自然数的事物使用 Z
。在你的例子中,你用一个整数来谈论一个集合的基数,这个数字总是一个自然数。
我在形式化以下形式的定义时遇到问题:定义一个整数,使得 属性 成立。
假设我正式定义了 属性:
Definition IsGood (x : Z) : Prop := ...
现在我需要一个表格的定义:
Definition Good : Z := ...
假设我证明了带有 属性 的整数存在并且是唯一的:
Lemma Lemma_GoodExistsUnique : exists! (x : Z), IsGood x.
是否有使用 IsGood
和 Lemma_GoodExistsUnique
定义 Good
的简单方法?
因为 属性 是在整数上定义的,所以似乎不需要额外的公理。无论如何,我看不出添加诸如选择公理之类的内容如何有助于定义。
此外,我在形式化以下形式的定义时遇到了问题(我怀疑这与我上面描述的问题有关,但如果不是这样请指出):对于每个 x
,存在y
,并且这些y
对于不同的x
是不同的。例如,如何使用 IsGood
:
N
个不同的好整数
Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) := ...?
在现实世界的数学中,这样的定义时有发生,所以如果 Coq 旨在适用于实用数学,那么形式化应该不难。
第一个问题的简短回答是:一般来说,这是不可能的,但在您的特定情况下,是的。
在 Coq 的理论中,命题(即 Prop
s)及其证明具有非常特殊的地位。特别是,通常不可能编写提取存在证明见证的选择运算符。这样做是为了使理论与某些公理和原则兼容,例如证明无关性,即给定命题的所有证明彼此相等。如果您希望能够做到这一点,您需要将此选择运算符作为附加公理添加到您的理论中,如 standard library.
但是,在某些特定情况下, 可以从抽象的存在证明中提取见证,而无需重复使用任何其他公理。特别是,当所讨论的 属性 是可判定的时,可以对可数类型(例如 Z
)执行此操作。例如,您可以使用 Ssreflect 库中的 choiceType
接口来准确获取您想要的内容(查找 xchoose
函数)。
话虽如此,我通常建议 反对 以这种方式做事,因为它会导致不必要的复杂性。直接定义 Good
可能更容易,而不求助于存在性证明,然后单独证明 Good
具有所寻求的 属性.
Definition Good : Z := (* ... *)
Definition IsGood (z : Z) : Prop := (* ... *)
Lemma GoodIsGood : IsGood Good.
Proof. (* ... *) Qed.
Lemma GoodUnique : forall z : Z, IsGood z -> z = Good.
如果你绝对想用存在性证明来定义 Good
,你也可以改变 Lemma_GoodExistsUnique
的证明以在 Type
中使用连接词而不是 Prop
,因为它允许您使用 proj1_sig
函数直接提取 witness:
Lemma Lemma_GoodExistsUnique : {z : Z | Good z /\ forall z', Good z' -> z' = z}.
Proof. (* ... *) Qed.
关于你的第二个问题,是的,和第一点有点关系。再一次,我建议你写下一个函数 y_from_x
,类型为 Z -> Z
,它将在给定 x
的情况下计算 y
,然后分别证明这个函数涉及输入和输出以特定的方式。然后,您可以通过证明 y_from_x
是单射的来说 y
对于不同的 x
是不同的。
另一方面,我不确定你的最后一个例子与第二个问题有什么关系。如果我正确理解你想做什么,你可以这样写
Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) :=
exists zs : list Z,
Z.of_nat (length zs) = N
/\ NoDup zs
/\ Forall IsGood zs.
这里,Z.of_nat : nat -> Z
是从自然数到整数的规范注入,NoDup
是断言列表不包含重复元素的谓词,Forall
是更高的- order predicate 断言给定的谓词(在本例中为 IsGood
)包含列表的所有元素。
最后一点,我建议不要对只能涉及自然数的事物使用 Z
。在你的例子中,你用一个整数来谈论一个集合的基数,这个数字总是一个自然数。