coq - 如何证明偏序归纳谓词的可判定性?

标签 coq proof deterministic formal-verification partial-ordering

上下文

我试图用 Coq 中的关系 le 定义偏序 A ≤ B ≤ C 并证明它是可判定的:forall x y, {le x y} + {~le x y}.

我通过等效的 bool 函数 leb 成功地做到了这一点,但找不到直接证明它的方法(或该母校的 le_antisym)。我陷入了以下情况:

1 subgoal
H : le C A
______________________________________(1/1)
False

问题

  1. 我如何证明 le C A 是一个假前提?
  2. 还有其他我应该使用的证明策略吗?
  3. 我应该以不同的方式定义我的谓词 le 吗?

最小的可执行示例

Require Import Setoid.

Ltac inv H := inversion H; clear H; subst.

Inductive t : Set := A | B | C.

Ltac destruct_ts :=
  repeat match goal with
  | [ x : t |- _ ] => destruct x
  end.

Inductive le : t -> t -> Prop :=
  | le_refl : forall x, le x x
  | le_trans : forall x y z, le x y -> le y z -> le x z
  | le_A_B : le A B
  | le_B_C : le B C .

Definition leb (x y : t) : bool :=
  match x, y with
  | A, _ => true
  | _, C => true
  | B, B => true
  | _, _ => false
  end.

Theorem le_iff_leb : forall x y,
  le x y <-> leb x y = true.
Proof.
  intros x y. split; intro H.
  - induction H; destruct_ts; simpl in *; congruence.
  - destruct_ts; eauto using le; simpl in *; congruence.
Qed.

Theorem le_antisym : forall x y,
  le x y -> le y x -> x = y.
Proof.
  intros x y H1 H2.
  rewrite le_iff_leb in *. (* How to prove that without using [leb]? *)
  destruct x, y; simpl in *; congruence.
Qed.

Theorem le_dec : forall x y, { le x y } + { ~le x y }.
  intros x y.
  destruct x, y; eauto using le.
  - apply right.
    intros H. (* Stuck here *)
    inv H.
    rewrite le_iff_leb in *.
    destruct y; simpl in *; congruence.
  - apply right.
    intros H; inv H. (* Same thing *)
    rewrite le_iff_leb in *.
    destruct y; simpl in *; congruence.
  - apply right.
    intros H; inv H. (* Same thing *)
    rewrite le_iff_leb in *.
    destruct y; simpl in *; congruence.
Qed.

最佳答案

le 的问题在于传递性构造函数:当对 le x y 的证明进行反演或归纳时,我们对来自传递性案例,这通常会导致证明尝试失败。您可以使用关系的另一种(但仍然是归纳的)表征来证明您的结果:

Require Import Setoid.

Ltac inv H := inversion H; clear H; subst.

Inductive t : Set := A | B | C.

Inductive le : t -> t -> Prop :=
  | le_refl : forall x, le x x
  | le_trans : forall x y z, le x y -> le y z -> le x z
  | le_A_B : le A B
  | le_B_C : le B C .

Inductive le' : t -> t -> Prop :=
  | le'_refl : forall x, le' x x
  | le'_A_B  : le' A B
  | le'_B_C  : le' B C
  | le'_A_C  : le' A C.

Lemma le_le' x y : le x y <-> le' x y.
Proof.
  split.
  - intros H.
    induction H as [x|x y z xy IHxy yz IHyz| | ]; try now constructor.
    inv IHxy; inv IHyz; constructor.
  - intros H; inv H; eauto using le.
Qed.

Theorem le_antisym : forall x y,
  le x y -> le y x -> x = y.
Proof.
  intros x y.
  rewrite 2!le_le'.
  intros []; trivial; intros H; inv H.
Qed.

Theorem le_dec : forall x y, { le x y } + { ~le x y }.
  intros x y.
  destruct x, y; eauto using le; right; rewrite le_le';
  intros H; inv H.
Qed.

然而,在这种情况下,我认为使用 le 的归纳表征并不是一个好主意,因为 bool 版本更有用。自然,在某些情况下,您希望对关系进行两种表征:例如,有时您希望对类型的相等性进行 bool 测试,但希望使用 = 进行重写。 ssreflect proof language使这种风格的工作变得容易。例如,这是您第一次尝试证明的另一个版本。 (reflect P b 谓词意味着命题 P 等价于断言 b = true。)

From mathcomp Require Import ssreflect ssrfun ssrbool.

Inductive t : Set := A | B | C.

Inductive le : t -> t -> Prop :=
  | le_refl : forall x, le x x
  | le_trans : forall x y z, le x y -> le y z -> le x z
  | le_A_B : le A B
  | le_B_C : le B C .

Definition leb (x y : t) : bool :=
  match x, y with
  | A, _ => true
  | _, C => true
  | B, B => true
  | _, _ => false
  end.

Theorem leP x y : reflect (le x y) (leb x y).
Proof.
apply/(iffP idP); first by case: x; case y=> //=; eauto using le.
by elim=> [[]| | |] //= [] [] [].
Qed.

Theorem le_antisym x y : le x y -> le y x -> x = y.
Proof. by case: x; case: y; move=> /leP ? /leP ?. Qed.

Theorem le_dec : forall x y, { le x y } + { ~le x y }.
Proof. by move=> x y; case: (leP x y); eauto. Qed.

关于coq - 如何证明偏序归纳谓词的可判定性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50390613/

相关文章:

coq - Coq 中的术语 "10"到底是什么?

math - 解释 Vinay Deolalikar 的证明 P != NP

algorithm - 二叉树的实现

haskell - Liquid Haskell 的简单一致性证明错误 - 液体类型不匹配

c - 什么会导致程序中的非确定性输出?

coq - Coq 的子类型

monads - 在 Coq 中证明延续传递式 Monad

coq - 在 Coq 中添加新符号时出现问题

Java 的序列化对象表示

c++ - UB 能否导致多个单线程应用程序运行产生不同的输出?