Coq学习——《Software-Foundation》Volume1.5-Tactics
Tactics
More tactics and more properties of functional programs.
- how to use auxiliary lemmas in both "forward-" and "backward-style" proofs; “正推”“逆推”中使用辅助引理;
- how to reason about data constructors -- in particular, how to use the fact that they are injective and disjoint; 如何对数据构造子进行论证,特别是,如何利用它们单射且不交的事实;
- how to strengthen an induction hypothesis, and when such strengthening is required; 如何增强归纳假设,以及何时需要增强;
- more details on how to reason by case analysis. 还有通过分类讨论进行论证的更多细节。
The [apply] Tactic
The goal to be proved is the same as some hypothesis in the context or some proved lemma, so we can apply them to finish the proof.
Finish with [apply H.] instead of [rewrite H. reflexivity.]
直接应用某条定理,而非重写后用 reflexivity.
1 |
|
When we [apply] some statements with \(\forall\), Coq will try to find appropriate values.
当我们应用 apply 定理的时候,Coq 会自动找寻符合定理的值,以下面为例:
1 |
|
这里我们使用 [apply H.] Coq 找到 [n=2]的实例,符合[H]定理要求,所以我们将结论转换为前提。
The [apply with] Tactic
Proof the theorem trans_eq first, and proof by using [apply trans_eq with (m:=[c;d])] (gives an instantiation of [X]). Trans_eq use abstract type so we can "with" the actual type.
Coq also has a tactic [transitivity] that accomplishes the same purpose as applying [trans_eq]. The tactic requires us to state the instantiation we want, just like [apply with] does.
Like:
1 |
|
The [injection] and [discriminate] Tactics
举自然数定义,性质:
- 构造子\(S\)是单射(Injective) 或“一一对应”的。即,如果\(S n = S m\),那么\(n=m\)必定成立。
- 构造子\(O\)和\(S\)是不相交(Disjoint)的。即,对于任何\(n\),\(O\)都不等于\(S n\)
可以用pred
推广到任意构造子上,编写撤销一次构造子调用的函数。为此,Coq 提供了更加简便的[injection] 策略,它能让我们利用构造子的单射性。
1 |
|
If you jest say [injection XX] with no [as] clause, then all the equations will be turned into hypotheses at the beginning of the goal. (We can follow with [intros] tactics).
one exercise
1 |
|
About disjointnesses.
Two terms beginning with different constructors (like [0] ans [S], or [true] and [false]) can never be equal.
Nonsensial to anything: Beginning with different constructors, any time we find ourselves in a context where we've assumed that two such terms are equal, we are justified in concluding anything we want.
The [discriminate] tactic embodies this principle: It is used on a hypothesis involving an equality between different constructors.
逻辑学原理“爆炸原理”,断言矛盾的前提会推出任何东西,甚至是假命题。
Example
1 |
|
The injectivity (one to one) allows us to use [f_equal] tactic to reason form like [n = m -> f x = f y].
Given a goal of the form [f a1 ... an = g b1 ... bn], the tactic [f_equal] will produce subgoals of the form [f = g], [a1 = b1], ..., [an = bn]. At the same time, any of these subgoals that are simple enough (e.g., immediately provable by [reflexivity]) will be automatically discharged by [f_equal].
Using Tactics on Hypotheses
Change the goal -> change the context.
For example, [simple in H], [apply L in H].
! [apply L in H]会针对 \(X\) 匹配 \(H\),如果成功,就将其替换为 \(Y\) 。换言之,
- [apply L in H] 给了我们一种“正向推理(forward reasoning)” :
- 根据 \(X \rightarrow Y\) 和一个匹配 \(X\) 的假设, 它会产生一个匹配 \(Y\) 的假设。
- Forward reasoning starts from what is given (premises, previously proven theorems) and iteratively draws conclusions from them until the goal is reached
- [apply L]是一种“反向推理”:
- 如果我们指导 \(X \rightarrow Y\) 并且试图证明 \(Y\), 那么证明 \(X\) 就足够了。
- Backward reasoning starts from the goal and iteratively reasons about what would imply the goal, until premises or previously proven theorems are reached.
数学或计算机科学课上见过的非形式化证明(informal proofs)可能倾向于正向推理。通常,Coq 习惯上倾向于使用反向推理,但在某些情况下,正向推理更易于思考。
Varying the Induction Hypothesis
变换归纳假设
[intros m] in the wrong places.
1 |
|
分析问题,由于我们已经通过[intros] 将 [m] 引入到上下文中。直观上我们告诉 Coq“现在开始考虑具体的[n]和[m]”,而在对[n]归纳证明时,[P n -> P ( S n )],对于具体[m]来说是没有意义的(useless)。
我们需求证明更一般的事情,(在后面才具体化[m])。
1 |
|
What's wrong in the second-second case.
Trying to carry out this proof by induction on [n] when [m] is already in the context doesn't work because we are then trying to prove a statement involving every [n] but just a single [m].
如果我们试着根据 Q 证明 R,就会以“假设 double (S n) = 10..”这样的句子开始, 不过之后我们就会卡住:知道 double (S n) 为 10 并不能告诉我们 double n 是否为 10。(实际上,它强烈地表示 double n '不是' 10!) 因此 Q 是没有用的。
1 |
|
We get a more general context.
1 |
|
What you should take away from all this is that we need to be careful, when using induction, that we are not trying to prove something too specific: When proving a property involving two variables [n] and [m] by induction on [n], it is sometimes crucial to leave [m] generic.
One of my exercises.
1 |
|
Another
1 |
|
Rearrangement of quantified variables
有时候需要对量化的变量做一下“重排”。
比如之前的double_injective
的证明,如果我们不引入任何东西就执行[induction m], Coq 就会自动帮我们引入 n。
What can we do?
- works but not nice: rewrite the statement of the lemma so that [m] is quantified before [n].
- work and nice: first intro duce all and then re-generalize one or more with tactic [generalize dependent].
An exercise
1 |
|
Unfolding Definitions
Manually unfold a name that has been introduced by a [Definition].
As for automatic unfolding (with tactic [simpl]), Coq is not smart enough...
Use [unfold] to explicitly tell Coq what to do.
1 |
|
As for automatic unfolding the definition, if [simpl] meet a function involving a pattern match with an application of an variable. It is not smart enough to notice whether the two branches of are identical or not.
Two ways to make progress
- Destruct the variable (depends on recognizing the dependencis)
- Tell Coq to unfold the function and show directly, and then ...
Using [destruct] on Compound Expressions
We have used this for the case analysis before.
About the [eqn:]!
When [destruct]ing compound expressions, the information recorded by the [eqn:] can actually be critical: if we leave it out, then [destruct] can erase information we need to complete a proof.
So becareful to add [eqn:] when destructing compound expressions.
exercise
1 |
|
Review
Review 部分摘录翻译版。
intros
:将前提/变量从证明目标移到上下文中reflexivity
:(当目标形如 e = e 时)结束证明apply
:用前提、引理或构造子证明目标apply... in H
:将前提、引理或构造子应用到上下文中的假设上(正向推理)apply... with...
:为无法被模式匹配确定的变量显式指定值simpl
:化简目标中的计算simpl in H
:化简前提中的计算rewrite
:使用相等关系假设(或引理)来改写目标rewrite ... in H
:使用相等关系假设(或引理)来改写前提symmetry
:将形如 t=u 的目标改为 u=tsymmetry in H
:将形如 t=u 的前提改为 u=tunfold
:用目标中的右式替换定义的常量unfold... in H
:用前提中的右式替换定义的常量destruct... as...
:对归纳定义类型的值进行情况分析destruct... eqn:...
:为添加到上下文中的等式指定名字, 记录情况分析的结果induction... as...
: 对归纳定义类型的值进行归纳injection
: reason by injectivity on equalities between values of inductively defined typesdiscriminate
: reason by disjointness of constructors on equalities between values of inductively defined typesassert (H: e)(或 assert (e) as H)
:引入“局部引理”e 并称之为 Hgeneralize dependent x
:将变量 x(以及任何依赖它的东西) 从上下文中移回目标公式内的前提中
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!