Coq中的分离三段论策略?

时间:2018-10-20 23:11:24

标签: coq coq-tactic

我正在学习命题逻辑和推理规则。 “析取三段论”规则指出,如果我们在我们的前提中有(P或Q),也有(不是P);然后我们可以到达Q。

我无法为自己的一生弄清楚如何在Coq中做到这一点。假设我有:

// XML document that we want to modify
let xml = "<foo><button/></foo>"

// Parse XML document
guard let document = try? XMLDocument(xmlString: xml, options: .documentValidate) else {
    return
}

// Find all the buttons
let buttons = try? document.nodes(forXPath: "//button")

// Modify the buttons by adding custom attributes
buttons?.compactMap({ $0 as? XMLElement }).forEach {
    $0.setAttributesWith([
        "customClass": "AmazingButton",
        "customModule": "IBComponents",
        "customModuleProvider": "target"
    ])
}

// Print modified XML document
print(document.xmlString)

我应该使用哪种策略

<?xml version="1.0" encoding="UTF-8"?><foo><button customModuleProvider="target" customModule="IBComponents" customClass="AmazingButton"></button></foo>

另外,如果有人可以与我分享Coq战术上的基本推理规则(例如惯用语收费或析取性介绍等),我会很高兴。也许我可以使用一个插件吗?

3 个答案:

答案 0 :(得分:3)

Coq没有内置此策略,但是幸运的是您可以定义自己的策略。注意

destruct H as [H1 | H1]; [contradiction |].

按照您的要求在上下文中放入H1 : B。因此,您可以为此组合策略创建别名:

Ltac disj_syllogism AorB notA B :=
  destruct AorB as [? | B]; [contradiction |].

现在,我们可以像这样轻松地模仿析取三段论规则:

Section Foo.
Context (A B : Prop) (H : A \/ B) (H0 : ~ A).
Goal True.
  disj_syllogism H H0 H1.
End Foo.

让我展示一些自动化程度较低的方法:

Ltac disj_syllogism AorB notA B :=
  let A := fresh "A" in
  destruct AorB as [A | B]; [contradiction (notA A) |].

这种方法不要求Coq找到矛盾,而是直接将其提供给contradiction策略(notA A术语)。或者我们可以在pose proof策略中使用明确的术语:

Ltac disj_syllogism AorB notA B :=
  pose proof (match AorB with
              | or_introl a => False_ind _ (notA a)
              | or_intror b => b
              end) as B.

我希望这会有所帮助。我不确定是否需要其他解释-请随时进行澄清,我将更新答案。

答案 1 :(得分:0)

基于安东·特鲁诺夫(Anton Trunov)的答案,“分离三段论”的简单版本如下:

(* Helper tactics. *) Ltac oe1 P_or_Q not_P := destruct P_or_Q ; [ contradiction | ]. Ltac oe2 P_or_Q not_Q := destruct P_or_Q ; [ | contradiction ].

(* Main tactic *) Ltac oE AorB H := oe1 AorB H || oe2 AorB H.

助手策略将根据False析取是在右边还是左边来处理一个案例,主要策略会同时尝试并返回成功者。

答案 2 :(得分:-1)

我认为您对Coq的工作方式可能抱有错误的期望?证明这一点的一般方法实质上是针对各种可能性的真值表:

Lemma it: forall a b, (a \/ b) /\ ~a -> b.
Proof.
  intuition.
  Show Proof.
Qed.

(fun (a b : Prop) (H : (a \/ b) /\ ~ a) =>
 and_ind
   (fun (H0 : a \/ b) (H1 : ~ a) =>
    or_ind (fun H2 : a => let H3 : False := H1 H2 in False_ind b H3)
      (fun H2 : b => H2) H0) H)

如果查看结果证明项,您会发现Coq本质上正在分解布尔型构造函数。我们可以手动执行此操作并获得相同的证明条件:

Lemma it: forall a b, (a \/ b) /\ ~a -> b.
Proof.
  intros a b H.
  induction H.
  induction H.
  contradict H. exact H0.
  exact H.
Qed.

例如惯用语对应于Coq中的apply,我认为这不是直接内置的。

然后,您可以使用此引理(并且我确定标准库中的某个位置有相应的版本)可以通过apply得出其他假设。