Как доказать разрешимость индуктивного предиката частичного порядка? - PullRequest
0 голосов
/ 17 мая 2018

Контекст

Я пытаюсь определить частичный порядок A ≤ B ≤ C с отношением le в Coq и доказать, что это разрешимо: 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.

Ответы [ 3 ]

0 голосов
/ 17 мая 2018

Я бы тоже согласился с решением Артура. Но позвольте мне продемонстрировать другой подход.

Для начала нам понадобится пара вспомогательных лемм:

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)) *)
0 голосов
/ 22 мая 2018

Обратите внимание, что вы можете использовать определения в Relations для определения отношения заказа.Например, оно содержит определение рефлексивного и транзитивного замыкания с именем clos_refl_trans.Полученные доказательства аналогичны тем, которые основаны на ваших определениях (см. Ответ Антона).

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.
0 голосов
/ 17 мая 2018

Проблема с 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 облегчает работу в этом стиле. Например, вот еще одна версия вашей первой попытки доказательства. (Предикат 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.
...