■
assert form
ゴールを直接の証明が簡単には書けないので、とりあえず簡単に証明できる中間結果を教えるtactic。
ringとかomegaで一発で証明するには複雑すぎるときに、問題を二つに分けるとよいことがある。
中間結果 form を指定すると、サブゴールにformが追加されて、元のゴールにはformが仮定として追加される。
< Goal forall x y: Z, x>=0 -> x*x>y*y -> x-y>0. < intros. 1 subgoal x : Z y : Z H : x >= 0 H0 : x * x > y * y ============================ x - y > 0
ここで、定理 Zgt_square_simpl を使いたいわけだが、この定理は「x-y>0」ではなく「x>y」を導くものなので、直接は適用できない。そこで、assert を使って
Unnamed_thm < assert (x>y); auto with zarith. 1 subgoal x : Z y : Z H : x >= 0 H0 : x * x > y * y ============================ x > y
これで定理が使える形になったので、apply Zgt_square_simpl すれば証明が終わる。
assert (identifier:=term)
これは assert と exact を続けて実行したのと同じだが、論理式を書くのが億劫な場合に便利。
仮定に forall があって、それを例化した仮定を後でたくさん使いたいときに使うとよい。
H : forall x : nat, P x -> Q x -> R x y : nat ============================
たとえば上のような場合で、「P y -> Q y -> R y」は導けるので
H : forall x : nat, P x -> Q x -> R x y : nat Hy : P y -> Q y -> R y ============================
としておけば、後で Hy を何度も使う場合は便利である。この状態にもっていくのに普通の assert を使うと
< assert (Hy: P y -> Q y -> R y); auto.
と書かないといけないが、こっちの形式で書くと
< assert (Hy := H y).
と書くだけでよい。
cut form
これは基本的に assert と同じであるが、できあがるサブゴールの並び順が逆になる。
apply term in ident
assert のところに書いたことを、apply 一発で済ませられる tactic。
仮定に「H: T -> U」があって、定理「th: U->V->W」があったとすると、
apply th in H.
を実行すると、T と V を証明すれば W が仮定に追加できる状態になる。例えば、
x : Z y : Z H : x >= 0 H0 : y = 1 -> x * x > y * y ============================
で、
apply Zgt_squre_simpl in H0.
とすれば、「x >= 0」と「y = 1」を証明すれば「x > y」を使えるようになる。
Zgt_squre_simpl の前提は「n >= 0」と「n * n > m * m」なので、H に対して適用してもよいのだが
apply Zgt_squre_simpl in H.
では、「m」を何にして定理を適用するのか不明なのでだめで、
apply Zgt_squre_simpl with (m:=y) in H.
と書かないといけない。
この方法で適用できる定理を見つけるのは面倒なので、使えそうな定理を知ってるときにしか使えないと思う。