証明可能な正しいプログラムについて私たちは何を知っていますか?


37

コンピュータープログラムの複雑さの増大と、コンピューターの社会における重要性の高まりにより、コードが正しく機能することを正式に証明しなければならないプログラミング言語をまだまとめて使用しないのはなぜなのか疑問に思います。

私はこの用語が「証明コンパイラ」であると信じていますここで見つけまし):プログラミング言語をコンパイルするコンパイラで、コードを書くだけでなく、コードの仕様を述べ、コードが準拠していることを証明する必要があります仕様(または自動化された証明者を使用してそうする)。

インターネットを検索しているときに、非常に単純なプログラミング言語を使用しているプロジェクト、または現代のプログラミング言語に適応しようとする失敗したプロジェクトのみを見つけました。これは私の質問につながります:

本格的なプログラミング言語を実装する認定コンパイラはありますか、またはこれは非常に難しい/理論的に不可能ですか?

また、私は、任意の複雑性クラスのような証明可能なプログラム、関与見ていました「証拠が存在するチューリングマシンですべての言語のクラスを決定可能なこと、このチューリングマシンの停止」私が呼ぶ、するアナログとして、、再帰言語のセット。ProvableRR

このような複雑なクラスを勉強することの利点を見ることができます:たとえば、の場合、Halting問題は決定可能です(明白な方法で定義されたは、それが決定可能な言語の最大クラスになると推測し)。さらに、実際に役立つプログラムを除外することはできないと思います。終了を証明できない場合に誰がプログラムを使用するでしょうか?ProvableRProvableRE

私の2番目の質問は:

含まれる言語に特定のプロパティがあることを証明することを要求する複雑性クラスについて何を知っていますか?


1
コンパイラーは、プログラムが停止する証拠を見つけるまで、長さiのすべての可能な証拠を列挙し、1から無限に移動させます。コンパイラーへの入力を確実に停止する必要がある場合、コンパイラーは常にその証拠を見つけます。停止の問題は決定できないため、停止するプログラムがあると結論付けなければなりませんが、この証拠は存在しません。重要な点は、プログラムが証拠が存在するかどうかを見つけることができず、証拠が存在する場合は見つけることができないということではありません。
アレックス10ブリンク

3
それらを分割する必要があると思います。それらは異なる答えを持つ異なる質問です。
マークライトブラット

4
最初の質問では、影響力のある論文は「社会プロセスと定理とプログラムの証明」、portal.acm.org / citation.cfm?id
コリンマッキーラン

1
プログラムの検証は決定できません。したがって、1つの問題は、何が良い解決策を構成するかを言うことです。cstheory.stackexchange.com/questions/4016/…を
ラドゥグリゴール

2
@Colin:その論文は証明の分析のために読む価値がありますが、その予測は偽造されています。今日では、コンパイラ、オペレーティングシステムカーネル、ガベージコレクタ、およびデータベースが正しいと証明されていますが、これらはすべて不可能であると予測されています。彼らの批判を回避するためのトリックは、形式的な証明の低レベルの詳細の人間による検証を避け、証明の機械検証を使用し、人間を使用して証明チェッカーを検証することでした。Noamの型理論への言及は、最先端技術が存在する場所であり、型理論は機能的であるため、命令型プログラムを拘束力のあるものにします。
ニールクリシュナ

回答:


28

「コンパイラの認証」とは通常、少し異なることを意味します。つまり、発行するマシンコードが高レベルのセマンティクスを正しく実装していることを証明できるコンパイラがあることを意味します。つまり、これはコンパイラのバグがないことの証明です。人々がコンパイラに与えるプログラムはまだ間違っている可能性がありますが、コンパイラは間違ったプログラムの正しいマシンコードバージョンを生成します。これらのラインに沿った最大のサクセスストーリーは、CompCert検証済みコンパイラです。これは、Cの大規模なサブセット用のコンパイラです。

Compcertコンパイラ自体は、正当性の証明(Coqで行われます)を備えたプログラムであり、プログラムのコードを生成する場合、(CompCertデザイナーが使用したアセンブリとCの動作セマンティクスに関して)正しいことを保証します。これらのことをマシンチェックする努力は非常に大きなものです。通常、正当性の証明は、検証するプログラムのサイズの1倍から100倍の範囲になります。マシンチェックプログラムと証明を書くことは、習得しなければならない新しいスキルです。数学やプログラミングではありませんが、両方を上手に行えるかどうかにかかっています。初心者プログラマーであるかのように、ゼロから始めているように感じます。

ただし、これに対する特別な理論的障壁はありません。これらの線に沿った唯一のものは、すべてのプログラムが合計されている任意の言語に対して、合計言語でプログラムされたときに少なくとも指数関数的に大きくなる一般的な再帰言語のプログラムを見つけることができるブルームサイズ定理です。この結果を理解する方法は、完全な言語がプログラムだけでなく終了証明もエンコードすることです。したがって、長い終了証明を持つ短いプログラムを作成できます。ただし、管理可能な終了証明を使用してプログラムを作成するだけなので、これは実際には重要ではありません。

編集:Dai Leは、最後のポイントの詳細を求めました。

これは、プログラムが機能する理由を理解できれば、その理由が何百万ページもの広大な不変長さである可能性は低いという事実に基づいて、ほとんど実用的な主張です。(私が使用した最長の不変条件は数ページの長さであり、少年は彼らが査読者に不平を言うのですか!理解できるように、不変条件はプログラムが人々がそれを理解するのを助けるすべての物語を取り去る理由です)

しかし、いくつかの理論的な理由もあります。基本的に、正確性の証明が非常に長いプログラムを体系的に発明する方法はあまり多くありません。主な方法は、(1)正当性を証明するロジックを取得する、(2)そのロジックで直接表現できないプロパティを見つける(一貫性の証明が典型的なソースです)、および(3)そのプログラムを見つける正しさの証明は、表現できない財産の表現可能な結果の家族に依存しています。(2)は表現できないため、これは各表現可能な結果の証明を独立して行う必要があることを意味します。これにより、正当性証明のサイズを拡大できます。簡単な例として、親リレーションを持つ1次ロジックでは、先祖リレーションを表現できないことに注意してください。kk)は、固定ごとに表現可能です。そのため、ある程度の祖先のプロパティ(たとえば100)を使用するプログラムを提供することにより、FOLの正当性の証明に、それらのプロパティの証明を100倍以上含めることができます。k

この主題に関する洗練された考え方は「逆数学」と呼ばれ、与えられた定理を証明するためにどの公理が必要かという研究です。私はそれについてあまり知りませんが、そのアプリケーションに関する質問をCSに投稿すると、少なくともTimothy Chowとおそらく他の数人があなたに興味深いことを伝えることができると確信しています。


1
この点についてもう少し詳しく説明してください。「管理可能な終了証明を持つプログラムを作成するだけです」
大ル

更新された回答をありがとう!あなたの答えは本当に私の視点を開きます。実際、私自身も「逆数学」に少し取り組んでいますが、あなたが述べたつながりに気付いていませんでした。再度、感謝します!
大ル

1
編集のポイントは、自然証明システム(たとえば、Fregeなど)で長い証明を必要とするトートロジーの候補がほとんどないという事実に関連しています。この理由の一部は、最初にトートロジーを知る唯一の方法が自己由来であるということです。それは、証拠が頭にあったからです。
ジョシュアグロチョフ16

22

最初の質問に対する答えは、一般に現在のツールではあまりにも多くの作業が必要だということです。この感覚をつかむには、Coqでのバブルソートの正確性を証明することをお勧めします(または、もう少しチャレンジしたい場合は、クイックソートを使用します)。そのような基本的なアルゴリズムの正確さを証明することが非常に難しく、時間がかかる限り、プログラマーが検証済みのプログラムを書くことを期待することは合理的ではないと思います。

この質問は、なぜ数学者が証明チェッカーによって検証可能な正式な証明を書かないのかという質問に似ていますか?正式な正当性証明を使用してプログラムを作成するということは、作成されたコードに関する数学的定理を証明することを意味し、その質問に対する答えはあなたの質問にも適用されます。

これは、検証済みプログラムの成功例がなかったことを意味するものではありません。Microsoftのhypervisorのようなシステムの正確性を証明しているグループがあることは知っています。関連するケースは、MicrosoftのVerified C Compilerです。しかし一般的に、現在のツールは、一般的なプログラマー(および数学者)にとって有用になる前に、多くの開発(SEおよびHCIの側面を含む)を必要とします。

Neelの全機能のみを備えた言語のプログラムサイズの拡大に関する回答の最後の段落については、実際にさらに証明するのは簡単です(正しく理解できれば)。すべてのプログラミング言語の構文がceであり、計算可能な関数の合計がceではないことを期待するのは合理的です。したがって、すべてのプログラムが合計されるプログラミング言語では、プログラムによって計算できない合計の計算可能な関数があります(その言語で。


2番目の質問については、少し前にScottのブログで同様の質問に答えました。基本的に、複雑度クラスに優れた特性があり、計算可能に表現できる(つまり、ce)場合、複雑度クラスの問題のいくつかの表現が、複雑度クラスに対応する非常に弱い理論で完全に証明できることを証明できます。基本的な考え方は、理論の証明可能合計機能がすべて含まれていることであるの関数となるという問題A Cを0AC0AC0-complexityクラスは完全であるため、complexityクラスのすべての問題が含まれ、これらのプログラムの全体性を証明できます。証明と複雑性理論の関係は、証明の複雑性で研究されています。興味がある場合は、SAクックとP. Nguyenの最近の本「証明の複雑性の論理的基礎」を参照してください。(2008年のドラフトが利用可能です。)したがって、基本的な答えは、多くのクラスで「Provably C = C」であるということです。

これは一般的には当てはまりません。なぜなら、構文上の特性を持たないセマンティックな複雑性クラス、たとえば、計算可能な全関数があるからです。再帰的とは全再帰関数を意味する場合、2つは等しくなく、理論で証明可能合計である計算可能関数のセットは、証明理論の文献でよく研究されており、理論の証明可能合計関数と呼ばれます。たとえば、次の証明可能総計関数れるε 0 -recursive関数(または同等ゲーデルのシステムで機能T)の証明可能総関数P A 2は、ジラールのシステムで機能しているFの証明可能トータル機能、PAϵ0TPA2F、原始再帰関数です...。Σ1

しかし、これはプログラム検証のコンテキストではあまり意味がないと思われます。同じ関数を拡張的に計算しているプログラムもありますが、2つのプログラムが同じ関数を計算していることを証明できません。意図的に。(これはモーニングスターとイブニングスターに似ています。)さらに、理論がその全体性を証明できないプログラムを取得するために、所定の証明可能な合計プログラムを変更するのは簡単です。


2つの質問は関連していると思います。目的は、検証済みプログラムを取得することです。検証済みプログラムとは、プログラムが数学的ステートメントである説明を満たすことを意味します。1つの方法は、プログラムをプログラミング言語で記述し、そのプロパティが説明を満たしていることを証明することです。これはより一般的な方法です。別のオプションは、制限された手段を使用して問題を記述する数学的ステートメントを証明し、それから検証済みプログラムを抽出することです。たとえば、対応する理論で、任意の数nに対して積がnに等しい素数のシーケンスがあることを証明する場合、Pを抽出できます。PnnP証明からの因数分解のアルゴリズム。(可能な限り最初のアプローチを自動化しようとする研究者もいますが、プログラムの興味深い非自明な特性をチェックすることは計算上困難であり、偽陽性と陰性なしでは完全に検証することはできません。)


3
いい答えだ!あなたは、1つの方法がプルーフからプログラムを抽出することであることに言及します。これは、例えばCoqで自動的に行うことができます。関連する分野は証明マイニングです。そこでは、人々(通常は数学的なロジックで作業している)が特定の証明から情報を抽出しようとします。たとえば、場合によっては、古典的なものを与えられた直観的な証明を(自動的に)見つけることができます。
ラドゥグリゴール

1
@Radu:Coqで自動的に実行できることを指摘してくれてありがとう。あなたが言及したように、いくつかのクラスの式の証明マイニングを使用して、いくつかの建設的な情報、したがって古典的な定理証明からプログラムを抽出することもできます(興味のある人はUlrich Kuhlenbachの論文を確認できます)。もう一つの可能性に関連する結果があればということである定理で証明されたP A、それはで建設的にも証明可能であるH Aハーヴェイフリードマンの翻訳で。_Π20PAHA
カベ

1
Andrej Bauerのブログには、CoqでのGodelのDialectica Interpretationを証明する新しい興味深い投稿があります。
カヴェー

18

最初の質問で質問していることは、「検証コンパイラ」と呼ばれることもあります。数年前、トニー・ホアはコンピューティング研究の大きな挑戦としてそれを提案しまし。これはある程度存在し、Coq定理証明器などのツールで積極的に使用されており、型理論としての命題の原則(「カリーハワード」)によって問題を整理します。

編集:「ある程度」に重点を置きたいだけです。これは解決された問題にはほど遠いですが、Coqの成功はそれが単なる夢ではないという希望を与えます。


8
検証済みのソフトウェアを構築することは、1956年に普通の古いソフトウェアを構築することであったと言えます。ソフトウェアが非常に重要になることはすでに明らかであり、すでに大きな成功事例がありました。しかし、人々はまだ多くの基本的な概念を欠いており(例えば、手順や変数がどのようなものであるかを明確に理解しています)、理論から実践までの距離は、定理のコードをプログラミングしてLispを実装するのと同じくらい短い場合があります。これは、言語と検証に取り組んでいる、信じられないほどエキサイティングな時間です。
ニールクリシュナスワミ

12

プログラムが正しいかどうかをチェックするツールは、プログラム検証ツールと呼ばれることもあります。このコンテキストでは、「正しい」とは通常、2つのことを意味します。プログラムが特定の出力を生成しないこと(セグメンテーション違反、NullPointerExceptionなど)、およびプログラムが仕様に一致することです。

コードと仕様は一致する場合がありますが、それでも間違っていると認識される場合があります。ある意味で、開発者に仕様を記述するよう依頼することは、2人の開発者に問題を解決するよう依頼することに似ています。2つの実装が一致する場合、それらがOKであるという確信が高まります。ただし、別の意味では、仕様は2番目の実装よりも優れています。仕様は効率的である必要も実行可能である必要もないため、はるかに簡潔であるため、間違えにくくなります。

これらの注意事項を念頭に置いて、Spec#プログラム検証ツールをご覧になることをお勧めします。


Spec#(およびその拡張Sing#)を理解している限り、プログラマーはアサートを静的に検証することができますが、プログラマーがこれを行う必要はなく、コードの任意のプロパティを証明することもできません。
アレックス10ブリンク

任意のプロパティは、原則としてfolアサーションとしてエンコードできます。このツールに何が必要かはわかりません。すべての可能な入力に対して、出力がどうあるべきかをスペックに伝えたいですか?
ラドゥグリゴール

4

一般的な場合、アルゴリズムが仕様と同等かどうかを確認するアルゴリズムを作成することはできません。これは非公式の証拠です。

ほとんどすべてのプログラミング言語はチューリング完全です。したがって、TMによって決定された言語は、この言語で作成されたプログラムによっても決定されます。

Equivalence/TM

Equivalence/TMNonemptiness/TMEmptiness/TMEmptiness/TMEquivalence/TMEquivalence/TM受け入れられません。したがって、2台のマシンが同等であるかどうかに関係なくアルゴリズムを使用できますが、それらが同等であるか、アルゴリズムに十分な時間を与えていないかはわかりません。

ただし、これは一般的な場合のみです。問題のより緩和されたバージョンを解決することにより、仕様がプログラムと同等であるかどうかを決定できる可能性があります。たとえば、いくつかの入力のみを調べたり、2つのプログラムがある程度の不確かさで同等であると言う場合があります。これがソフトウェアテストのすべてです。

残りの質問については:

注:この部分は、説明のために編集されています。避けようとしていた間違いを犯したことがわかりました。ごめんなさい。

TrueRTrueRR

ProvableR=TrueRProvableRTrueRTrueRProvableRAϵTrueRAAAϵProvableR

非公式には、これは次のように要約できます:言語が決定的であることは、それが証明されるまでわかりません。したがって、正式なシステムで言語が決定可能であるという知識を持っている場合、この知識はその証拠にもなります。したがって、言語が決定可能であり、証明できないという知識を同時に持つことはできません。これら2つのステートメントは相互に排他的です。

RProvableRProvableRRR

@Kavehは、それを最もよく要約しています。Provableは常に、あるシステム/理論で証明可能であることを意味し、一般に真実と一致しません。

他の複雑度クラスについても同じことが言えます。メンバーシップを決定するには、最初に証明が必要です。これが、2番目の質問が複雑すぎると思う理由です。複雑な理論だけでなく、言語に持たせたい性質に応じて計算理論も含まれているからです。


1
RProvableRΣ30Σ10

1
証明可能とは、常に何らかのシステム/理論で証明可能を意味し、一般的な真実と一致しません。
カヴェー

1
私の質問がおもしろいのは、決定可能な言語のセットではなく、停止しているチューリングマシンのセットについて話す必要があることです。
アレックス10ブリンク

1
@Alexまあ、あなたは言語について話すいくつかの方法が必要ですが、数え切れないほど多くがあります。そのため、(証明などの)有限オブジェクトに関連する言語について話したい場合は、TMなどの有限オブジェクトによって識別可能な言語に制限する必要があります。
マークReitblatt

2
R

3

次の古典的なモノグラフは、ほぼ正確にあなたの2番目の質問を研究します:

ハートマニス、J。実行可能な計算と証明可能な複雑性のプロパティ、応用数学におけるCBMS-NSF地域会議シリーズ、30。産業応用数学協会(SIAM)、フィラデルフィア、ペンシルベニア州、1978年。

{LM|TnTn Fで証明可能}MTnMn

Tnnログngn1FTME[Tn]TME[Tngn]

TnFTME[Tn]TME[Tn]

TnnログnTME[Tn]={LM|Fが証明するj[LMj=LMTjnTn]}

ただし、スペースの場合、状況はより適切に制御されます。

定理6.9:(1)If snnSPACE[sn]=FSPACE[sn]

(2)場合SPACE[S(n)]=FSPACE[S(n)]S(n)ns(n)SPACE[S(n)]=SPACE[s(n)]


1

問題は正しく提起されなければなりません。たとえば、無限のメモリとそれにアクセスする何らかの手段(ベースアドレスをある数だけ移動する操作)が与えられた場合に、実際のプログラムが完了するかどうかを知りたがる人はいません。チューリングの定理は、具体的な意味でのプログラムの正確性とは無関係であり、プログラム検証の障壁としてそれを引用する人々は、2つのまったく異なることを混乱させています。エンジニア/プログラマーがプログラムの正確性について話すとき、有限の特性について知りたいです。これは、何かが証明可能であるかどうかに興味がある数学者にも当てはまります。Godelの手紙http://vyodaiken.com/2009/08/28/godels-lost-letter/でこれについて詳しく説明しています。

つまり、Entscheidungsproblemの決定不能性にもかかわらず、Yes-or-No質問に関する数学者のメンタルワークを完全に機械に置き換えることができることを明らかに意味します。結局のところ、マシンが結果を出さない場合に問題をもっと考えることは意味がないほど大きい自然数nを選択する必要があります。

実際のコンピューターで実行されているプログラムの膨大な状態セットを調べて、悪い状態を検出することは不可能な場合があります。それができない理論的な理由はありません。実際、この分野では多くの進歩がありました。たとえば、http: //www.cs.cornell.edu/gomes/papers/SATSolvers-KR-book-draft-07.pdfをご覧ください(Neil Immermanに感謝しますこれについて教えてください)

別のより困難な問題は、プログラムを修正するために必要なプロパティを正確に指定することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.