如何将可传递关系从元素提升到列表?

时间:2018-10-24 06:45:15

标签: isabelle theorem-proving

我试图证明列表元素上的传递关系等同于列表上的传递关系(在某些情况下)。

这是第一个引理:

lemma list_all2_rtrancl1:
  "(list_all2 P)⇧*⇧* xs ys ⟹
   list_all2 P⇧*⇧* xs ys"
  apply (induct rule: rtranclp_induct)
  apply (simp add: list.rel_refl)
  by (smt list_all2_trans rtranclp.rtrancl_into_rtrancl)

这是一个对称引理:

lemma list_all2_rtrancl2:
  "(⋀x. P x x) ⟹
   list_all2 P⇧*⇧* xs ys ⟹
   (list_all2 P)⇧*⇧* xs ys"
  apply (erule list_all2_induct)
  apply simp

我想一个关系应该是自反的。但是也许我应该使用另一个假设。假设P是可传递的,但是P不是可传递的,则可以证明引理。我被卡住了。您能否建议选择哪些假设以及如何证明这一引理?

似乎nitpick给了我关于最后一个引理(xs = [0]ys = [2])的特定情况的错误反例:

lemma list_all2_rtrancl2_example:
  "list_all2 (λx y. x = y ∨ Suc x = y)⇧*⇧* xs ys ⟹
   (list_all2 (λx y. x = y ∨ Suc x = y))⇧*⇧* xs ys"
  nitpick

我可以证明该示例成立了引理:

lemma list_all2_rtrancl2_example_0_2:
  "list_all2 (λx y. x = y ∨ Suc x = y)⇧*⇧* [0] [2] ⟹
   (list_all2 (λx y. x = y ∨ Suc x = y))⇧*⇧* [0] [2]"
  apply (rule_tac ?b="[1]" in converse_rtranclp_into_rtranclp; simp)
  apply (rule_tac ?b="[2]" in converse_rtranclp_into_rtranclp; simp)
  done

1 个答案:

答案 0 :(得分:1)

使用listrel代替list_all2是可行的。实际上,如下所示,它们是等效的(请参见set_listrel_eq_list_all2)。但是,标准库中关于listrel的几个定理没有与list_all2等效的定理。


theory so_htlatrfetl_2
  imports Complex_Main
begin

lemma set_listrel_eq_list_all2: 
  "listrel {(x, y). r x y} = {(xs, ys). list_all2 r xs ys}"
  using list_all2_conv_all_nth listrel_iff_nth by fastforce

lemma listrel_tclosure_1: "(listrel r)⇧* ⊆ listrel (r⇧*)"
  by (simp add: listrel_rtrancl_eq_rtrancl_listrel1 
      listrel_subset_rtrancl_listrel1 rtrancl_subset_rtrancl)

lemma listrel_tclosure_2: "refl r ⟹ listrel (r⇧*) ⊆ (listrel r)⇧*"
  by (simp add: listrel1_subset_listrel listrel_rtrancl_eq_rtrancl_listrel1 
      rtrancl_mono)

context includes lifting_syntax
begin

lemma listrel_list_all2_transfer [transfer_rule]:
  "((=) ===> (=) ===> (=) ===> (=)) 
  (λr xs ys. (xs, ys) ∈ listrel {(x, y). r x y}) list_all2"
  unfolding rel_fun_def using set_listrel_eq_list_all2 listrel_iff_nth by blast

end

lemma list_all2_rtrancl_1:
  "(list_all2 r)⇧*⇧* xs ys ⟹ list_all2 r⇧*⇧* xs ys"
proof(transfer)
  fix r :: "'a ⇒ 'a ⇒ bool"
  fix xs :: "'a list"
  fix ys:: "'a list"
  assume "(λxs ys. (xs, ys) ∈ listrel {(x, y). r x y})⇧*⇧* xs ys"
  then have "(xs, ys) ∈ (listrel {(x, y). r x y})⇧*"
    unfolding rtranclp_def rtrancl_def by auto  
  then have "(xs, ys) ∈ listrel ({(x, y). r x y}⇧*)" 
    using listrel_tclosure_1 by auto
  then show "(xs, ys) ∈ listrel {(x, y). r⇧*⇧* x y}"
    unfolding rtranclp_def rtrancl_def by auto  
