在 mathcomp 的 ssralg 中从 int_Ring 类型中提取整数

Extracting integer from int_Ring type in mathcomp's ssralg

问题的一些设置:符号 `_i 被定义为序列的 i-th 分量,但也意味着 i-th 系数一个多项式。以下代码输出 Negz 2 : int_ZmodType:

From mathcomp Require Import all_ssreflect.
From mathcomp Require Import all_algebra.
Open Scope ring_scope.
Definition my_seq := [:: Posz 4; Negz 2].
Eval compute in my_seq`_1.

my_seq的类型是seq int。类型 int 具有构造函数 PoszNegz.

的header https://github.com/math-comp/math-comp/blob/master/mathcomp/algebra/poly.v 告诉我们 Poly s 是一个系数来自序列 s 的多项式。它还表示 p`_i 是多项式 p 的 i-th 系数。我希望以下代码输出 Negz 2:

Definition my_polynomial := Poly my_seq.
Eval compute in my_polynomial`_1.

结果项不是 Negz 2,尽管它确实具有类型 int_Ring。多项式有一个序列构造函数 polyseq。事实上,polyseq my_polynomial 的类型是 seq int_Ring。然而,做 Eval compute in (polyseq my_polynomial)`_1. 会产生同样的混乱。

在从具体类型 intint_Ring 的转换中,整数的值是否丢失了?或者,有没有办法从 int_Ring 恢复 int 的值? int_Ring 的打包方式,看起来不太可能,因为构造函数不引用元素。但是,int_ZmodType 也是如此。作为参考,这些类型在

中定义

https://github.com/math-comp/math-comp/blob/master/mathcomp/algebra/ssralg.v

这是您的代码的一个版本:

From mathcomp Require Import all_ssreflect.
From mathcomp Require Import all_algebra.
Open Scope ring_scope.
Definition my_seq := [:: Posz 4; Negz 2].
Definition my_poly := @Polynomial _ my_seq erefl.
Compute my_poly`_1.

此版本没有使用库中定义的更简单的 Poly 包装函数,而是直接调用 polynomial 的构造函数。如果你看一下这种类型的定义,你会发现多项式只是一个包含多项式系数序列的记录,加上一个布尔等式的证明,断言这个序列的最后一个元素(前导系数)不为零。 (上面表达式中的第二个参数是 true = true 的证明,根据计算规则,Coq 将其理解为 (last 1 polyseq != 0) = true 的证明。)你可以手动检查那里没有什么能阻止我们计算的表达式减少,所以 Coq 能够找出答案。

要看你原来的尝试有什么问题,我们得稍微展开一下。我在这里按顺序包含了相关定义,扩展了一些符号:

Poly s := foldr cons_poly (polyC 0)

polyC c := insubd poly_nil [:: c]

(* from eqtype.v *)
insubd {T : Type} {P : pred T} {sT : subType T P} u0 (x : T) : sT := 
  odflt u0 (insub x)

insub {T : Type} {P : pred T} {sT : subType T P} (x : T) : option sT 
  := if @idP (P x) is ReflectT Px then @Some sT (Sub x Px) else None

这里我们找到了罪魁祸首:Poly 是根据 insub 定义的,而 insub 又是由 idP 上的案例分析定义的,这是一个不透明的引理!当一个不透明的术语妨碍时,Coq 的归约就会停滞不前。 (如果你很好奇,这里发生的是 insub 正在测试,使用 idP,多项式的前导系数是否确实不为零,如果是,则使用该事实构建多项式。)

问题在于 ssreflect 中的许多定义并未在逻辑内部进行完全计算。这是由于两个原因。一是性能:通过允许一切都完全减少,我们可以使类型检查慢得多。另外一个就是ssreflect是为了方便推理而剪裁的,所以很多定义并不是最高效的。 CoqEAL 库的开发是为了将具有更好计算行为的定义与更容易推理的定义联系起来,例如 ssreflect;不幸的是,我不知道该项目是否还在维护。

这并没有完全回答问题,但我设法证明了系数确实是Negz 2。我在这里给出证明以供记录。请注意,我对 ssreflect 一点都不熟悉,所以可能会有更好更自然的方法来做到这一点。

From mathcomp Require Import all_ssreflect.
From mathcomp Require Import all_algebra.
Open Scope ring_scope.
Definition my_seq := [:: Posz 4; Negz 2].
Eval compute in my_seq`_1.

Definition my_polynomial := Poly my_seq.

Example test : my_polynomial `_1 = Negz 2.
Proof.
  cbn.
  rewrite 2!polyseq_cons. cbn.
  rewrite 2!size_polyC. cbn.
  rewrite polyseqC. cbn. reflexivity.
Qed.

编辑:如以下评论所述,存在更简单的证据证明这一事实。