在Coq中制作和比较集合

时间:2015-05-04 01:25:55

标签: set equality coq

我无法理解是否有可能证明两套(在这种情况下是常规语言)是相同的,因此可以互换。根据我的理解,即使它们在建设性上不相等,集也可以是等价的。

常规语言是一组字符串,但我不知道怎么说r1 = r2这样就可以在证明中使用像对称这样的东西。

这是我的RegularLanguage声明:

Inductive RegularLanguage (A : Set) : Set :=
  | EmptyLang : RegularLanguage A
  | EmptyStr : RegularLanguage A
  | Unit : A -> RegularLanguage A
  | Union :
    RegularLanguage A
    -> RegularLanguage A
    -> RegularLanguage A
  | Concat :
    RegularLanguage A
    -> RegularLanguage A
    -> RegularLanguage A
  | KleeneStar : RegularLanguage A -> RegularLanguage A
.

即使我说类型是Set,但据我所知,这并不会创建一组字符串。我需要一些RegularLanguage -> Set of strings类型的函数吗?

感谢您的帮助。

2 个答案:

答案 0 :(得分:6)

对于我试图澄清的一些Coq概念存在一些误解。

首先,在Coq中,你不应该像我们所说的那样查看Set" set"在传统数学中。相反,您应该将其视为类型。 Coq也有Type,但就本文而言,您可以将SetType视为可互换。为了避免混淆,从现在开始,我将使用" set"指的是传统数学中常用的概念," type"在Coq。

中引用SetType的元素

那么,集合和类型之间究竟有什么区别?那么,在正常的数学中,自问是否任何任何给定集合的成员是有意义的。因此,如果我们要在正常数学中发展正则表达式理论,并且每个正则表达式都被视为一个集合,那么提出诸如0 \in EmptyLang之类的问题是有意义的,因为即使0是一个自然数,它可能是任何先验集合的元素。作为一个不太习惯的例子,空字符串既是完整语言的成员(即包含所有字符串的成员),也是任何基本语言的Kleene闭包。

另一方面,在Coq中,该语言的每个有效元素都具有一个类型。例如,空字符串对于某些list A具有A类型,其写为[] : list A。如果我们尝试询问[]是否属于某些常规语言,请使用" has type"语法,我们得到一个错误;尝试输入例如。

Check ([] : EmptyLang). 

两个集合和类型都可以看作是元素的集合,但是类型在某种意义上更具限制性:例如,一个可以采用两个集合的交集,但是没有办法取两个的交集。类型。

其次,当你写

Inductive RegularLanguage (A : Set) : Set := (* ... *)

not 意味着您在标题下面列出的元素定义了类型。这意味着,对于每种类型A(A : Set)部分),您要定义一个标记为RegularLanguage A的新类型(RegularLanguage (A : Set) : Set部分),其元素为< em>由给定的构造函数列表自由生成。因此,我们有

EmptyLang : RegularLanguage nat

RegularLanguage nat : Set

但我们没有

EmptyLang : Set

(再一次,您可以尝试将所有上述判断输入Coq,以查看哪些被接受,哪些不被接受。

自由生成&#34;特别是,您列出的构造函数是 injective disjoint 。正如之前提到的那样,特别是Union l1 l2 = Union l2 l1并非如此;事实上,你通常可以证明Union l1 l2 <> Union l2 l1。问题在于,你在Coq(你不能改变)的归纳定义类型和你想要的常规语言相等概念中得到的平等概念不匹配。

虽然有几种解决方法,但我认为最简单的方法是使用setoid rewrite功能。这将涉及首先定义函数或谓词(例如,作为larsr建议,布尔函数regexp_match : RegularLanguage A -> list A -> bool)以确定常规语言何时包含某些字符串。然后,您可以在语言上定义等价关系:

Definition regexp_equiv A (l1 l2 : RegularLanguage A) : Prop :=
  forall s, regexp_match l1 s = regexp_match l2 s.

并使用setoid rewrite来重写这种等价关系。然而,有一个小警告,即你只能在与这种等价关系兼容的上下文中用等价关系重写,并且你需要明确地证明lemmas这样做。您可以在reference manual

中找到更多详细信息

答案 1 :(得分:1)

如果它们是由不同的构造函数构造的,则集合RegularLanguage A中的两个不同元素不相等。考虑L1 = ( a | b )L2 = ( b | a)。这里L1 <> L2因为构造函数的参数不同。

在您的注释中,L1可能为Union nat (Unit nat 1) (Unit nat 2)),L2为Union nat (Unit nat 2) (Unit nat 1))

相反,你想说有一个函数regexp_match : A -> RegularLanguage A -> list A -> bool匹配给定语言的字符串。你必须实现这个功能。

如果匹配并拒绝相同的字符串,则两个正则表达式相等。例如,L1L2

Lemma L1_eq_L2 : forall S, regexp_match L1 S = regexp_match L2 S.

如果您可以证明这一点,那么您可以使用此功能将regexp_match L1 S替换为regexp_match L2 S,反之亦然。