Coq:使用子类型卡住

时间:2018-07-23 01:06:24

标签: coq

我有以下定义:(将正整数定义为nat的子类型)

Definition Z_pos_filter (p: nat) : bool :=
  if (beq_nat p 0) then false else true.
Definition Z_pos: Set := {n : nat | is_true (Z_pos_filter n) }.

Definition Z_pos__N (p: Z_pos): nat := proj1_sig p.

Definition Z_pos_mult (p q: Z_pos): Z_pos.
destruct (Z_pos_filter (Z_pos__N p * Z_pos__N q)) eqn:prf.
- exact ((exist _ (Z_pos__N p * Z_pos__N q) prf)).
- assert (forall n: nat, S n <> 0) by (intros; omega).
  assert (forall a b: nat, a <> 0 /\ b <> 0 -> a * b <> 0).
  { intros. destruct a, b. omega. omega. omega. simpl. apply H. }
  assert (forall r: Z_pos, Z_pos__N r <> 0) by apply Z_pos_nonzero_N.
  assert (Z_pos__N p * Z_pos__N q <> 0) by (apply H0; split; apply H1).
  unfold Z_pos_filter in prf.
  rewrite <- beq_nat_false_iff in H2.
  rewrite H2 in prf. inversion prf.
Defined.

但是我坚持要证明Z_pos_mult与黑白乘法自然数兼容:

Lemma compat: forall p q: Z_pos, Z_pos__N (Z_pos_mult p q) = Z_pos__N p * Z_pos__N q.

我该如何解决?

3 个答案:

答案 0 :(得分:1)

您对Z_pos_mult的定义太复杂了。它依赖于依赖模式匹配 从一开始就对。我建议仅将这种依赖模式匹配用于证明,而不用于定义。

这是一个替代定义。并不是在进行任何证明之前就固定了返回值。

Definition Z_pos_mult (p q : Z_pos) : Z_pos.
exists (Z_pos__N p * Z_pos__N q).
destruct p as [p ph]; destruct q as [q qh].
unfold Z_pos_filter in ph, qh |- *; simpl.
destruct (p =? 0) eqn: ph'; try discriminate.
destruct (q =? 0) eqn: qh'; try discriminate.
rewrite beq_nat_false_iff in ph'.
rewrite beq_nat_false_iff in qh'.
destruct (p * q =? 0) eqn:pqh'; auto.
rewrite beq_nat_true_iff in pqh'.
destruct p; destruct q; try solve[discriminate | case ph'; auto | case qh'; auto].
Defined.

有了这个定义,您要求的证明就很容易编写。

Lemma compat: forall p q: Z_pos, Z_pos__N (Z_pos_mult p q) = Z_pos__N p * Z_pos__N q.
Proof.
intros [p ph] [q qh]; unfold Z_pos_mult; simpl; auto.
Qed.

原则上,也可以为您的代码提供证明,但这非常困难。

答案 1 :(得分:1)

恕我直言,以原始形式回答这个问题是在提倡一种可疑的风格。我认为此类数字的乘积应仅是基本类型的乘积。并且证明应仅从投影的内射性得出,就像在mathcomp中所做的那样。

通常,如果归约后在术语中出现非完全不透明的证明,您将遇到很多问题。

答案 2 :(得分:0)

这就是我在香草Coq中的做法。我假设我们仍然可以调整定义。

WITH
--  Select Features
    feat AS 
        (SELECT toid AS building_id,
                wkb_geometry AS geom 
                FROM buildings
        ),
    polygon_dump AS
        (SELECT (ST_DumpAsPolygons(ST_Clip(a.st_roughness,1,b.geom,-9999,true))).val AS polygon_vals,building_id AS building_id2
            FROM grosvenor_raster_roughness a, feat b
        ),
    threshold AS
        (SELECT building_id2 AS building_id, Count(*) AS thres_val
            FROM polygon_dump
                WHERE polygon_vals >= 0 AND polygon_vals < 0.5
        GROUP BY building_id2
        ),
    b_stats AS
        (SELECT  building_id, (stats).*
            FROM (SELECT building_id, ST_SummaryStats(ST_Clip(a.st_roughness,1,b.geom,-9999,true)) AS stats
                FROM grosvenor_raster_roughness a
                    INNER JOIN feat b
                ON ST_Intersects(b.geom,a.st_roughness)
            ) AS foo
        )
--  Summarise statistics
    SELECT count As pixel_count,
           thres_val AS threshold_val,
           cast(thres_val as real)/cast(count as real)*100 AS percent_value,
           min AS min_pixel_val,
           max AS max_pixel_val,
           mean AS avg_pixel_val,
           stddev AS pixel_stddev
        FROM b_stats
        JOIN threshold USING(building_id)
            WHERE count > 0;

让我补充一点,在SSReflect / Mathcomp中处理这种事情要愉快得多。