【问题标题】:Establish isomorphism between finite natural numbers and sigma在有限自然数和 sigma 之间建立同构
【发布时间】:2017-08-04 08:09:36
【问题描述】:

我在这里和 Coq 一起研究我定义的两种类型之间的关系。第一个类似于nat 的有限子集,只有三个元素:

Inductive N3 := zero | one | two.

第二个是 sigma 类型,其元素满足{x: nat | x < 3} 的命题。这是它的定义:

Definition less_than_3 := {x| x < 3}.

我想证明这两种类型是同构的。我通过以下方式定义了这两个函数:

Definition lt3_to_N3 (n: less_than_3) : N3 :=
match n with
  | exist 0 _ => zero
  | exist 1 _ => one
  | exist 2 _ => two
  | exist _ _ => two
end.

Definition N3_to_lt3 (n: N3) : less_than_3 :=
match n with
  | zero => exist _ 0 l_0_3
  | one => exist _ 1 l_1_3
  | two => exist _ 2 l_2_3
end.

l_0_3l_1_3l_2_3 只是公理:

Axiom l_0_3 : 0 < 3.
Axiom l_1_3 : 1 < 3.
Axiom l_2_3 : 2 < 3.

我成功定义了同构的第一部分

Definition eq_n3_n3 (n: N3) : lt3_to_N3 (N3_to_lt3 n) = n.
Proof.
by case n.
Defined.

但我无法定义另一边。这是我到目前为止所做的:

Definition eq_lt3_lt3 (x: less_than_3) : eq x (N3_to_lt3 (lt3_to_N3 x)).
Proof.
case: x.
move=> n p.
simpl.
???

我完全不确定定义的其余部分。我还尝试在x(N3_to_lt3 (lt3_to_N3 x)) 上进行模式匹配,但我不确定返回什么。

Definition eq_lt3_lt3 (x: less_than_3) : eq x (N3_to_lt3 (lt3_to_N3 x)) :=
match N3_to_lt3 (lt3_to_N3 x) with
  | x => ???
end.

感谢您的帮助。

【问题讨论】:

    标签: coq coq-tactic


    【解决方案1】:

    如果您从 math-comp 中的 finType 机器中获利,您也可以获得一些乐趣。

    例如,您可以使用序数枚举 [与您的类型同构] 通过枚举所有值来证明您的引理,而不是做繁琐的情况:

    From mathcomp Require Import all_ssreflect.
    
    Set Implicit Arguments.
    Unset Strict Implicit.
    Unset Printing Implicit Defensive.
    
    Lemma falseP T : false -> T.
    Proof. by []. Qed.
    
    Inductive N3 := zero | one | two.
    
    Definition lt3_to_N3 (n: 'I_3) : N3 :=
      match n with
      | Ordinal 0 _ => zero
      | Ordinal 1 _ => one
      | Ordinal 2 _ => two
      | Ordinal _ f => falseP _ f
      end.
    
    Definition N3_to_lt3 (n: N3) : 'I_3 :=
      match n with
      | zero => @Ordinal 3 0 erefl
      | one  => @Ordinal 3 1 erefl
      | two  => @Ordinal 3 2 erefl
      end.
    
    Lemma eq_lt3_lt3 : cancel lt3_to_N3 N3_to_lt3.
    Proof.
    apply/eqfunP; rewrite /FiniteQuant.quant0b /= /pred0b cardE /enum_mem.
    by rewrite unlock /= /ord_enum /= !insubT.
    Qed.
    
    (* We can define an auxiliary lemma to make our proofs cleaner *)
    Lemma all_by_enum (T : finType) (P : pred T) :
      [forall x, P x] = all P (enum T).
    Proof.
    apply/pred0P/allP => /= H x; first by have/negbFE := H x.
    suff Hx : x \in enum T by exact/negbF/H.
    by rewrite mem_enum.
    Qed.
    
    Lemma eq_lt3_lt3' : cancel lt3_to_N3 N3_to_lt3.
    Proof.
    by apply/eqfunP; rewrite all_by_enum enumT unlock /= /ord_enum /= !insubT.
    Qed.
    

    如您所见,目前的 math-comp 设计并不是非常适合完成这项工作,但多了解一下这个库还是很有趣的。

    另一个有趣的练习是为您的自定义数据类型定义finType 实例,然后确定两个集合具有相同的基数!这里有许多引理组合可供尝试,让您玩得开心!

    【讨论】:

    • 这似乎有点复杂。我会尝试通过你的证明,谢谢!
    【解决方案2】:

    由于您使用的是 ssreflect,最简单的路线是使用&lt; 的计算定义(在ssrnat 中),然后应用val_inj 引理:

    From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat.
    
    Inductive N3 := zero | one | two.
    
    Definition less_than_3 := {x| x < 3}.
    
    Definition lt3_to_N3 (n: less_than_3) : N3 :=
    match n with
      | exist 0 _ => zero
      | exist 1 _ => one
      | exist 2 _ => two
      | exist _ _ => two
    end.
    
    Definition N3_to_lt3 (n: N3) : less_than_3 :=
    match n with
      | zero => exist _ 0 erefl
      | one => exist _ 1 erefl
      | two => exist _ 2 erefl
    end.
    
    Lemma eq_lt3_lt3 (x: less_than_3) : eq x (N3_to_lt3 (lt3_to_N3 x)).
    Proof.
    by apply: val_inj; case: x => [[| [|[|x]]] Px].
    Qed.
    

    val_inj 的声明有点复杂,但基本思想很简单:对于类型 T 上的任何布尔谓词 P,规范投影 { x : T | P x = true } -&gt; T 是单射的。正如 Vinz 所说,这依赖于证明不相关的布尔等式;也就是说,布尔值之间相等的任何两个证明本身都是相等的。因此,{x | P x = true} 上的相等性完全由元素 x 决定;证明部分无关紧要。

    【讨论】:

    • 我建议在ssrflect中使用bijective的定义,这又依赖于cancel
    【解决方案3】:

    我会从类似的东西开始

    Definition eq_lt3_lt3 (x: lt3) : eq x (N3_to_lt3 (lt3_to_N3 x)).
    Proof.
    destruct x as [ n h ].
    destruct n as [ | [ | [ | p ]]]; simpl in *.
    

    此时您将拥有如下目标:

    exist (fun x : nat => x < 3) 0 h = exist (fun x : nat => x < 3) 0 l_0_3
    

    基本上,现在唯一的区别是左侧有“0 h 的一些证明”,右侧有“0 l_0_3 的确切证明”。

    因此,您必须研究证明无关/身份证明的唯一性(可通过 nat & lt 证明)。

    【讨论】:

    • 由于您似乎使用 ssreflect,我记得 std lib 中有一些东西可以解决这个问题,但我不记得确切的名称......
    • 我已经尝试过这样做,现在,将唯一性声明为公理:pastebin.com/x3CgPUSH。证明似乎是正确的,但我最终发现自己陷入了困境。 Coq 要求我证明exist (fun x : nat =&gt; x &lt; 3) (S (S (S p))) h = exist (fun x : nat =&gt; x &lt; 3) 2 l_2_3,但这是不可能的情况。我该如何解决?
    • 你的假设没有矛盾吗?在最后一种情况下,您应该有类似h : S (S (S p)) &lt; 3 的东西。我很确定你知道如何为这个声明推导出 False ;)
    • 关于唯一性部分,您可以查看Peano_dec 模块中的le_unique
    • 谢谢,我终于明白了!
    猜你喜欢
    • 1970-01-01
    • 2020-03-18
    • 1970-01-01
    • 2013-10-10
    • 2012-03-28
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多