数学的な証明を書き留めるのは、コンピューターコードを書くよりもフォールトプルーフなのはなぜですか?


190

バグなしでコンピュータプログラムを書き留めるよりも、間違いを犯さずに数学的な証明を書き留める方がはるかに簡単だと気づきました。

これは私の経験よりも広く行われているようです。ほとんどの人は、プログラミング中に常にソフトウェアのバグを作成します。また、コンパイラには、常に間違いを教えてくれます。私は一度に間違いのない大きなコンピュータープログラムを書いた人のことを聞いたことがなく、バグがないと完全に確信していました。(実際、バグのないプログラムはほとんどなく、多くの高度にデバッグされたプログラムですらあります)。

しかし、コンパイラーが間違いを犯したことをフィードバックすることなく、場合によっては他人からフィードバックを得ることなく、論文全体または数学的な証明の本を書くことができます。

はっきりさせてください。これは、人々が数学の証明で間違いを犯さないと言うことではありませんが、経験の浅い数学者にとっても、その間違いは通常それほど問題ではなく、あなたの間違い。

実際、これが当てはまらない場合、数学はほとんど不可能に思えます。

だから、これは私に質問をするようになりました:前者が後者よりもはるかに扱いやすいようにする、誤りのない数学的な証明を書くことと誤りのないコンピューターコードを書くこととで何がそんなに違いますか?

プログラマーが怠makesになり、コードを厳密に書くために必要なことをできないようにするのは、人々がコンパイラーの「外部の神託」をミスに向けているという事実に過ぎないと言うことができます。この見方は、もし彼らがコンパイラーを持っていなければ、数学者と同じように完璧であることができるということを意味するでしょう。

あなたはこの説得力があると思うかもしれませんが、プログラミングと数学的な証明を書き留めた私の経験に基づいて、これは本当に説明ではないと直感的に思えます。2つの取り組みについては、根本的に異なるものがあるようです。

私の最初の考えは、違いがあるかもしれないが、数学者にとって、正しい証明はすべての論理的なステップが正しいことだけを必要とするということです。すべてのステップが正しい場合、証明全体が正しいです。一方、プログラムにバグがないためには、すべてのコード行が正しいだけでなく、プログラム内の他のすべてのコード行との関係も同様に機能する必要があります。

言い換えれば、ステップ場合の証明では、ステップでミスを作り、その後、正しいなりません台無しステップ今まで。ただし、コード行が正しく記述されている場合、行間違いは行の動作に影響するため、行を記述するときは常に他のすべての行との関係を考慮する必要があります。これを制限するためにカプセル化とそれらすべてを使用できますが、完全に削除することはできません。Y X X Y X XXYXXYXX

つまり、数学的証明のエラーをチェックする手順は、証明ステップの数が本質的に線形ですが、コンピューターコードのエラーをチェックする手順は、コードの行数が本質的に指数関数的です。

どう思いますか?

注:この質問には、さまざまな事実や視点を探求する多数の回答があります。回答する前に、それらすべてを読んで、追加する新しいものがある場合にのみ回答してください。冗長な回答、または事実と意見を裏付けない回答は削除される場合があります。


3
紙上と定理証明器で機械化されたプログラムの両方の正確性の証拠を知っていますか?どちらも存在し、更新に矛盾します。正しいことは、一般的に教えられているプログラミングは、正確性を証明するプログラミングとほとんど関係がないということです。
Blaisorblade

76
クヌースのことを思い出すの引用、私が思う「上記のコードに注意してください私はそれが正しい証明し、私はそれをテストしたことがない!」
ハーゲン・フォン・Eitzen

コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ジル

7
1億行の長さで「バグ」のない手書きの数学の証明を見つけてください。私が所有しているすべてのものを提供します。
デイヴァー

関数型プログラムは証明よりもはるかに簡単に書くことができますが、状態が入るとすぐに...難易度が爆発します...
aoeu256

回答:


226

あなたの質問に対する答えとして、一つの理由と一つの誤解を提供させてください。

主な理由は、(一見)正しい証明を書くことが容易であることは、彼らは非常に高いレベルで書かれているということです。次のようなプログラムを作成できるとします。

function MaximumWindow(A, n, w):
    using a sliding window, calculate (in O(n)) the sums of all length-w windows
    return the maximum sum (be smart and use only O(1) memory)

プログラムの仕様はその実装よりもはるかに簡潔であるため、この方法でプログラミングする場合、間違いを起こすのははるかに困難です。実際、擬似コードをコード、特に効率的なコードに変換しようとするすべてのプログラマーは、アルゴリズムのアイデアとその実装の詳細の間でこの大きな溝に遭遇します。数学的証明はアイデアに集中し、詳細には集中しません。

数学的な証明のためのコードの本当の対応物は、コンピュータ支援の証明です。これらは通常のテキストによる証明よりも開発がはるかに難しく、多くの場合、読者には「自明」である(通常は気づかない)さまざまな隠れたコーナーを発見しますが、コンピューターにはそれほど明白ではありません。また、コンピュータは現在、比較的小さな隙間しか埋めることができないため、校正を読む人が森のために森を見逃すようなレベルに校正する必要があります。

重要な誤解は、数学的な証明がしばしば正しいということです。実際、これはおそらくかなり楽観的です。複雑な証明を間違いなく書くことは非常に難しく、論文にはしばしば誤りが含まれます。おそらく最も有名な最近の例は、上のいくつかの1000 +ページを含む有限単純群の分類でワイルズ初の試み(の特殊なケース)(フェルマーの最終定理を意味する)谷山-志村予想、および様々なギャップ、あるquasithinグループでした分類が終了したと思われる20年後に書かれました。

Voevodskyの紙でのミスが、彼は間違いなく彼が開発を開始することをそんなに証明書かれて作られたホモトピー型理論、正式にホモトピー理論を開発するための便利な論理的なフレームワークを、そして今後検証するためにコンピュータを使用し、すべての(少なくとも彼自身によると彼のその後の仕事を入場)。これは極端な(そして現在、非実用的な)位置ですが、結果を使用するときは、証明を調べて正しいかどうかを確認する必要があります。私の地域には、間違っていることが知られているが撤回されていない論文がいくつかあり、その状況は専門家の間で口から耳に伝えられています。


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
DW

1
将来、証明アシスタントを使用してコードと証明の両方をチェックすることは可能ですか?多分それはあなたにアグダ学ぶ時ですか?(ごめん...)
アレックスヴォング

3
@AlexVong問題の1つは、非自明なコードの正式な仕様を記述すること(コードが実際に仕様を満たしていることを確認できるようにする)がほとんど不可能であることです。たとえば、ブラウザの正式な仕様がどれほど複雑になるか想像できますか(すべてのユーザーインタラクション、サポートされているすべてのファイル形式とプロトコルなどを含む)。
svick

2
@svickあなたは正しいです、ユーザーとの対話のために、正しい振る舞いがどうあるべきかさえはっきりしないことがあります。そのため、代わりに適切な形式仕様(例えば、証明、コンパイラー)に焦点を当てる必要があります。
アレックスヴォング

1
確かに。これは、多くの人々が低レベル言語でのコーディングが高レベルの抽象言語でのコーディングよりもはるかに退屈で面白くないと感じる理由の説明にもなります。もちろんそれは人によっても異なるかもしれませんが(もちろん、実行するソフトウェアを書くよりも非常に低レベルのハードウェア/電子回路を構築することを楽しむ人もいるかもしれません。また、多くの場合、低レベルのコードはかけがえのないもので、うまく書くことができます単独で称賛に値する希少なスキル/偉業になることができます)。
xji

77

(これを適切な答えにする時間/関心がないので、おそらくここでいくつかのダウン投票を危険にさらしていますが、以下に引用されたテキスト(および引用された記事の残りの部分)は非常に洞察力があり、それらが書かれていることも考慮しています有名な数学者によって。おそらく後で答えを改善できるでしょう。)

既存の答えと特に区別できるものではないと考えているアイデアは、「証明」または議論が数学コミュニティに伝えられ、その目的は、(退屈な)詳細を原則として満たすことができることを彼らに確信させることです完全に指定された正式な証拠を取得すること。この重要な例の1つは、既存の定理を単純に述べることで使用できることですが、コードの再利用は一般的にはるかに困難です。また、マイナーな「バグ」も考慮してください。これにより、コードの一部が完全に役に立たなくなる可能性があります(たとえば、SEGFAULT)。

コンピュータプログラムをまったく機能させるために必要な正確性と完全性の基準は、数学的コミュニティの有効な証明の基準よりも数桁高いです。それにもかかわらず、大規模なコンピュータープログラムは、非常に慎重に作成され、非常に慎重にテストされた場合でも、常にバグがあるようです。[...]私たちが実践している数学は、他の科学よりも形式的に完全で正確ですが、コンピュータープログラムよりも内容に関して形式的に完全で正確ではありません。違いは努力の量だけではありません。努力の種類は質的に異なります。大規模なコンピュータープログラムでは、無数の互換性問題に多大な労力を費やす必要があります。すべての定義の一貫性を確保し、「良い」開発を行う 便利ではあるが面倒ではない一般性を持ち、機能などの「正しい」一般性を決定するデータ構造。簿記部分とは異なり、大きなプログラムの作業部分に費やされるエネルギーの割合は驚くほど小さい。一般性と機能が追加されると「正しい」定義が変更されるため、ほとんど必然的に手に負えなくなる互換性の問題のため、コンピュータープログラムは通常、頻繁にゼロから書き直す必要があります。

数学の証明と進歩について(pp。9-10)、WILLIAM P. THURSTON https://arxiv.org/pdf/math/9404236.pdf


3
「コードの再利用」についてのポイントはかなり適切です。長い証明をロシア語から英語に翻訳するには、かなりの入力が必要です。しかし、C ++からJavaへの大規模なコンピュータープログラムの翻訳には、非常に多くの考えが必要です。また、古代ギリシャ語で3000年前の証拠を復活させるのも簡単です。PL / 1で30年前のプログラムを復活させることは、ほぼ同じくらい難しいです。
Quuxplusone

2
コンピュータプログラマは使用:古代ギリシャの例では、また、私は実感しましたトンなど、地元の俗語や口語表現のを(void*)1してopen('/dev/null')も、先の言語に翻訳おろか、異なるサブカルチャーの間で移植できない可能性があります。(読者は、長年の経験によって、おおよそのセマンティクスを理解する必要があります。)数学的な証明には、この種の「スラング」はあまり含まれていないと思います。証明に単語が使用されている場合、その実際の普遍的な意味は読者が何らかの形で推測できるはずです。コンピュータプログラムには普遍的な意味すらありません!
Quuxplusone

1
+1、構成主義者として、任意の大きな値とは異なる ramp延した推定が私を夢中にさせるので。これは、数学者が無限級数について語り始め、それらの級数に基づいて議論を始め、隠された0誤り。00
ナット

@Nat、詳しく説明できますか?わかりません。
グレゴリーマガルシャク

@GregoryMagarshak この答えは私が好きであるとして記述された無限の有効なシリーズの建設には、誤謬につながると仮定した場合、示されたこのhidden- 誤acy00(Wikipediaセクションの下の「偽装」バージョン)。古典的な数学者は、誤りは無限級数が収束すると仮定したと言うかもしれませんが、構成主義者は誤りを無限の無条件の推定であると説明します。
ナット

55

EWダイクストラを引用して始めましょう:

「プログラミングは応用数学の最も困難な分野の1つです。貧しい数学者は純粋な数学者のままでいるべきです。」(EWD498から)

「プログラミング」でのダイクストラの意味は、現在の使用法とはかなり異なりますが、この引用にはまだいくつかのメリットがあります。他の回答では、数学の抽象化のレベルはプログラミングよりもはるかに高くすることが許可されていることを既に述べています。

しかし、これは単に証明とコンピュータープログラムのより根本的な違いの結果であり、それが彼らの目的であると信じています。

数学的証明の主な目的は、数学的主張が正しいこと、そしておそらくさらに重要なこととして理解を達成することを自分自身に納得させることです。したがって、設計によって理解が得られるようにすべてが作成される数学の世界でのみ作業することを選択することができます(一部の学生は異なることを懇願しますが...)これはまさにダイクストラが「純粋な数学者」、つまり(ほとんど)数学的事実とその特性の理解にのみ関心があります。

したがって、正しい証明を作成することは比較的フォールトプルーフであることに驚かないでください。それが「運動」全体のポイントです。(それでも、これは間違いが存在しない、またはほとんど存在しないという意味ではありません。

さて、プログラミングを検討する場合、私たちの目的は何ですか?私たちは本当に理解を求めているのではなく、機能する何かを求めています。しかし、いつ何かが「機能する」のでしょうか?何か奇妙なマシンが実行したいタスクを完了できるようなものをうまく作成できたときに機能します。

これは根本的な違いだと思います。それは、私たちの目標が単に「証明する」定理として単純に述べることはできず、数学的人工物ではなく、現実世界(何か)で何かを望んでいることを意味するからです。これは、機械をなだめなければならないため、理論的には目標を達成することができないことを意味します(ダイクストラはあなたに関係なく試してもらいます)。どういうわけか。

したがって、最終的には、試してみて、結果にある程度満足するまで失敗、修正、失敗、再試行する以外に方法はありません。


誤りのない証明を書く仮説は、誤りのないプログラム(実際には@Arielが指摘しているように異なるステートメントである)よりも単純であることに注意してください。それでも、これが暗示されている質問にいくらかの光を投げかけることを願っています:「いくつかの定理を証明することとプログラムを書くことの違いは本当に何ですか?」(カリー・ハワード通信の不注意なオブザーバーは、「何もありません!」と言うかもしれません)


コメントで@wvxvwが言及したように、「構造化プログラミングに関する注意」(EWD249、21ページ)からの次の段落は非常に関連性があります。

(...)プログラムはそれ自体が目標ではありません。プログラムの目的は計算を呼び起こすことであり、計算の目的は望ましい効果を確立することです。プログラムはプログラマーによって作成された最終製品ですが、それによって引き起こされる可能性のある計算-「作成」は機械に任されています!-彼の貿易の真の主題です。例えば、プログラマーが自分のプログラムが正しいと述べるときはいつでも、彼はそれが引き起こすかもしれない計算について本当に断言します。

(...)したがって、ある意味では、プログラムの作成は数学的理論の作成よりも困難です。プログラムと理論の両方は、構造化された時代を超越したオブジェクトです。しかし、数学理論は現状では理にかなっていますが、プログラムは実行によってのみ理にかなっています。


2
私はただの素人です。ダイクストラは「プログラミング」によって実際に何を参照しましたか?
Ovi

2
@Ovi正確にはわかりませんが、主な違いは、「一般的な」プログラミングタスク以上の(非自明な)アルゴリズムの問​​題を解決することについて話していることです。つまり、いくつかの接続を必要とするCRUDプログラムについては、既存のアーキテクチャまたは他のコンポーネントなど。プログラミングに関するダイクストラの意見の詳細は、この回答
離散トカゲ

3
ダイクストラを引用して賛成票を投じましたが、間違った場所を選択しました!彼は、構造化プログラミングの最初の段落でこの問題について多くのことを書いています。別の見積書を提出して回答を変更したくはありませんが、その論文から回答にさらに追加することを検討してください。
wvxvw

@Oviあなたの質問に対する私の推測は、ダイクストラの時代のプログラミングは、高レベル言語の現代の時代と比較して、アセンブリコードを書くことを意味することが多かったということです。同様に、私は人月の神話の1974年版を読んでいます、概念はまだ現在のですが、技術的な言及は、ほとんどの人は、今日のプログラミングとして考えるものとは大幅に異なるシステム・レベルのアセンブラやPL / I、ある
JimLohse

46

Lamportは、プルーフの書き方(8-9ページ)のプルーフのエラーのvalence延に関する意見の不一致の根拠を提供します。

約20年前、私は入門数学クラスのシュレーダー・バーンスタインの定理の証明を書くことにしました。私が見つけることができた最も単純な証拠は、ケリーの古典的な一般的なトポロジーテキストにありました。ケリーはより洗練された聴衆のために書いていたので、私は彼の半ページの証拠に多くの説明を加えなければなりませんでした。ケリーの証明が間違っていることに気づいたとき、私は5ページを書きました。最近、私は説得力のある間違った証明で証明スタイルについての講義を説明したかったので、ケリーに頼りました。彼の証拠には何の問題もありませんでした。明らかに正しいようです!証拠を読んで再読することで、私の記憶が失敗したか、20年前に非常に愚かだったと確信しました。それでも、ケリーの証明は短く、良い例として役立つので、構造化された証明として書き直し始めました。

...このスタイルは、私がMartin Abadiと書いた論文の中で、通常の定理の証明に最初に適用されました。彼はすでに従来の証明を書いていました-私たちと、おそらく審判を納得させるのに十分な証明です。定理は正しいものの、構造化されたスタイルで証明を書き直したところ、ほぼすべての人に重大な間違いがあることがわかりました。間違った証明が間違った定理につながらないかもしれないという希望は、次のコラボレーションで破壊されました。何度も何度も予想を立てて、黒板に証明スケッチ(説得力のある従来の証明に簡単に変えることができたスケッチ)を作成します。それ以来、慎重で構造化された証拠なしに結果を信じたことはありません。


6
同じ論文:「逸話的な証拠は、数学雑誌に掲載されたすべての論文の3分の1が、小さな誤りだけでなく、不正確な定理と証明を含むことを示唆している」。まあ、それは90年代でしたが、今日はそんなに違いますか?おそらく、当時存在していたこれらの論文はまだ存在し、すべてが積み重なっています...ですから、論文で提供される数学的証明に誤りが少ないとは完全に確信していません。
MarkokraM

魅力的な逸話ですが、質問に直接答えたり関与したりすることはありません。回答を編集して、尋ねられた質問に直接回答しますか?あなたは数学的な証明がコンピューターコードを書くのと同じくらい間違っていると主張していますか?提供できるという証拠はありますか?逸話や2つは実際にそれを実証していませんか?
DW

@DW私がレスリーにメールメッセージを送信した場合、彼はその主張についてさらなる証拠を与えることができます。
MarkokraM

3
@DWレスリーは、彼の誠実な回答の中で、彼の同僚が当時のMath Reviewsに掲載された51の証拠で調査を行ったと語った。彼の意見では、それは逸話以上のものですが、いくつかの事実のために強力な証拠には適合しません。以前に発行された論文などの誤った証明を使用したため、証明に関するいくつかのエラーが発生したため、ケースはより複雑でした。素晴らしい研究トピックになりますが、多くの作業が必要です。プログラムで数学の証明を検証する方法は、依然として大きな問題です。インタラクティブな証明支援用に作成されたアプリは非常に初期の段階にあります。少なくともそれらのインターフェース。
MarkokraM

@DW逸話1つまたは2つは、数学的な証明が「正しい」ように見えるが、実際には不健全である様子を示しています。複雑なコンピューターアルゴリズムを作成し、数学的証明を行い、数学的証明のようなコンピューターアルゴリズムを作成して、詳細の多くのバグによって高レベルの「アルゴリズム」が裏切られる方法を発見しようとした人まったく驚くことではありません。
Yakk

39

大きな違いの1つは、通常、プログラムは入力で動作するように記述されているのに対して、数学的な証明は一般に一連の公理と既知の定理から始まることです。十分に一般的な証拠を得るために複数のコーナーケースをカバーする必要がある場合がありますが、ケースとその解決は明示的に列挙され、結果の範囲はカバーされるケースに暗黙的に制限されます。

これをコンピュータープログラムと比較してください。コンピュータープログラムは、可能な入力の範囲に対して「正しい」出力を提供する必要があります。すべての入力を列挙してすべて試すことはほとんど不可能です。さらに悪いことに、プログラムが人間と対話し、その入力が機能を変更できるようにするとしますか?人間は予測不可能なことで有名であり、人間との相互作用を伴う合理的に大きなプログラムへの可能な入力の数は途方もない速度で増加します。失敗が唯一の選択肢である場合、プログラムが使用される可能性のあるすべての異なる方法を予測し、それらすべてのユースケースが機能するか、少なくとも合理的な方法で失敗するようにする必要があります。そして、それはあなたも、だ方法を知っていると仮定していますはずこれらすべてのあいまいなコーナーケースで動作するように。

最後に、大きなプログラムは実際には単一のプルーフと比較することはできません。大規模なプログラムは、おそらく文学の小さなライブラリを収集してレビューすることに似ていますが、その中には回避する必要があるエラーがあるものもあります。小さなアルゴリズムの実装である可能性のある単一のプルーフの規模のプログラムの場合、経験豊富なソフトウェアエンジニアは、特に一般的な些細なエラー(スペルミスなど) )校正で解決する初期の問題に相当します。


