【问题标题】:How to prove decidability of a partial order inductive predicate?如何证明偏序归纳谓词的可判定性?
【发布时间】:2023-07-09 21:46:01
【问题描述】:

上下文

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

我通过等效的布尔函数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.

【问题讨论】:

  • 为什么称其为部分排序?有三个元素 A |乙| C,它们完全有序。
  • 这是我能想到的最简单的例子,但我正在处理的关系不是总订单,所以我不希望有人根据订单是总计。

标签: coq proof deterministic formal-verification partial-ordering


【解决方案1】:

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 的归纳表征不是一个好主意,因为布尔版本更有用。自然,在某些情况下,您希望对关系进行两种表征:例如,有时您希望对类型进行相等性的布尔测试,但希望使用= 进行重写。 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.

【讨论】:

  • 用完全相同的le'打败我。
  • @Yves 只是在这里和那里做了。
  • 那么le'基本上是列举了leb中的模式匹配处理的情况?它不会导致元素数量 n 的许多情况 O(n) 吗?我希望通过摆脱leb来避免它...
  • @authchir 是的,它就是这样做的。我认为您无法避免这种增长。如果你要概括le,你仍然需要至少提到每个构造函数一次。
【解决方案2】:

我也会选择 Arthur 的解决方案。但让我演示另一种方法。

首先,我们需要几个支持引理:

Lemma not_leXA x : x <> A -> ~ le x A.
Proof. remember A; intros; induction 1; subst; firstorder congruence. Qed.

Lemma not_leCX x : x <> C -> ~ le C x.
Proof. remember C; intros; induction 1; subst; firstorder congruence. Qed.

现在我们可以定义le_dec

Definition le_dec x y : { le x y } + { ~le x y }.
Proof.
  destruct x, y; try (left; abstract constructor).
  - left; abstract (eapply le_trans; constructor).
  - right; abstract now apply not_leXA.
  - right; abstract now apply not_leCX.
  - right; abstract now apply not_leCX.
Defined.

请注意,我使用了Defined 而不是Qed——现在您可以使用le_dec 进行计算,这通常是使用sumbool 类型的重点。

我还使用abstract 向评估者隐藏了证明条款。例如。假设我定义了一个与le_dec 相同的le_dec' 函数,但删除了所有abstract,那么在尝试计算le_dec B A / le_dec' B A 时会得到以下结果:

Compute le_dec B A.
(* ==> right le_dec_subproof5 *) 

Compute le_dec' B A.
(* ==> right
     (not_leXA B
        (fun x : B = A =>
         match x in (_ = x0) return (x0 = A -> False) with
         | eq_refl =>
             fun x0 : B = A =>
             match
               match
                 x0 in (_ = x1)
                 return match x1 with
                        | B => True
                        | _ => False
                        end
               with
               | eq_refl => I
               end return False
             with
             end
         end eq_refl)) *)

【讨论】:

    【解决方案3】:

    请注意,您可以使用Relations 中的定义来定义您的订单关系。例如,它包含一个名为clos_refl_trans 的自反和传递闭包的定义。结果证明类似于基于您的定义的证明(参见@Anton 的回答)。

    Require Import Relations.
    
    Inductive t : Set := A | B | C.
    
    Inductive le : t -> t -> Prop :=
      | le_A_B : le A B
      | le_B_C : le B C.
    
    Definition le' := clos_refl_trans _ le.
    
    Lemma A_minimal : forall x, x <> A -> ~ le' x A.
    Proof.
      intros. intros contra. remember A as a. induction contra; subst.
      - inversion H0.
      - contradiction.
      - destruct y; apply IHcontra2 + apply IHcontra1; congruence.
    Qed.
    
    Lemma C_maximal : forall x, x <> C -> ~ le' C x.
    Proof.
      intros. intros contra. remember C as c. induction contra; subst.
      - inversion H0.
      - contradiction.
      - destruct y; apply IHcontra2 + apply IHcontra1; congruence.
    Qed.
    
    Lemma le'_antisym : forall x y,
      le' x y -> le' y x -> x = y.
    Proof.
      intros. induction H.
      - destruct H.
        + apply A_minimal in H0; try discriminate. contradiction.
        + apply C_maximal in H0; try discriminate. contradiction.
      - reflexivity.
      - fold le' in *. rewrite IHclos_refl_trans1 by (eapply rt_trans; eassumption).
        apply IHclos_refl_trans2; (eapply rt_trans; eassumption).
    Qed.
    

    【讨论】: