Coq归纳谓词归纳规则中的抽象模式

Coq归纳谓词归纳规则中的抽象模式,coq,Coq,考虑Coq中的以下命题: Inductive subseq : list nat -> list nat -> Prop := | nil_s : forall (l: list nat), subseq nil l | cons_in l1 l2 x (H: subseq l1 l2) : subseq (x :: l1) (x :: l2) | cons_nin l1 l2 x (H: subseq l1 l2) : subseq l1 (x :: l2) . Lemm

考虑Coq中的以下命题:

Inductive subseq : list nat -> list nat -> Prop :=
 | nil_s : forall (l: list nat), subseq nil l 
 | cons_in l1 l2 x (H: subseq l1 l2) : subseq (x :: l1) (x :: l2)
 | cons_nin l1 l2 x (H: subseq l1 l2) : subseq l1 (x :: l2)
.

Lemma subseq_remove_rewritten: forall (x:nat) (l1' l1 l2 : list nat),
  subseq l1' l2 ->
  l1' = (x :: l1) ->
  subseq l1 l2.
Proof. 
  intros x l1' l1 l2 H1 H2.
  induction H1.
  - discriminate.
  - injection H2 as H3 H4.
    rewrite H4 in H1.
    apply cons_nin. apply H1.
  - apply IHsubseq in H2.
    apply cons_nin. apply H2.
Qed.

Lemma subseq_remove: forall (x:nat) (l1 l2 : list nat),
  subseq (x :: l1) l2 ->
  subseq l1 l2.
Proof. 
  intros x l1 l2 H. 
  apply subseq_remove_rewritten with (x:=x) (l1':=x :: l1).
  apply H.
  reflexivity.
Qed.
我在科克之前在伊莎贝尔工作过。最初,归纳法无法直接解决这一目标,而诀窍是提出一个类似subseq_remove_重写的引理,然后证明原始目标。这是手册Isabelle/HOL中的情况:高阶逻辑的证明助手。后来,这一策略变得更加聪明,人们可以编写用于抽象的模式。所以证据是这样写的:

lemma 
  assumes "subseq (x # l1) l2"
  shows "subseq l1 l2"
  using assms
  apply(induction "x # l1" "l2" rule: subseq.induct)
    apply simp
   apply(intro subseq.intros(3),simp)
  by (intro subseq.intros(3))

我想知道Coq是否有类似的方法来避免证明像subseq_remove_重写的引理,直接去证明subseq_remove

您可以使用
依赖诱导
策略(有文档记录)。例如:

Require Import Coq.Lists.List.
Import ListNotations.
Require Import Coq.Program.Equality. (* Needed to use the tactic *)

Inductive subseq : list nat -> list nat -> Prop :=
 | nil_s : forall (l: list nat), subseq nil l
 | cons_in l1 l2 x (H: subseq l1 l2) : subseq (x :: l1) (x :: l2)
 | cons_nin l1 l2 x (H: subseq l1 l2) : subseq l1 (x :: l2)
.

Lemma subseq_remove: forall (x:nat) (l1 l2 : list nat),
  subseq (x :: l1) l2 ->
  subseq l1 l2.
Proof.
  intros x l1 l2 H.
  dependent induction H generalizing x.
  - now apply cons_nin.
  - eauto using cons_nin.
Qed.
Require Import Coq.Lists.List.
Import ListNotations.

Fixpoint subseq (l1 l2 : list nat) : Prop :=
  match l1, l2 with
  | [], _ => True
  | x1 :: l1, [] => False
  | x1 :: l1, x2 :: l2 => x1 = x2 /\ subseq l1 l2 \/ subseq (x1 :: l1) l2
  end.

Lemma subseq_nin x2 l1 l2 : subseq l1 l2 -> subseq l1 (x2 :: l2).
Proof. destruct l1 as [|x1 l1]; simpl; eauto. Qed.

Lemma subseq_remove: forall (x:nat) (l1 l2 : list nat),
  subseq (x :: l1) l2 ->
  subseq l1 l2.
Proof.
  intros x l1 l2 H.
  induction l2 as [|x2 l2 IH]; try easy.
  destruct H as [[<- H]|H]; eauto using subseq_nin.
Qed.
不幸的是,尽管这种策略已经存在了一段时间,但在参考手册中仍然被描述为实验性的,我不知道Coq开发人员将来是否有任何改进的计划。它有一些不足之处,例如不允许用户命名归纳证明中使用的变量和假设。我个人更喜欢将等式假设添加到证明中,就像您第一次尝试一样,或者将
subseq
的定义重新表述为
固定点
,这样您就可以通过简化来反转假设。例如:

Require Import Coq.Lists.List.
Import ListNotations.
Require Import Coq.Program.Equality. (* Needed to use the tactic *)

Inductive subseq : list nat -> list nat -> Prop :=
 | nil_s : forall (l: list nat), subseq nil l
 | cons_in l1 l2 x (H: subseq l1 l2) : subseq (x :: l1) (x :: l2)
 | cons_nin l1 l2 x (H: subseq l1 l2) : subseq l1 (x :: l2)
.

Lemma subseq_remove: forall (x:nat) (l1 l2 : list nat),
  subseq (x :: l1) l2 ->
  subseq l1 l2.
Proof.
  intros x l1 l2 H.
  dependent induction H generalizing x.
  - now apply cons_nin.
  - eauto using cons_nin.
Qed.
Require Import Coq.Lists.List.
Import ListNotations.

Fixpoint subseq (l1 l2 : list nat) : Prop :=
  match l1, l2 with
  | [], _ => True
  | x1 :: l1, [] => False
  | x1 :: l1, x2 :: l2 => x1 = x2 /\ subseq l1 l2 \/ subseq (x1 :: l1) l2
  end.

Lemma subseq_nin x2 l1 l2 : subseq l1 l2 -> subseq l1 (x2 :: l2).
Proof. destruct l1 as [|x1 l1]; simpl; eauto. Qed.

Lemma subseq_remove: forall (x:nat) (l1 l2 : list nat),
  subseq (x :: l1) l2 ->
  subseq l1 l2.
Proof.
  intros x l1 l2 H.
  induction l2 as [|x2 l2 IH]; try easy.
  destruct H as [[<- H]|H]; eauto using subseq_nin.
Qed.
需要导入Coq.Lists.List。
导入列表符号。
固定点水下(l1 l2:列表nat):道具:=
将l1、l2与
|[],\uU9=>True
|x1::l1,[]=>错误
|x1::l1,x2::l2=>x1=x2/\subseq l1 l2\/subseq(x1::l1)l2
结束。
x2 l1 l2中的引理subseq_:subseq l1 l2->subseq l1(x2::l2)。
证明。将l1分解为[| x1 l1];单纯形;奥托。Qed。
引理subseq_remove:forall(x:nat)(l1-l2:list-nat),
水下(x::l1)l2->
水下l1和l2。
证明。
简介x l1 l2 H。
诱导l2为[| x2 l2 IH];别着急。
自毁[[