14
最後の段落の+1。数学的な証明は原則として互いの上に構築されますが、通常は基本がよく理解されており、コンピューターライブラリに類似しています(バグもありますが...)、実際の証明は長すぎません。対照的に、消費者向けソフトウェアは長く複雑であるため、失敗する機会が多くあります。
ユヴァルフィルマス

6
実際には、消費者ソフトウェアのもう1つの問題は、「正しい」動作が事前に不十分に定義されていることが多いため、後で正しいものが間違ってしまうことです。人々が公理を変えることを決めたということを知るためだけに、証拠を書き込もうとするようなものです。表記法で修正できますよね?
ダンブライアント

2
@DanBryantその状況は数学でも起こります。特に、用語の定義は時間とともに変化し、多くの場合、使用されたとおりにあいまいです。Imre Lakatosの「Proofs and Refutations」では、これを「ポリゴン」という用語で説明しています。同様のことが「機能」でも発生しましたが、程度は「積分」でも発生しました。今日でも、「カテゴリ」は明確なものではなく、証明と定理は正確にあなたが何を意味するかに応じて失敗する可能性があります。
デレクエルキンズ

25

彼らは、コンピュータの問題は、あなたが彼らに伝えることを正確に行うことだと言います。

これは多くの理由の1つかもしれないと思います。

コンピュータープログラムでは、ライター(あなた)は賢いが、リーダー(CPU)は愚かであることに注意してください。
しかし、数学的な証明があれば、ライター(あなた)は賢く、リーダー(校閲者)も賢いのです。

これは、あなたがコンピュータで「まあ、あなたは私が何を意味するか知っている」状況に入る余裕がないことを意味します。あなたの意図を知らなくても、あなたが言うことを正確に行います。

たとえば、これが何らかの証明のステップだとしましょう:

x2+4x+3x+3=(x+1)(x+3)x+3=x+1

x2+4x+3x+3x=3


3
素晴らしい答えです!ただし、コンピュータとして、「不必要に」という言葉の使用に反対します。;)[これが-x複合であることを証明することを目的とした、より大きな証明のほんの一歩であったとしよう。このステップは事実間違っているとき-x = 3に完了証明の正しさに非常に関連性がある]!
Quuxplusone

@Quuxplusone:= P
Mehrdad

コンピューターはシンボリック数学と非決定的書き換えルールも使用できますが、C ++のように使用する言語はすべて非常に低レベルであり、古代の技術に基づいています(CはAlgol 60よりも機能が少ないなど)。唯一の例外は、イドリス/アグダ、シンボリックソルバーを備えたLisp、Mathematicaなどの証明/チェック言語です。 ja.wolframalpha.com/input/...
aoeu256

23

Yuvalの答えで対処されなかったと思う問題の1つは、異なる動物を比較しているようだということです。

nn!

プログラムのセマンティックプロパティの検証は決定できません(ライスの定理)。同様に、1次述語論理のステートメントが真であるかどうかの確認も決定できません。要点は、問題の見方と実際の硬度に違いはないということです。一方、プログラム(コンパイラー)の構文特性について推論することができます。これは、証明を検証できるという事実に類似しています。バグ(コードは私が望むことをしません)はセマンティックなので、それらを正しいものと比較する必要があります。

Yuvalを強化し、正式なシステムで記述および検証できる数学的証明を書くというモチベーションでフィールド全体が成長したので、検証プロセスでさえ些細なことではないと言います。


18

前者が後者よりもはるかに扱いやすいように、誤りのない数学的証明を書くことと、誤りのないコンピューターコードを書くことの何がそんなに違うのですか?

主な理由はi 等性(同じ入力に対して同じ結果を与える)と不変性(変わらない)だと思います。

火曜日に読まれた場合、または1999年から2000年に進んだときに数学的な証明が異なる結果を与える可能性がある場合はどうなりますか?数学的証明の一部が数ページ前に戻り、数行を書き直し、その時点から再び開始する場合はどうでしょうか?

このような証明は、コンピューターコードの通常のセグメントと同じくらいバグになりやすいと確信しています。

他の二次的な要因もあります:

  1. 数学者は通常、重要な/公開可能な証明を書く前に、はるかに教育を受けています。セルフタイトルのプロの開発者の1/4は6年未満前にコーディングを開始しました(SO調査2017を参照)が、ほとんどの数学者は10年以上の正式な数学教育を受けていると思います。
  2. 数学的な証明がコンピュータコードと同じレベルの精査に保持されることはめったにありません。単一のタイプミスはプログラムを破壊する可能性がありますが、数十のタイプミスでは証明の価値(読みやすさだけ)を破壊するには不十分な場合があります。
  3. 悪魔は詳細にあり、コンピューターコードは詳細をスキップできません。証明は、単純/ルーチンと見なされる手順を自由にスキップできます。現代の言語で利用可能ないくつかの素晴らしい構文糖がありますが、これらはハードコーディングされており、比較ではかなり制限されています。
  4. 数学は古く、より強固な基盤/コアを持っています。確かに、数学には新しくて光沢のあるサブフィールドがたくさんありますが、基本的な原則のほとんどは何十年も使用されてきました。これは安定性につながります。反対に、プログラマーは基本的なコーディング方法にまだ同意していません(アジャイル開発とその採用率について尋ねるだけです)。

プログラミングの「in等性」に相当するものは機能的な純度であり、Haskellなどの一部の言語で認識およびサポートされていることに言及する価値があります
ファラプ

12

ユヴァルが書いたことに同意します。しかし、もっと簡単な答えもあります:実際には、ソフトウェアエンジニアは通常、プログラムの正当性をチェックしようとさえしません。

それにはさまざまな理由があります。1つは、ほとんどのソフトウェアエンジニアが数学的に問題を明確に定式化するスキルを持たず、正確性の証明の書き方を知らないことです。

もう1つは、複雑なソフトウェアシステム(特に分散システム)の正確性条件を定義することは、非常に困難で時間のかかる作業であるということです。彼らは数週間のうちに機能すると思われる何かを持っていることが期待されています。

もう1つの理由は、プログラムの正確性が、明確なセマンティクスを持たない他のユーザーによって記述された他の多くのシステムに依存していることです。ライブラリ/サービスに観察可能な動作がある場合(契約の一部ではない場合)、最終的に誰かが最終的にそれに依存するというハイラムの法則があります。それは本質的に、数学の補題のような明確な契約を持つモジュール形式のソフトウェアを開発するという考えが実際には機能しないことを意味します。リフレクションが使用される言語では悪化します。今日のプログラムが正しい場合でも、誰かがその依存関係の1つで些細なリファクタリングを行うと、明日故障する可能性があります。

実際には、通常発生するのはテストがあることです。テストは、プログラムから期待されるものとして機能します。新しいバグが見つかるたびに、テストを追加してそれをキャッチします。ある程度は機能しますが、正確性を証明するものではありません。

人々が正しさを定義するスキルも、正しいプログラムを書くスキルも、そうすることも期待していない場合、そうするのはかなり難しいことですが、ソフトウェアが正しくないことは驚くことではありません。

しかし、最終的には、ソフトウェアエンジニアリングはコードレビューによって行われることをお勧めします。つまり、プログラムの作成者は、少なくとも1人の他の人にプログラムが正しく機能することを納得させなければなりません。それが、いくつかの非公式の高レベルの議論が行われているポイントです。しかし、ここでも通常、正確性の明確で厳密な定義または正確性の証明に近いものは何も起こりません。

数学では、人々は正確さに焦点を合わせています。ソフトウェア開発では、プログラマーが気にしなければならないことが多くあり、それらの間にはトレードオフがあります。バグのないソフトウェアまたは正確性の適切な定義(要件が時間とともに変化する)さえあれば理想的ですが、他の要因とトレードオフする必要があり、その中で最も重要なものの1つは、既存のソフトウェアの開発に費やされる時間です開発者。そのため、実際にはより良い場所での目標とプロセスは、ソフトウェアをバグのないものにするのではなく、可能な限りバグのリスクを軽減しています。


プログラマーと数学者の間で正式に(つまり、マシンチェックの方法で)正しさの仕様を策定し、たとえば10KLOC以上のプログラムに対して正しいコードを証明することで、だれが悪いのか、実際はわかりません。一方では、ほとんどのプログラマーが十分に発達した定理証明スキルを持っていないことは完全に正しいです。一方、大規模な形式的証明は大規模なプログラムに似ており、管理するには基本的にソフトウェアエンジニアリングのスキルが必要です。このようなプログラムの正当性の非公式な証拠は、正しいとは思えません。
デレクエルキンス

多分。いずれにせよ、単に明確にするために、私は答えで正式な証明を取っておらず、アルゴリズム論文で言うレベルでの非公式な証明だけを取り上げています。
カヴェー

11

すでに多くの良い答えがありますが、数学とプログラミングが同じではない理由はまだたくさんあります。

1 数学的な証明は、コンピュータープログラムよりもはるかに単純になる傾向があります。仮説的証明の最初のステップを考えてみましょう:

aを整数とする

bを整数とする

c = a + bとする

これまでのところ、証拠は問題ありません。それを同様のプログラムの最初のステップに変えましょう。

a = input();

b = input();

c = a + b;

すでに無数の問題があります。ユーザーが実際に整数を入力したと仮定すると、境界をチェックする必要があります。ある-32768より大きい(または任意のシステム上の分intはあるが)?ある未満32767?bについても同じことを確認する必要があります。また、abを追加したためa + bでない限りプログラムは正しくありません。が-32768より大きく、32767より小さい。これは、数学者が無視できることをプログラマが心配しなければならない5つの別個の条件です。プログラマーはそれらを心配する必要があるだけでなく、それらの条件のいずれかが満たされない場合に何をすべきかを考え、それらの条件を処理する方法を決定したときは何でもするコードを書く必要があります。数学は簡単です。プログラミングは難しいです。

2質問者は、コンパイル時エラーと実行時エラーのどちらを指しているのかは言いませんが、プログラマーは一般にコンパイル時エラーを気にしません。コンパイラはそれらを見つけて、簡単に修正できます。タイプミスのようなものです。初めてエラーなしで複数の段落を入力する頻度はどれくらいですか?

3 トレーニング。幼い頃から数学を学ぶように教えられており、小さな間違いの結果に何度も直面しています。訓練を受けた数学者は、通常中学校で多段階代数の問題の解決を開始しなければならず、1年の間毎週そのような問題を数十(またはそれ以上)行わなければなりませんでした。マイナス記号が1つ落ちただけで、問題全体が間違っていました。代数の後、問題はより長く、より困難になりました。一方、プログラマーは通常、正式なトレーニングがはるかに少ないです。多くは(少なくとも最初は)独学であり、大学まで正式な訓練を受けていませんでした。大学レベルでさえ、プログラマーはかなりの数の数学の授業を受けなければなりませんが、数学者はおそらく1つまたは2つのプログラミングの授業を受けました。


10

私はユヴァルの答えが好きですが、少しの間それをリフしたいと思いました。数学の証明を書く方が簡単だと思う理由の1つは、プラトニックな数学のオントロジーがどのように機能するかということです。私が意味するものを見るために、以下を考慮してください:

  • Mathの関数は純粋です(関数を呼び出した結果全体が戻り値に完全にカプセル化されます。戻り値は決定論的であり、入力値から完全に計算されます)。
  • Mathには突然変異や再割り当てはありません(そのようなものをモデル化する必要がある場合、関数とシーケンスが使用されます)。
  • 数学は参照的に透過的であり(たとえば、ポインターなし、名前による呼び出しと値による呼び出しの概念はありません)、数学オブジェクトには拡張等式セマンティクスがあります同じこと)。

それは議論の余地ですが上記の制限が可能かどうかを書いて簡単にプログラムを、私は上記の制限が作るのですかという幅広い合意があると思う推論を容易にプログラムについては。数学の証明を書くときに行う主なことは、現在書いている証明の理由です(プログラミングとは異なり、抽象化が無料なので、数学で努力を繰り返す必要はありません)ので、一般的に主張する価値があります上記の制限。


7

基本的な数学的証明は、生きている人間のニーズを満たすように設計された実際のアプリケーションにはなりません。

人間は、コンピュータープログラムの領域で日常的に行われている可能性のあるものの欲望、ニーズ、および要件を変更します。

前者が後者よりもはるかに扱いやすいように、誤りのない数学的証明を書くことと、誤りのないコンピューターコードを書くことの何がそんなに違うのですか?

数学的問題と同じくらい明確な要件があれば、完璧なプログラムを書くことができます。ダイクストラのアルゴリズムがグラフ上の2点間の最短経路を見つけられることを証明することは、任意の入力を受け入れ、その中の2点間の最短点を見つけるプログラムを実装することと同じではありません。

管理するメモリ、パフォーマンス、およびハードウェアの問題があります。アルゴリズムを作成するときにそれらについて考えられないように、純粋で機能的な構造を使用してこれを管理できると思いますが、コンピュータープログラムはハードウェアの「実際の」世界に住んでいますが、数学的な証明は...「理論」にあります。


または、より簡潔にするために

ここに画像の説明を入力してください


4

それを別の角度から見ると、学問以外の環境ではしばしばお金になります。

他の投稿がよく主張しているように、Mathは単一の抽象的な仕様であるため、証明するためには、その仕様内で一貫して機能する証明が必要です。コンピュータープログラムは、数学の抽象的な仕様の多くの実装で動作する可能性があります-つまり、ある言語、またはハードウェアメーカーが浮動小数点数学を実装する方法は、結果にわずかな変動を引き起こす可能性がある別の言語とわずかに異なる場合があります。

そのため、書き込む前にコンピュータープログラムを「証明」するには、プログラムが実行する可能性のあるすべてのハードウェアの組み合わせについて、ハードウェアレベル、オペレーティングシステムレベル、ドライバーレベル、プログラミング言語、コンパイラー、インタープリターなどでロジックを証明する必要があります実行される可能性があり、考えられるあらゆるデータを取り込む可能性があります。宇宙ミッション、兵器システム、原子力制御システムでこのレベルの準備と理解が得られるでしょう。失敗とは、数百億ドルの損失と潜在的に多くの命の損失を意味しますが、それ以外のことはあまりありません。

「毎日」のプログラマーやビジネスでは、ほぼ正しいコードで一定レベルの精度を受け入れ、使用可能な製品を販売する方がはるかに費用効率が高く、開発者はバグが発見されたときに遡って修正することができます使用法。


3
あなたは数学が何であるかという狭い視野と、コンピュータープログラムが「証明」することの必要性についての広すぎる視野を持っているようです。プログラムが正しいことを証明するためにシステム全体が正しいことを証明する必要はありません。他のコンポーネントが仕様を満たしていると仮定して、それが正しいことを証明する必要があります。そうでない場合、それはあなたのプログラムのせいではありません。一方で、IEEE754の実装のバリエーションなど、コンポーネントの仕様に含まれない詳細に依存しているためにプログラムが破損した場合、それあなたの責任です。
デレクエルキンス

公正なコメント。私の学歴ではないので、いくつかの用語を誤用している可能性があります。私の以前のコメントのために、他のコンポーネントが完璧であると仮定するのは賢明なことではないと感じていますが。
navigator_

4

あなたの推論は有効だと思うが、あなたの意見はそうではない。数学的な証明は、両方が人間によって書かれている場合、プログラムよりもフォールトトレラントではありません。ダイクストラはすでにここで引用されていますが、追加の引用を提供します。

しかし、限られた能力で計算が望ましい効果を確立することを保証するのに十分であるような方法で計算を整理しなければなりません。この整理にはプログラムの構成が含まれ、サイズの次の問題に直面しています。プログラムテキストの長さ。この問題も明示的に認識させる必要があります。テキストを読み書きできる範囲は、そのサイズに大きく依存しているという事実を引き続き認識しておく必要があります。[...]

「明快さ」が量的な側面を明らかにしたという事実に読者の注意を向けたいと思うのと同じ気分で、不思議なことに、多くの数学者は気付いていないようです。10ページの条件が満たされた場合の結論の妥当性を示す定理は、定理がアピールされるたびにすべての条件を検証する必要があるため、便利なツールとはいえません。ユークリッド幾何学では、ピタゴラスの定理は任意の3点A、B、Cを保持するため、AとCを通る直線は、BとCを通る直線に直交するように描かれます。または、ポイントA、B、Cのすべてが一致しますか?しかし、これはピタゴラスの定理を使用できる便利さの主な原因のようです。

要約:気の遅い人間として、私は頭が非常に小さく、それと一緒に暮らし、私の限界を尊重し、それらを無視しようとするのではなく、完全な信用を与えることを学ぶべきでした。後者の無駄な努力は失敗によって罰せられます。

これは、ダイクストラの構造化プログラミングの最初の章の最後の3つの段落をわずかに編集したものです。

おそらくこれを言い換えて、あなたの質問により良く適用するために:正しさは主に証明の大きさの関数です。長い数学的証明の正確性を確立することは非常に困難です(公開された「証明」の多くは、実際に誰も検証していないため、不確実性の辺りに住んでいます)。しかし、些細なプログラムの正当性を些細な証拠と比較した場合、おそらく顕著な違いはありません。ただし、自動化されたプルーフアシスタント(より広い意味では、Javaコンパイラはプルーフアシスタントでもあります)では、多くの基礎を自動化することでプログラムが勝ちます。


「長い数学的証明」とはどういう意味ですか?グラフのマイナー定理の証明は非常に長いですが、実際には誰からも議論されていません。Feit-Thompsonの定理にはかなり長い証明がありますが、決して真の意味ではありませんでした。証明とプログラムの長さをどのように比較しますか?言葉の数?似たような複雑さ(長さ)のプルーフとプログラムを比較しても、プルーフとプログラムの間に目立った違いはありませんか?
ユヴァルフィルマス

@YuvalFilmusは引用のように:10ページのアサーションは人間にとって長いものです。プログラムの長さを判断するにはどうすればよいですか?まあ、Dikstraはメトリックを提供しました:テキストの長さ。私はそれがあまりにも単純すぎるかもしれないと思うが、それでもそれは良い発見的方法である。他の、より興味深いメトリック、などの、例えば、存在する循環的複雑度
wvxvw

3

他の答えが彼らの答えに触れているように(私は詳しく述べたい)、しかし問題の大部分はライブラリの使用法です。完全なドキュメント(バグのないコードとして一般的)であっても、ライブラリの完全な知識をライブラリを使用するすべてのプログラマに転送することは不可能です。プログラマーが自分のライブラリーを完全に理解していない場合、使用時にミスを犯す可能性があります。これらは、コードが機能しないときに発見される重大なバグにつながる場合があります。しかし、軽微なバグの場合、これらは気付かない場合があります。

同様の状況は、数学者が既存の証明と補題を完全に理解せずに使用した場合です。彼ら自身の証拠はおそらく欠陥があるだろう。これは、使用するすべてのライブラリを完全に学習することです。これは実際には非常に時間がかかり、プログラマーが持っていないドメインの知識を必要とする場合があります(DNAシーケンス/タンパク質合成についてはほとんど知りませんが、ライブラリを使用してこれらの概念を扱うことができます)。

もっと簡潔に言えば、ソフトウェアエンジニアリング(実際にはエンジニアリング全般)は、さまざまな抽象化レベルをカプセル化することに基づいており、人々が専門とする問題の小さな領域に集中できるようにします。各レイヤー間。その通信が完全でない場合、問題が発生します。


3
数学者が使用する証明や補題を「完全に理解」していると思うのはなぜですか?ここでデモンストレーションしようとしている数学者とプログラマーの違いはわかりません。
デレクエルキンス

3

すべての素晴らしい答えの後に私は独創的になろうとします。

プログラム証明です

カリー・ハワード同型が教えてくれる、あなたのプログラム内の型は定理であり、実際のコードがその証拠です。

確かに、これは非常に抽象的な高レベルのビューです。おそらく、あなたが意味する問題は、典型的なコードを書くのは低すぎるので難しくなるということです。ほとんどの場合、「マシンに何をすべきかを伝える必要があります」。または、別の方法でこれを調べると、数学者は抽象化が本当に得意です。

サイドノートとして:「ストリームの音楽」は、両者の間の最も美しい橋の1つです。これは、基本的には「私が欲しいと言うことができるように物事を設定し、これをしている途中」とマシンが魔法のように行い、これを必要に応じて正確に。


これで問題が解決するかどうかはまったくわかりません。OPは、強力な型システムを備えたプログラミング言語について話していることを示すものではなく、より一般的な型システムを意味していると思います。したがって、この場合、Curry-Howardは些細なことです。
6005

私はそれがCまたは同様のものについては少し手に負えないことを知っています。しかし、私のポイントは、数学は典型的なCS初心者が考えるよりも近いということです!
オレグLobachev

1
あなたは、カリー・ハワード同型性の「不注意な観察者」であるようです。プログラムと証明の間に同型性があったとしても、プログラムを書く行為と証明を書く行為がまったく似ているということにはなりません。実際、すべての「興味深い」または「典型的な」プログラムが典型的な証明に対応していない場合や、その逆の場合もあります。
離散トカゲ

@Discretelizard「興味深い」プログラムが「典型的な証明」に対応しないというのは、明らかにそうではありません。誰かの「典型的な証明」を取り、否定できないほど面白いプログラム(のスケッチ)(ガウスの消去に密接に関連するもの)を作成する例を次に示します。適切に正確な型を備えていると、ほとんどの「興味深い」プログラムは有用な補題または定理になると思いますが、多くの(建設的な)証明には実際の計算上の重要性はありません。
デレクエルキンス

3

他の多くの答えのどれも、以下を指摘していません。数学的証明は、無限のメモリと無限の計算能力を持つ架空の計算システム上で動作します。したがって、任意の大きな数値を無限の精度で保持でき、計算で精度を失うことはありません。

π


2
「数学的な証明は、無限のメモリと無限の計算能力を持つ架空のコンピューティングシステムで動作します。」ほとんどの数学的証明は、実数(「無限精度」がある場合)などの形式的な代数システムで「動作」します。これはプログラムでも実行できます。これを正確に行う、いわゆるコンピューター代数システム(CAS)があります。さらに、数学のすべての分野は、すべての実数を有限の浮動小数点数として正確に表すことができないという事実に関係しています。あなたは数学とプログラミングを区別していないところにいると思います。
離散トカゲ

1
@Discretelizard、はい、任意の精度で特別なパッケージが存在しますが、それでも利用可能なメモリは実際の達成可能な精度を制限します。また、特別なパッケージです。このようなパッケージを使用してプログラミングを行うのはごくわずかであり、ほとんどがアカデミックな環境です。
クロバー

π

@Discretelizard、私のポイントはまだ残っていると思う、ほとんどのプログラマーはそのようなCASシステムを使用していない。実際のプログラミングには遅すぎます。ほとんどのプログラミングは、基本的に、限られた精度の数値での操作を伴います。上位の言語はC、C ++、Python、Javaなどです。デフォルトではCASスタイルの表現を使用しません(ただし、これらを使用してパッケージを作成できます)。あなたの反例は、コンピューター言語/システムの小さなニッチなサブセットです。
クロバー

2
@crobarあなたの答えの問題は、検出されたバグの大部分は浮動小数点エラーまたは整数オーバーフローによるものではないということです(ただし、それらはまともな数を提供しますが、これらの側面は間違いなくプログラムの完全な正確さをはるかに低くします)。ただし、数学者は、パフォーマンス、市場投入までの時間、保守性、難易度が高い場合に要件を変更する能力の制限など、プログラマーの懸念の多くを欠いているというより一般的な主張をすることができます。
デレクエルキンズ

3

そうではありません。数学的な証明は本質的にまったくバグが多く、読者がコンパイラよりも寛容であるというだけです。同様に、コンピュータプログラムの読者は、少なくともそれを実行しようとするまで、それが正しいと信じ込ませやすい。

たとえば、数学的証明をZFCのような正式な言語に翻訳しようとすると、バグも含まれます。これは、これらの証明が非常に長くなる可能性があるため、証明を生成するプログラムを作成せざるを得ないためです。基本的な証明を形式化するための積極的な研究はありますが、危険にさらされている人はほとんどいません。

そして確かに、数学はBSODを取得できます! 初めてじゃない!

ここに画像の説明を入力してください

十分に検証されたすべての数学的な証明が本質的に正しい、または正しくできるというこの正統的な考え方は、職場でのソフトウェアプロジェクトの動機付けと同じものです。完全な機能—それは明確な最終製品につながる反復プロセスです。

これが裏返しです。ご覧ください、私たちはすでに資金を調達し、ビジネスコンセプトを検証しました。すべての文書はここで読むことができます。実行する必要があるだけで、それは確かなことです!

ヒルベルトも気の毒に思わないでください。彼は自分が何に夢中になっているか知っていました。ただのビジネスです。

本当に確認したい場合は、ケースバイケースですべてを取り、独自の結論を導きます!


3

プログラムが数学の証明よりもエラーを起こしやすい2つの重要な理由がわかります。

1:プログラムには、時間とともに変化する変数または動的オブジェクトが含まれますが、プルーフの数学オブジェクトは通常静的です。したがって、数学の表記法は推論の直接的なサポートとして使用できます(a = bの場合、これは当てはまります)。これはプログラムで機能しません。また、この問題は、プログラムが並列であるか、複数のスレッドがある場合、さらに悪化します。

2:数学では、比較的きちんと定義されたオブジェクト(グラフ、多様体、リング、グループなど)を想定しますが、プログラミングでは、非常に乱雑でかなり不規則なオブジェクトを扱います:有限精度演算、有限スタック、文字整数変換、ポインター、コレクションが必要なガベージ等...したがって、正確性に関連する条件の収集を念頭に置くことは非常に困難です。


3

次の2つの異なる「カテゴリ」を区別する必要があります。

  • 擬似プルーフ(または擬似コード)-それは本で見るものです。自然言語で書かれています(例:英語)。それが、数学(またはアルゴリズム)を学ぶために使用すべきものです。
  • フォーマルプルーフ(またはフォーマルコード)-プルーフ(またはコード)を機械的に検証可能(または実行可能)にする必要がある場合にそれを記述します。このような表現には、「人間の知性」は必要ありません。事前に定義されたいくつかの手順(通常は今日のコンピューターで行われます)に従うことで、機械的に検証(または実行)できます。

私たちは何千年もの間擬似コードを使用してきました(例:Euclidsアルゴリズム)。(CやJavaのような正式な言語で)正式なコードを書くことは、コンピューターの発明後に非常に人気があり有用になりました。しかし、悲しいことに、正式な証明(Principia MathematicaやMetamathなどの正式な言語)はあまり人気がありません。そして、今日誰もが疑似証明を書いているので、人々はしばしば新しい証明について議論します。それらの間違いは、実際の「証明」から数年、数十年、または数世紀後にも発見されます。


3

私は参照を見つけることができませんが、トニー・ホアはかつて次の行に沿って何かを言ったと思います:プログラムのチェックと証明のチェックの違いは、証明を一度に2行チェックできることです。

一言で言えば、地域性です。

証拠は、簡単に確認できるように書かれています。プログラムは、実行できるように作成されています。このため、プログラマーは通常、プログラムをチェックする人に役立つ情報を省きます。

xが読み取り専用であるこのプログラムを検討してください

    assume x >= 0
    p := 0 ;
    var pp := 0 ;
    while( x >= pp + 2*p + 1 ) 
    {
        var q := 1 ;
        var qq := q ;
        var pq := p ;
        while(  pp + 4*pq + 4*qq <= x )
        {
            q, pq, qq := 2*q, 2*pq, 4*qq ;
        }
        p, pp := p + q, pp + 2*pq + qq ;
    }
    assert  p*p <= x < (p+1)*(p+1)

実行は簡単ですが、確認は困難です。

ただし、欠落しているアサーションを再度追加すると、割り当ての各シーケンスがその事前条件と事後条件に照らして正しいこと、およびループごとにループの事後条件が暗黙的に含まれることをチェックするだけで、プログラムをローカルでチェックできます不変量とループガードの否定。

    assume x >= 0
    p := 0 ;
    var pp := 0 ; 
    while( x >= pp + 2*p + 1 ) 
        invariant p*p <= x 
        invariant pp == p*p
        decreases x-p*p 
    {
        var q := 1 ;
        var qq := q ; 
        var pq := p ; 
        while(  pp + 4*pq + 4*qq <= x )
            invariant (p+q)*(p+q) <= x
            invariant q > 0 
            invariant qq == q*q 
            invariant pq == p*q 
            decreases x-(p+q)*(p+q)
        {
            q, pq, qq := 2*q, 2*pq, 4*qq ;
        }
        assert (p+q)*(p+q) <= x and pp==p*p and pq==p*q and qq==q*q and q>0
        p, pp := p + q, pp + 2*pq + qq ;
    }
    assert  p*p <= x < (p+1)*(p+1)

元の質問に戻って:数学的な証明を書き留めるのは、コンピューターコードを書くよりもフォールトプルーフなのはなぜですか?プルーフは読者が簡単にチェックできるように設計されているため、著者が簡単にチェックできるため、アラート作成者はプルーフで論理エラーを起こさない(または少なくとも保持する)傾向があります。プログラミングするとき、コードが正しい理由を書き損ねることがよくあります。その結果、プログラムの読者と作成者の両方がコードをチェックすることは困難です。その結果、作成者はエラーを作成(および保持)します。

しかし、希望はあります。プログラムを書くときに、プログラムが正しいと思う理由も書き留めておけば、コードを書いているときにチェックできるので、バグの少ないコードを書くことができます。これには、他の人がコードを読んで自分でチェックできるという利点もあります。


2

証明を書いたり、コードを書いたりすることは、実際にはもっと難しいのか、原理的には難しいのかを尋ねることができます。

実際には、証明はコーディングよりもはるかに困難です。大学レベルの数学を2年間受けた人はほとんどいません。たとえ些細なものであっても、証明を書くことができます。大学レベルのCSを2年間受けた人の間では、おそらく少なくとも30%がFizzBu​​zzを解決できます。

しかし、原則として、それが逆の場合には根本的な理由があります。少なくとも原則として、判断や判断を一切必要としないプロセスを通じて、証拠の正当性を確認できます。プログラムはできません-プログラムが停止するかどうかは、所定のプロセスを介して判断することさえできません。


3
2年間の大学レベルの数学は、2年間の証明の作成(または証明の作成に時間を費やすこと)に焦点を合わせたという意味ではありません。いえ、私の印象では、中/早期高校のジオメトリクラスが証明を含めることが一般的であるということですので、明らかに我々はできるにも13歳が上の教育未満の学年で簡単な証明を書くことができることを期待しますトピック。段階的な代数計算も本質的に証明です。あなたは、プログラミング方法が低すぎることと、方法が高すぎることを証明するための「自明」の基準を設けていると思う。
デレクエルキンス

3
同じ方法でプログラムを書くことができます。作成するすべての関数/手順が、正式な仕様と、仕様を満たしていることを証明する(Coqで言うなど)必要があるという要件を想像できます。その後、判断や理解を一切必要としない方法で、その証拠を正確にチェックする方法があります。
DW

@DW:(1)すべての場合に目的の動作を完全に指定できる、(2)必要な証明が存在する(つまり、問題が決定できないわけではない)、(3)証明が存在する場合、それを見つけることができます。少なくともいくつかの場合(おそらくほとんどすべての場合)、これら3つの仮定はすべて間違っていると思います。再3、いくつかの証明は簡単かもしれませんが、多くの証明を見つけるのは非常に難しいことに注意してください。
ベン・クロウェル

@DerekElkins:些細な証拠さえ書くことができる大学生はほとんどいないという私の主張は、私自身の学生との経験に基づいています。これはコミュニティカレッジにあるため、YMMVです。一部の高校の幾何学クラスに大量の校正が含まれているという事実は、すべての大学生が校正を書くことができるという事実に翻訳されていません。彼らはまた、基本的な代数のやり方を知っているはずですが、私の学校では、新入生の計算学生の約半分はできません。
ベン・クロウェル

それは、答えに追加する良い説明であり、プログラムが正しいかどうかを確認するために同じアプローチをとることができない理由を説明するためです。一般的に(2)と(3)は、実際問題としても原則としてもめったに問題になりません(プログラムが正しいことを証明できない場合は、正しいことを証明できるまで別の方法で記述してください)。しかし、あなたの(1)重要なポイントであり、証明のために私たちがプログラムと同じことをすることが難しくなる理由を説明するための答えを強化すると思います。
DW

2

真である数学的ステートメントのごく一部のみが実際に証明できます。さらに重要なことは、すべての真のステートメントが証明されることを可能にする数学的公理の非自明な(*)セットを構築することは不可能であろう。コンピューターでできることのほんの一部を実行するプログラムを作成するだけでよい場合、証明可能な修正ソフトウェアを作成することは可能ですが、コンピューターは証明可能な修正の範囲を超えることを行うことがしばしば求められますソフトウェアが達成できる。

(*)すべての真のステートメントを列挙して証明できる公理のセットを定義することは可能ですが、それらは一般的にあまり興味深いものではありません。公理のセットを正式に分類することは可能ですが、比較的話せる、自明でないものに、重要なのは、真実であるが証明できない文の証明可能な存在がセットの欠陥ではないということです公理の。公理を追加して既存の真であるが証明不可能なステートメントを証明可能にすると、他のステートメントは真になりますが、それらは証明できません。


1
「実際に証明できるのは、真である数学的ステートメントのごく一部のみです。」-「部分」の測定方法は?これは何らかの確率分布の下にありますか?この声明を裏付ける証拠はありますか?
DW

「コンピューターはしばしば、正しいと思われるソフトウェアが達成できる範囲を超えることを行うように求められます。」-これについての証拠はありますか?例はありますか?「原則として正しいことが証明できる範囲を超えて」、「実際に証明することを合理的に想像できる範囲を超えて」と主張していますか?
DW

@DW:XとYが真であるが証明不可能な直交ステートメントである場合、すべての証明可能なステートメントPに対して、少なくとも2つの直交ステートメント(PおよびX)と(PおよびY)があります-証​​明可能。無限のセットを扱うとき、そのようなロジックは必ずしも何も証明しません。なぜなら、奇数の整数ごとに2つの偶数の整数(4x)を識別できるため、同様のロジックを使用して奇数の整数の2倍の偶数の整数があることを示すことができるからです(4x + 2)他の奇数の整数に関連付けられていませんが、もちろん偶数と奇数の整数のカーディナリティは同じです。
supercat

@DW:「小さな部分」というフレーズは、実際に証明できる真のステートメントの割合を説明する上で本当に意味があるかもしれませんが、すべての真のステートメントを証明できないことは「欠陥」ではないことを理解することは有益だと思います。コンピューターに関しては、多くの分野で、非常に小さいがゼロではない障害の可能性があるアルゴリズムを日常的に使用しており、確率が許容できるほど低くなるように調整します(たとえば、流星によって打たれる機器の確率以下)。多くの場合、様々な故障モードは、しかし、独立しているわけではないので、それは本質的に不可能...かもしれ
supercat

...さまざまな障害の組み合わせの確率を判断する。任意の1分間の故障確率が10 ^ -500に1であると推定した場合、数百桁もずれている可能性がありますが、信頼性の高いシステムを使用できますが、494桁もずれている場合システムは数年に一度程度故障します。
supercat

2
  1. コンピュータープログラムは、実世界でテストされています。限られた数の人しか理解できないという長い数学的証明におけるトリッキーな技術的エラーは、検出されないままでいる可能性が高い。ソフトウェア製品での同じ種類のエラーは、普通のユーザーが気づく奇妙な動作を引き起こす可能性があります。したがって、前提は正しくない可能性があります。

  2. コンピュータプログラムは、便利な実世界の機能を実行します。これを行うために100%正確である必要はなく、正確性の高い基準はかなり高価です。証明は、実際に何かを証明する場合にのみ有用であるため、数学者にとって「100%正しい」部分をスキップすることは選択肢ではありません。

  3. 数学的証明は明確に定義されています。証拠に欠陥がある場合、著者は間違いを犯しています。要件が適切に伝達されなかったため、またはプログラマーが聞いたことがないものとの互換性の問題があるため、コンピュータープログラムの多くのバグが発生します。

  4. 多くのコンピュータープログラムが正しいことを証明することはできません。顔の認識など、非公式に定義された問題を解決する場合があります。または、株式市場予測ソフトウェアのようであり、正式に定義された目標を持っているが、実世界の変数が多すぎる場合があります。


2

人間の活動としての数学の大部分は、証明が人間にとって簡単に検証できるドメイン固有の言語の開発です。

プルーフの品質は、その長さと複雑さに反比例します。多くの場合、検討中の特定の証明内で相互作用する補助概念とともに、ステートメントを作成している現在の状況を記述するための適切な表記法を開発することにより、長さと複雑さが軽減されます。

これは簡単なプロセスではなく、研究の最前線から排除された人々によって目撃されたほとんどの証拠は、数千年ではないにしても数百年、その分野の表記法があった数学分野(代数や分析など)にあります実際に証拠を書き留めるという行為が風のように感じるところまで洗練されました。

しかし、研究の最前線で、特に確立された表記法や十分に開発された表記法の分野にない問題に取り組む場合、正しい証明を書くことでさえ正しいプログラムを書くことの難しさに近づきます。これは、プログラミング言語の設計の類似物を同時に作成し、ニューラルネットワークをトレーニングして正しくコンパイルし、その中に証明を書き、メモリを使い果たし、言語を最適化しようとするためです。言語を学習している脳を反復し、証明をもう一度書くなど。

繰り返しますが、正しい証明を書くことは数学の特定の領域で正しいプログラムを書くことの難しさに近づくと思いますが、数学の進歩という概念は証明の容易さに密接に結びついているため、それらの領域は必然的に若く未開発です検証。

私が言いたいことを言い表す別の方法は、プログラミング言語と数学の両方が、コンピュータープログラムと証明がそれぞれコンパイルできるように設計されているということです。コンピュータープログラムのコンパイルはコンピューターで行われ、通常はプログラム自体の正確さとはほとんど関係のない構文の正確さを保証しますが、プルーフの「コンパイル」は人間によって行われ、同じものである構文の正確さを保証します証明の正確さ。


1

ここでは、リンゴとオレンジを正直に比較しています。 耐障害性バグフリーは同じものではありません。

プログラムが数値2を比較し、3それを言う場合、2 is greater than 3バグのある実装が原因である可能性があります。

# Buggy implementation
function is_a_greater_than_b(a,b):
  return b > a

ただし、プログラムにはまだ障害がありません。2つの数値aを比較する場合、およびはbbがより大きいかどうかを常に示すことができますa。それはあなた(プログラマー)がコンピューターに何をするように依頼することになっていたかではありません。


2
それでは、プログラムでの「障害」の定義は何ですか?
user56834

0

a)コンピュータプログラムは数学の証明よりも大きいので

a.1)数学の証明を書くときよりも複雑なコンピュータープログラムを書くときに使う人が多いと思う。これは、ミスマージンが高いことを意味します。

b)CEO /株主は小さなバグを修正するよりもお金に関心があるため、(開発者として)いくつかの要件/期限/デモを満たすためにタスクを実行する必要があります

c)comp sciの「深い」知識がなくてもプログラマーになることができるので、数学では難しいと思います(私は信じています)

さらに:

NASA:

このソフトウェアにはバグがありません。人間が達成したのと同じくらい完璧です。これらの統計を検討してください。プログラムの最後の3つのバージョン(それぞれ420,000行の長さ)には、それぞれ1つのエラーしかありませんでした。このソフトウェアの最後の11バージョンには、合計17個のエラーがありました。

ソフトウェアのアップグレードを行って、シャトルが全地球測位衛星でナビゲートできるようにします。この変更には、プログラムのわずか1.5%、つまり6,366行のコードが含まれます。その1つの変更の仕様では、電話帳よりも厚い2,500ページが実行されます。現在のプログラムの仕様は30ボリュームを満たし、40,000ページを実行します。

https://www.fastcompany.com/28121/they-write-right-stuff


「コンピュータープログラムは数学の証明よりも大きい」それはプログラムと証明に依存します。そして、これの多くは非常に推測的なようです。
デビッドリチャービー

@DavidRicherbyよく私は、Last fermatの定理やNASAのApollo github.com/chrislgarry/Apollo-11 math.wisc.edu/~boston/869.pdfのようなことを心に留めていまし た。
Exeus

0

基本レベル:

最も単純で最も基本的なレベルで物事を見てみましょう。

数学の場合、
2 + 3 = 5

私は非常に若かったときにそれについて学びました。最も基本的な要素を見ることができます:2つのオブジェクトと3つのオブジェクト。すばらしいです。

コンピュータープログラミングでは、ほとんどの人が高級言語を使用する傾向があります。一部の高レベル言語は、Cのような下位の高レベル言語の1つに「コンパイル」することさえできます。その後、Cをアセンブリ言語に翻訳できます。その後、アセンブリ言語はマシンコードに変換されます。多くの人が複雑さはそこで終わると考えていますが、それは終わりではありません。現代のCPUはマシンコードを命令として受け取り、その後「マイクロコード」を実行してそれらの命令を実際に実行します。

これは、最も基本的なレベル(最も単純な構造を扱う)で、ハードウェアに埋め込まれ、ほとんどのプログラマーが直接使用も更新もしないマイクロコードを扱っていることを意味します。実際、ほとんどのプログラマーはマイクロコード(マイクロコードよりも0レベル高い)に触れないだけでなく、ほとんどのプログラマーはマシンコード(マイクロコードよりも1レベル高い)やアセンブリ(マイクロコードよりも2レベル高い)にも触れません(おそらく、大学時代の少しの正式なトレーニングを除く)。ほとんどのプログラマーは、3レベル以上だけ時間を費やします。