qed

lemma list_all2_rtrancl_2:
  "reflp r ⟹ list_all2 r⇧*⇧* xs ys ⟹ (list_all2 r)⇧*⇧* xs ys"
proof(transfer)
  fix r :: "'a ⇒ 'a ⇒ bool"
  fix xs :: "'a list"
  fix ys :: "'a list"
  assume as_reflp: "reflp r" 
  assume p_in_lr: "(xs, ys) ∈ listrel {(x, y). r⇧*⇧* x y}"
  from as_reflp have refl: "refl {(x, y). r x y}" 
    using reflp_refl_eq by fastforce
  from p_in_lr have "(xs, ys) ∈ listrel ({(x, y). r x y}⇧*)"
    unfolding rtranclp_def rtrancl_def by auto
  with refl have "(xs, ys) ∈ (listrel {(x, y). r x y})⇧*"
    using listrel_tclosure_2 by auto
  then show "(λxs ys. (xs, ys) ∈ listrel {(x, y). r x y})⇧*⇧* xs ys" 
    unfolding rtranclp_def rtrancl_def by auto
qed

end

还提供了list_all2的直接证明(传统):

  1. list_all2_induct应用于列表;基本情况是微不足道的。因此,如果(L P)* x#xs y#ys(L (P*)) xs ys(L P)* xs ysP* x y,则仍然显示为zs
  2. 想法是可以找到xs(L P) xs zs这样的(L P)+ zs ys(例如P* x y)。
  3. 然后,根据P x xP*的传递特性,通过归纳法(L P) x#xs y#zs(L P)* x#xs y#zs。因此,(L P)+ zs ys也是如此。
  4. 另外,假设有P y y(L P)+ y#zs y#ys,归纳为(L P)* y#zs y#ys。因此,(L P)* x#xs y#ys也是如此。
  5. 从3和4得出theory so_htlatrfetl imports Complex_Main begin lemma list_all2_rtrancl2: assumes as_r: "(⋀x. P x x)" shows "(list_all2 P⇧*⇧*) xs ys ⟹ (list_all2 P)⇧*⇧* xs ys" proof(induction rule: list_all2_induct) case Nil then show ?case by simp next case (Cons x xs y ys) show ?case proof - from as_r have lp_xs_xs: "list_all2 P xs xs" by (rule list_all2_refl) from Cons.hyps(1) have x_xs_y_zs: "(list_all2 P)⇧*⇧* (x#xs) (y#xs)" proof(induction rule: rtranclp_induct) case base then show ?case by simp next case (step y z) then show ?case proof - have rt_step_2: "(list_all2 P)⇧*⇧* (y#xs) (z#xs)" by (rule r_into_rtranclp, rule list_all2_Cons[THEN iffD2]) (simp add: step.hyps(2) lp_xs_xs) from step.IH rt_step_2 show ?thesis by (rule rtranclp_trans) qed qed from Cons.IH have "(list_all2 P)⇧*⇧* (y#xs) (y#ys)" proof(induction rule: rtranclp_induct) case base then show ?case by simp next case (step ya za) show ?case proof - have rt_step_2: "(list_all2 P)⇧*⇧* (y#ya) (y#za)" by (rule r_into_rtranclp, rule list_all2_Cons[THEN iffD2]) (simp add: step.hyps(2) as_r) from step.IH rt_step_2 show ?thesis by (rule rtranclp_trans) qed qed with x_xs_y_zs show ?thesis by simp qed qed end

nitpick

作为一个旁注,我认为(我对nitpick知之甚少),nitpick不应在没有任何警告的情况下提供无效的反例。我相信,通常,当0.9.7i“怀疑”反例可能无效时,它会通知用户该例“可能是虚假的”。如果尚未在其他地方记录此问题,则提交错误报告可能会很有用。