簡體   English   中英

堅持一個簡單引理的證明:我應該使用哪種歸納法?

[英]Stuck on the proof of a simple Lemma: which induction should I use?

我有以下結構:

Inductive instr : Set :=
 | Select    : nat -> instr
 | Backspace : instr.

Definition prog := list instr.

和以下功能:

Fixpoint Forward (input output: list nat) : option prog :=
match input with
  | nil => match output with
                 | nil => Some nil
                 | y::r => None
           end
  | x::rest => match output with
                | nil => match rest with
                            | nil => None   
                            | xx::rrest => match (Forward rrest nil) with
                                                            | Some pp => Some ((Select x) :: Backspace :: pp)
                                                            | None => None
                                           end
                         end
                | y::r => if ( beq_nat x y ) then match (Forward rest r) with
                                                   | Some pp => Some ((Select x) :: pp)
                                                   | None => None 
                                                   end
                          else match rest with
                                             | nil => None
                                             | xx::rrest => match (Forward rrest output) with
                                                                           | Some pp => Some ((Select x) :: Backspace :: pp)
                                                                           | None => None                                                                          
                                                            end
                                end

                end
end.

現在我想證明這個簡單的引理:

Lemma app_forward :
  forall (p p':prog) (input1 input2 output1 output2:list nat),
    Forward input1 output1 = Some p ->
        Forward input2 output2 = Some p' ->
           Forward (input1 ++ input2) (output1 ++ output2) = Some (p++p').

無論我使用什么歸納原理,我都被卡住了。 一定有一些我看不到的明顯的東西。 有人不能幫我證明這個嗎?

謝謝 !!

你的問題有兩個問題。 第一個是你要證明的陳述是假的,這里是一個反例的證明。

Lemma not_app_forward :
    not
      (forall (p p':prog) (input1 input2 output1 output2:list nat),
        Forward input1 output1 = Some p ->
            Forward input2 output2 = Some p' ->
               Forward (input1 ++ input2) (output1 ++ output2) = Some (p++p')).
Proof. 
intros abs.
assert (tmp := abs (Select 1 :: Backspace :: nil) (Select 1 :: Select 2 :: nil)
                   (1 :: 2 :: nil) (1 :: 2 :: nil) nil (1 :: 2 :: nil) refl_equal refl_equal).
compute in tmp.
discriminate.
Qed.

因此,與您的說法相反,這不是一個簡單的引理。

第二個問題是函數形狀復雜,歸納證明難以組織。 我將在下面介紹這方面。

從函數Forward的結構來看,您應該通過對input參數進行歸納來執行證明是很自然的,因為它是在子項上發生遞歸調用的參數。 然而,遞歸調用不僅發生在直接子項上(如Forward rest ... )而且還發生在子項的子項中(如Forward rrest ... ),這一事實使證明變得復雜。

有幾種方法可以解決這個困難,但都需要一些解釋或學習。

1 - 一種方法是使用 Coq 的Equations插件並使用 Equations 重新定義您的Forward函數。 然后,您可以使用功能歸納來解決您的問題:這將使用專門針對您的問題量身定制的歸納原則。

2 - 第二種方法是手動構建定制的感應原理。 這是一個嘗試。

Definition two_step_list_induction {A : Type} :
  forall (P : list A -> Prop),
    P nil ->
    (forall a, P (a :: nil)) ->
    (forall a b tl, 
        P (b :: tl) -> P tl -> P (a :: b :: tl)) ->
  forall l, P l.
Proof.
intros P Pn P1 Prec.
fix tsli 1.
intros [ | x l].
  exact Pn.
  generalize (tsli l).
  destruct l as [ | y tl]; intros Pl.
    exact (P1 x).
  apply Prec;[assumption | exact (tsli tl)].
Defined.

然后,您可以使用以下形狀的命令開始您的證明:

Lemma app_forward :
  forall (p p':prog) (input1 input2 output1 output2:list nat),
    Forward input1 output1 = Some p ->
        Forward input2 output2 = Some p' ->
           Forward (input1 ++ input2) (output1 ++ output2) = Some (p++p').
Proof.
intros p p' input1; revert p; induction input1 as [ | a | a b tl Ih1 Ih2]
  using two_step_list_induction.

但是,正如我已經說過的,你想要證明的引理實際上是錯誤的,所以這個證明永遠不會奏效,我也無法說明所提出的方法會奏效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM