プログラムの検証に精通している場合は、背景の前に質問を読むことをお勧めします。プログラムの検証に慣れていない場合でも、この質問に答えることはできますが、背景を最初に読むことをお勧めします。
バックグラウンド
部分的な正確性の確認は決定できないとしばしば言われます。議論のために、フロイドのスタイルでこの声明を正確にする1つの非常に特定の方法を選んでみましょう-ホア。フローグラフは区別付き有向グラフである初期のノードのすべてのノードが到達可能であるから。プログラムは、そのノードでコマンドです流れ図です。コマンドには3つのタイプがあります(1)前提条件は q、(2)アサーションは qをアサート、(3)割り当てはv:= eです。ここで、qはfol(1次論理)式、eはfol項、vは変数です。
我々は、プログラムがあると言う部分正しい各ノード注釈を付ける方法がある場合、XとA前提条件A(X)と事後条件のB(x)のように、(1)は、最初のノードの前提条件が有効である、(2){ a(x) } x { b(x) }はすべてのコマンドxに適用され、(3)(b(x)はa(y)を意味します)はxからyまでのすべてのエッジに有効です。ここで、Hoareトリプルは次のように定義されます。
- { p } assert q { r }は、(pが(q and r)を意味する)が有効であることを意味します
- { p } は、 q { r }が((pおよびq)がrを暗示する)が有効であることを意味すると仮定する
- { P } V:= E { R((つまり}手段PとEの代わりにVが)を意味し、Rは)有効です
この部分的な正しさを確認することが決定できない理由について、手で波打った議論があります:a(x)とb(x)を入力したら、いくつかのfol式が有効であるかどうかを確認する必要があります。
部分的に正確に終了をエンコードする一般的な方法は、「前回実行されてから終了に向かって進行した」と本質的に言う特別なアサーションを追加することです。これらの進行アサーションは、フローグラフ上のすべての無限ウォーク(初期ノードから開始)に無限に多くの進行アサーションが含まれるように配置する必要があります。具体的には、進行アサーションの形式は 常にassert u < vで、ここでuとvは正の整数であり、割り当てu:= fが先行し、その後に割り当てv:= uが続くとしましょう。ここでfはバリアント関数、uは現在の値、vは以前の値です。ここで、「正の整数」について説明し、それらを比較するため、folよりも少し多く使用できることを確認する必要があります。Peano算術が使用可能であるとしましょう。(この選択については強く感じません。都合が良ければ無視してください。)もちろん、fはプログラムで言及されている他の関数や定数を使用するかもしれません。(プログラムの最初に仮定を追加することは、非論理公理を導入することと同等であることに注意してください。)
これで、進行状況のアサーションがあるプログラムがまだ部分的に正しい場合、元のプログラムが終了することがわかります。
質問
終了プログラムを考えると、進行状況の表明のためのバリアント関数を思いつくのは難しいと感じています。しかし、どのくらい難しいですか?(上記の大きな背景があっても、見方によっては、この質問を未解決または未定義のままにしておくことを知っています。)
別の言い方をすれば、終了を部分的な正確さまで減らす問題を形式化し、その複雑さについて何かを述べているリファレンスを探しています。もちろん、これをすべて行う回答は歓迎されます。