さらに、アセンブリ(通常、人々が受けるレベルと同じくらい低いレベル)を見ると、個々のステップは通常、訓練を受け、そのステップを解釈するためのリソースを持っている人々によって理解されます。この意味で、アセンブリは高レベルの言語よりもはるかに簡単です。ただし、アセンブリは非常に単純であるため、複雑なタスクや平凡なタスクを実行するのも非常に面倒です。上位言語はそれから私たちを解放します。

「リバースエンジニアリング」に関する法律では、裁判官は、コードを理論的に一度に1バイト処理できるとしても、現代のプログラムは数百万バイトを必要とすると宣言したため、実現可能な努力。(したがって、内部開発は、著作権法の一般化された「コピーを作成しない」規則の違反とは見なされませんでした。) )

近代化:

286向けのコードを実行していますか?または、64ビットコードを実行しますか?

数学は、数千年にわたってさかのぼる基礎を使用します。コンピュータでは、人々は通常、20年前の何かへの投資は無駄なリソースの無駄だと考えています。これは、数学をより徹底的にテストできることを意味します。

使用ツールの標準:

私は(自分よりも正式なコンピュータプログラミングトレーニングを受けた友人から)、C仕様を満たすバグのないCコンパイラなどはないと教えられました。これは、C言語が基本的にスタックの目的で無限のメモリを使用する可能性を想定しているためです。明らかに、そのような不可能な要件は、人々が本質的にもう少し有限な実際のマシンで動作する使用可能なコンパイラを作成しようとしたときから逸脱しなければなりませんでした。

実際には、Windows Script HostのJScriptを使用して、多くの優れたオブジェクトを使用できることがわかりました。(新しいコードを試すために必要なツールセットがMicrosoft Windowsの最新バージョンに組み込まれているため、この環境が気に入っています。)この環境を使用すると、オブジェクトの動作方法に関する簡単に見つけられるドキュメントがないことがあります。ただし、オブジェクトの使用は非常に有益であるため、とにかくそうします。だから私がやることは、スズメバチの巣のようにバグがあるかもしれないコードを書くことであり、効果を見ることができ、オブジェクトとやり取りしながらオブジェクトの動作を学ぶことができるサンドボックス化された環境でそうします。

他のケースでは、時々オブジェクトの動作を理解した後にだけ、オブジェクト(オペレーティングシステムにバンドルされている)がバグであり、Microsoftが修正しないと意図的に決定した既知の問題であることがわかりました。 。

このようなシナリオでは、10年以上にわたって「わずか2つのリモートホール」という有名なセキュリティレコードで、定期的に(1年に2回)定期的に新しいリリースを作成する優れたプログラマーによって作成されたOpenBSDに依存しますか?(それほど深刻でない問題に対するエラッタパッチもあります。)いいえ、決してありません。私は、Microsoft Windowsを使用するマシンを人々に提供するビジネスをサポートするビジネスに取り組んでいるので、このような高品質の製品には依存していません。

実用性/使いやすさは、人々が役に立つと思うプラットフォームで作業することを要求し、それは有名なセキュリティにとって悪いプラットフォームです(たとえ同じ会社の製品がはるかに悪かった千年紀の初期から大きな改善がなされたとしても) 。

概要

コンピュータープログラミングがエラーを起こしやすい理由は数多くあり、それはコンピューターユーザーのコミュニティに受け入れられています。実際、ほとんどのコードは、エラーのない作業を許容しない環境で作成されています。(セキュリティプロトコルの開発など、一部の例外は、この点でもう少し努力を要する場合があります。)企業がより多くのお金を投資したくない理由や、顧客を満足させるための人為的な期限を逃すという一般的な考えに加えて、テクノロジーの行進では、時間をかけすぎると、10年以内に物事が大きく変わるため、時代遅れのプラットフォームで作業することになります。

率直に言って、strlenとstrcpyのソースコードを見たとき、非常に便利で人気のある関数がどれほど短いかに驚いたことを思い出すことができます。たとえば、strlenは「int strlen(char * x){char y = x; while((y ++)); return(yx)-1;}」のようなものでした

ただし、典型的なコンピュータープログラムはそれよりもはるかに長くなります。また、多くの最新のプログラミングでは、十分にテストされていないか、バグがあることがわかっている他のコードを使用します。今日のシステムは、「下位レベルで処理される詳細」として多くの特徴点を手で振り払うことを除いて、簡単に考えられるものよりもはるかに複雑です。

この必須の複雑さ、および複雑で間違ったシステムで作業することの確実性により、コンピュータープログラミングは、物事がはるかに単純なレベルに煮詰められる傾向がある多くの数学よりも検証する多くのハードウェアになります。

数学で物事を分解すると、子どもたちが理解できる個々の部分に到達します。ほとんどの人は数学を信頼しています。少なくとも基本的な算術演算(または、少なくともカウント)。

実際にコンピュータープログラミングを分解して、内部で何が起こっているのかを確認すると、最終的に電子的に実行される壊れた標準とコードの壊れた実装になります。その物理的な実装は、ほとんどの大学で訓練されたコンピューター科学者が行うマイクロコードの1つ下のステップです触ってはいけません(彼らがそれに気づいていれば)。

大学にいるプログラマーや最近の卒業生と、バグのないコードを書くことができるという考えにまったく反対するプログラマーと話をしました。彼らは可能性を書き留めており、いくつかの印象的な例(私が示すことができた)はいくつかの説得力のある議論であることを認めていますが、彼らはそのようなサンプルを代表的ではないまれな吸虫と見なし、まだ数えることができる可能性を却下していますそのようなより高い基準を持つことに。(数学で見られるはるかに信頼できる基盤とはまったく異なる態度。)


1
プログラミングの複雑さについて良いケースを作りますが、数学についてはほとんど考慮しません!実際には、正式な数学に関わる複雑さを過小評価しているようだ:「あなたは数学で物事を分解するとき、あなたは子供たちが理解できる個々のピースを取得」、本当に?さらに、十分に「高レベル」なプログラミングについても同じことが言えます(たとえば、Scratchは子供向けに設計されています)。また、完全なC仕様は実装可能ではありませんが、重要なサブセットをサポートするコンパイラーは、コンピューター支援プルーフを使用して正式に正しいことが示されています。
離散トカゲ

2+3=5

メタノート:あるもののエキスパートであり、別のエキスパート(またはそれ以下)のエキスパートである場合、あなたはこの2つを比較する最悪の立場にいます。
ラファエル

離散トカゲ-これはコンピューターサイエンスSEです。さらに、投稿する前に他の回答を実際に読んだことがあるので、彼らはコンピューターよりも数学に触れているように感じました。私の答えは、他の場所で書かれたものとほとんど重複する単語を追加するだけで長くしない方が良いと感じました。/// Scratchの場合、高レベルはより複雑であり、単純ではありません(すべての可動部分を完全に理解するという観点から見ると)。私が書いていたこの観点から、アセンブリは他の層の上のスクラッチよりも単純です(電子NANDゲートはまだ単純です)
TOOGAM

0

数学的証明は「何」の知識を記述し、プログラムは「ハウツー」知識を記述します。

プログラマーは、発生する可能性のあるすべての状態と、プログラムの動作が結果としてどのように変化するかについて推論する必要があるため、プログラムの作成はより複雑になります。証明では、定型的またはカテゴリー的な推論を使用して、他の定義に関することを証明します。

ほとんどのバグは、プログラマーが予期していなかった状態に入るプロセスによって引き起こされます。プログラムでは通常、数千、または大規模なシステムでは、静的データではないがプログラムの実行方法を実際に変換する数百万の可能な変数があります。これらのすべての相互作用は、特にあなたの下に変化する抽象化の層がある現代のコンピューターでは、予期できない動作を作成します。

証明では、状態の変化はありません。議論の定義と目的は修正されています。証明には、一般的に問題について考え、多くのケースを考慮する必要がありますが、それらのケースは定義によって修正されます。


2
数学的証明は、「何」の知識を完全に記述することができると思います。たとえば、存在を証明するための例を構築する証明や、値を計算する方法を取ります。それでも、著者(または読者!)によって明示的に記述された状態以外の状態は存在しないという意味で、状態は証明にはないものであることに同意します。プログラムが読者/著者が知らないことを行うことができるのはまさにこの状態ですが、これは証明では不可能です。(確かに、プルーフには意図しない機能や結果が含まれる可能性がありますが、それらを取得するにはいくつかの積極的な考えが必要です)
離散トカゲ

@Discretelizardこれは役立つコメントです。「何」と「方法」の間の線は確かに曖昧だと思います。アルゴリズムがあなたが思うように動作することを証明するのは、実際には「ハウツー」を私の頭の中に記述しているのではなく、特定の特性が保持されることを保証しているだけです。哲学的な観点から、「ハウツー」知識には世界との対応が必要だと思います。プログラムは常にあなたが彼らに伝えることをします。あなたがバグを持っているとき、あなたがそれをするように言ったことは世界(あなたがモデリングしているもの)と一致しませんでした。アプリケーション(物理問題など)に依存しない数学は、すべてコヒーレンスに依存しているようです。
ジャスティンマイナーズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.