タグ付けされた質問 「correctness-proof」

アルゴリズムの正当性の証明について、またはそれについて尋ねる質問。

29
数学的な証明を書き留めるのは、コンピューターコードを書くよりもフォールトプルーフなのはなぜですか?
バグなしでコンピュータプログラムを書き留めるよりも、間違いを犯さずに数学的な証明を書き留める方がはるかに簡単だと気づきました。 これは私の経験よりも広く行われているようです。ほとんどの人は、プログラミング中に常にソフトウェアのバグを作成します。また、コンパイラには、常に間違いを教えてくれます。私は一度に間違いのない大きなコンピュータープログラムを書いた人のことを聞いたことがなく、バグがないと完全に確信していました。(実際、バグのないプログラムはほとんどなく、多くの高度にデバッグされたプログラムですらあります)。 しかし、コンパイラーが間違いを犯したことをフィードバックすることなく、場合によっては他人からフィードバックを得ることなく、論文全体または数学的な証明の本を書くことができます。 はっきりさせてください。これは、人々が数学の証明で間違いを犯さないと言うことではありませんが、経験の浅い数学者にとっても、その間違いは通常それほど問題ではなく、あなたの間違い。 実際、これが当てはまらない場合、数学はほとんど不可能に思えます。 だから、これは私に質問をするようになりました:前者が後者よりもはるかに扱いやすいようにする、誤りのない数学的な証明を書くことと誤りのないコンピューターコードを書くこととで何がそんなに違いますか? プログラマーが怠makesになり、コードを厳密に書くために必要なことをできないようにするのは、人々がコンパイラーの「外部の神託」をミスに向けているという事実に過ぎないと言うことができます。この見方は、もし彼らがコンパイラーを持っていなければ、数学者と同じように完璧であることができるということを意味するでしょう。 あなたはこの説得力があると思うかもしれませんが、プログラミングと数学的な証明を書き留めた私の経験に基づいて、これは本当に説明ではないと直感的に思えます。2つの取り組みについては、根本的に異なるものがあるようです。 私の最初の考えは、違いがあるかもしれないが、数学者にとって、正しい証明はすべての論理的なステップが正しいことだけを必要とするということです。すべてのステップが正しい場合、証明全体が正しいです。一方、プログラムにバグがないためには、すべてのコード行が正しいだけでなく、プログラム内の他のすべてのコード行との関係も同様に機能する必要があります。 言い換えれば、ステップ場合の証明では、ステップでミスを作り、その後、正しいなりません台無しステップ今まで。ただし、コード行が正しく記述されている場合、行間違いは行の動作に影響するため、行を記述するときは常に他のすべての行との関係を考慮する必要があります。これを制限するためにカプセル化とそれらすべてを使用できますが、完全に削除することはできません。Y X X Y X XバツXXYYYバツXXバツXXYYYバツXXバツXX つまり、数学的証明のエラーをチェックする手順は、証明ステップの数が本質的に線形ですが、コンピューターコードのエラーをチェックする手順は、コードの行数が本質的に指数関数的です。 どう思いますか? 注:この質問には、さまざまな事実や視点を探求する多数の回答があります。回答する前に、それらすべてを読んで、追加する新しいものがある場合にのみ回答してください。冗長な回答、または事実と意見を裏付けない回答は削除される場合があります。

13
「いくつかのテストケースを試す」ヒューリスティックを欺く方法:正しいように見えるが実際は正しくないアルゴリズム
ある問題のアルゴリズムが正しいかどうかをテストするための通常の出発点は、いくつかの単純なテストケースでアルゴリズムを手動で実行してみることです。 「。これは優れたヒューリスティックです。これは、アルゴリズムに対する誤った試行の多くを迅速に排除し、アルゴリズムが機能しない理由を理解するための優れた方法です。 ただし、アルゴリズムを学習するとき、一部の学生はそこでやめようとします:試行することを考えられるすべてのコーナーケースを含む少数の例でアルゴリズムが正しく機能する場合、アルゴリズムが正しい必要があると結論付けます。「いくつかのテストケースで試してみることができるのに、なぜアルゴリズムが正しいことを証明する必要があるのか​​」と尋ねる学生が常にいます。 それでは、「多数のテストケースを試す」ヒューリスティックをどのように欺くのでしょうか。このヒューリスティックでは不十分であることを示す良い例を探しています。言い換えれば、表面的には正しいように見えるアルゴリズムの1つ以上の例を探しており、だれかが思い付く可能性のあるすべての小さな入力に対して正しい答えを出力しますが、アルゴリズムは実際には動作しません。たぶん、アルゴリズムはたまたますべての小さな入力で正しく動作し、大きな入力に対してのみ失敗するか、異常なパターンを持つ入力に対してのみ失敗します。 具体的には、私は探しています: アルゴリズム。欠陥はアルゴリズムレベルである必要があります。実装のバグを探していません。(たとえば、最低限、この例は言語にとらわれず、ソフトウェアエンジニアリングや実装の問題ではなく、アルゴリズムの問​​題に関連する必要があります。) 誰かがもっともらしく思いつくかもしれないアルゴリズム。擬似コードは、少なくとももっともらしいように見えるはずです(たとえば、難読化された、または明らかに疑わしいコードは良い例ではありません)。宿題や試験の問題を解決しようとするときに、一部の学生が実際に思いついたアルゴリズムである場合、ボーナスポイントがあります。 妥当な手動テスト戦略に高い確率で合格するアルゴリズム。手作業でいくつかの小さなテストケースを試みる人は、欠陥を発見する可能性は低いはずです。たとえば、「12個の小さなテストケースで手動でQuickCheckをシミュレート」しても、アルゴリズムが正しくないことを明らかにすることはできません。 好ましくは、決定論的アルゴリズム。私は多くの学生が「手作業でいくつかのテストケースを試す」が決定論的アルゴリズムが正しいかどうかをチェックする合理的な方法であると考えているのを見てきましたが、ほとんどの学生はいくつかのテストケースを試すことは確率論を検証する良い方法だとは思わないでしょうアルゴリズム。確率的アルゴリズムの場合、特定の出力が正しいかどうかを確認する方法がないことがよくあります。また、出力分布に関する有用な統計テストを実行するのに十分な例をクランクすることはできません。したがって、決定論的アルゴリズムは学生の誤解の中心により明確になるため、決定論的アルゴリズムに焦点を当てることを好みます。 私はあなたのアルゴリズムが正しいことを証明することの重要性を教えたいです。そして、このようないくつかの例を使って、正当性の証明の動機付けを助けたいと思っています。私は比較的単純で学部生がアクセスしやすい例を好むでしょう。重い機械や数学的/アルゴリズム的背景を必要とする例はあまり有用ではありません。また、「不自然」なアルゴリズムも必要ありません。ヒューリスティックを欺くための奇妙な人工アルゴリズムを構築するのは簡単かもしれませんが、非常に不自然に見えるか、このヒューリスティックを欺くためだけに明らかなバックドアが構築されている場合、おそらく学生には納得しません。良い例はありますか?

2
欲張りアルゴリズムが正しいことを証明する方法
私は正しいと思われる貪欲なアルゴリズムを持っていますが、よくわかりません。正しいかどうかを確認するにはどうすればよいですか?貪欲なアルゴリズムが正しいことを証明するために使用するテクニックは何ですか?一般的なパターンやテクニックはありますか? これが参考質問になることを願っています初心者に向けられるしています。したがって、通常よりも広い範囲です。少なくとも1つの例で説明されているが、多くの状況をカバーする、一般的で教訓的に提示された答えを与えるように注意してください。ありがとう!

1
シャッフルアルゴリズムの正しさを証明する方法は?
アイテムのリストをランダムな順序で作成する方法は2つありますが、それらが同等に公平であるかどうかを判断したいです 私が使用する最初の方法は、要素のリスト全体を作成してから、シャッフルを実行することです(Fisher-Yatesシャッフルなど)。2番目の方法は、挿入のたびにリストをシャッフルする反復的な方法です。擬似コードでは、挿入関数は次のとおりです。 insert( list, item ) list.append( item ) swap( list.random_item, list.last_item ) この特定のシャッフルの公平性を示す方法に興味があります。このアルゴリズムが使用される場合、このアルゴリズムの利点は、わずかに不公平であっても大丈夫です。決定するには、その公平性を評価する方法が必要です。 私の最初のアイデアは、この方法で可能な合計順列と、最終的な長さのセットで可能な合計順列を計算する必要があるということです。ただし、このアルゴリズムから生じる順列の計算方法については少し迷っています。また、これが最良の、または最も簡単なアプローチであると確信することもできません。


5
正当性の証拠がないアルゴリズムの例
Hoareのロジックがあります。なぜアルゴリズムは正しいのに、それでも正しいという証拠がないのでしょうか?アルゴリズムがCで表現されていると仮定します。その後、ステップごとに、想定されていることを実行していると主張できます。 だから私の質問は: 正しいが、正確性の証拠がないアルゴリズムの例を教えてください。 編集:少しの背景が私がどこに行くのかを明確にするのに役立つと思います。スコットアーロンソンを引用します。 1970年代以降、P ≠≠\ne NPは、ツェルメロフレンケル集合論などの数学の標準公理系から独立している(つまり、証明可能でも反証不可能でもない)可能性があるという推測がありました。明確にするために、これは次のいずれかを意味します NP完全問題の多項式時間アルゴリズムは存在しませんが、それを証明することはできません(少なくとも通常の形式システムではそうではありません)、または NP完全問題の多項式時間アルゴリズムは存在しますが、それが機能することを証明できないか、多項式時間で停止することを証明できません。 2番目の可能性について言及しています。アーロンソンはそれを可能性として自信を持ってリストできるので、タイプ2の既存の例があるに違いないと思います。だから私はこの質問をしています。しかし、迅速かつ明確な答えは見当たらないようです。

6
間隔内の2つの数値の最大XORを見つける:二次式よりも良いことはできますか?
lllrrr L ≤ I 、最大(I ⊕ J )最大(私⊕j)\max{(i\oplus j)}L ≤ I 、J ≤ Rl≤私、j≤rl\le i,\,j\le r ナイーブアルゴリズムは、考えられるすべてのペアを単純にチェックします。たとえば、ルビーでは次のようになります。 def max_xor(l, r) max = 0 (l..r).each do |i| (i..r).each do |j| if (i ^ j > max) max = i ^ j end end end max end 私感私たちはより良い次より行うことができます。この問題のためのより良いアルゴリズムはありますか?

3
このクイックソートの正当性の証明を理解しようとしています
この証明は帰納法による証明であり、次のようになります。 P(n)は、「クイックソートが長さnのすべての入力配列を正しくソートする」という表明です。 基本ケース:長さ1のすべての入力配列は既にソートされています(P(1)が保持されます) 帰納的ステップ:n => 2を修正します。長さnの入力配列を修正します。 表示する必要があります:P(k)がすべてのk <nに対して成り立つ場合、P(n)も成り立ちます 次に、ピボットpの周りに分割された配列Aを描画します。したがって、彼はpを描画し、配列の<pである部分を最初の部分として呼び出し、> pである部分を2番目の部分として呼び出します。パーツ1の長さ= k1、パーツ2の長さはk2です。(前に提供された)Partitionサブルーチンの正確性の証明により、ピボットpは正しい位置に巻き上げられます。 帰納的仮説:1番目、2番目の部分は再帰呼び出しによって正しくソートされます。(P(K1)、P(k2)を使用) したがって、再帰呼び出しの後、配列全体が正しくソートされます。 QED 私の混乱:これが正確さをどのように証明するかを正確に確認するのに多くの問題があります。したがって、P(k)が実際にすべての自然数k <nに対して成立すると仮定します。 これまでに見た誘導証明のほとんどは、次のようなものです。基本ケースを証明し、P(n)=> P(n + 1)であることを示します。それらは通常、ある種の代数的操作も含みました。この証明は非常に異なっているように見え、誘導の概念をそれに適用する方法がわかりません。私は、Partitionサブルーチンの正確さが鍵であるといくぶん推論できます。したがって、その正確さの理由は次のとおりです。再帰呼び出しのたびに、ピボットの周りで配列が分割されることがわかっています。その後、このピボットはその正しい位置になります。次に、各サブアレイはピボットを中心にさらに分割され、そのピボットは正しい位置に配置されます。これは、長さ1のサブ配列を取得するまで繰り返し行われます。 しかし、P(k)がすべてのk <nに当てはまるとは想定していません。実際にそれを示しています(Partitionサブルーチンは常に1つの要素を正しい位置に配置するため)。Pを想定していませんか? (k)すべてのkに当てはまる

1
編集距離計算のためのマイクロ最適化:それは有効ですか?
上ウィキペディア、編集距離のためのボトムアップの動的プログラミングスキームの実装が与えられています。それは完全に定義に従っていません。内部セルはこうして計算されます: if s[i] = t[j] then d[i, j] := d[i-1, j-1] // no operation required else d[i, j] := minimum ( d[i-1, j] + 1, // a deletion d[i, j-1] + 1, // an insertion d[i-1, j-1] + 1 // a substitution ) } ご覧のとおり、一致がある場合、アルゴリズムは常に左上隣から値を選択し、一部のメモリアクセス、ALU操作、および比較を保存します。 ただし、削除(または挿入)の結果、値が小さくなる可能性があるため、アルゴリズムはローカルで正しくありません。つまり、最適性の基準に違反しています。しかし、おそらく間違いは最終結果を変えない-それはキャンセルされるかもしれない。 このマイクロ最適化は有効ですか、そしてなぜ(そうではない)のでしょうか?

2
この平方根境界検出アルゴリズムでループ不変量はどのように取得されますか?
もともとmath.SEにありましたが、そこには答えがありませんでした。 次のアルゴリズムを考えてみましょう。 u := 0 v := n+1; while ( (u + 1) is not equal to v) do x := (u + v) / 2; if ( x * x <= n) u := x; else v := x; end_if end_while ここで、u、v、およびnは整数であり、除算演算は整数除算です。 アルゴリズムによって計算されるものを説明します。 パートIに対する回答をアルゴリズムの事後条件として使用して、ループ不変式を確立し、アルゴリズムが終了して正しいことを示します。 クラスでは、事後条件があることが判明した及び不変である0 ≤ U 2 ≤ …

6
プログラム検証手法は、ハートブリードのジャンルのバグの発生を防ぐことができますか?
ハートブリードバグの問題について、ブルースシュナイアーは4月15日の暗号グラムで次のように書いています。「破滅的」は正しい言葉です。1から10のスケールで、これは11です。私は数年前に、特定のオペレーティングシステムのカーネルが最新のプログラム検証システムで厳密に検証されていることを読みました。したがって、今日のプログラム検証手法を適用することで、Heartbleedのジャンルのバグが発生するのを防ぐことができますか、それとも、これはまだ非現実的か、または基本的に不可能でしょうか。

3
スレッドの安全性を証明することは可能ですか?
変数とこれらの変数を変更する命令で構成されるプログラム、および同期プリミティブ(モニター、ミューテックス、Javaの同期またはC#のロック)が与えられた場合、そのようなプログラムがスレッドセーフであることを証明できますか? スレッドセーフティやレース条件などを記述するための正式なモデルさえありますか?

1
現代の正規表現の表現力
私は最近、主に単語のグループを特別なプロパティと照合する正規表現の課題を提案するWebサイトについて友人と話し合いました。彼は||||||||、数|が素数であるような文字列に一致する正規表現を探していました。そのような言語は、通常であれば、補題をポンプの翻訳が素数のためにあるという事実与えますので、私はすぐにそれが今まで動作しません彼に言われた十分な大きさ、それが存在するのk ≤ pがあるようP + N kは、すべての主要ですN ≥ - 1、よく、これは全くケースしにくい(素数の配分、そのような未知の自明とプロパティを破砕、...)pppk≤pk≤pk \leq pp+nkp+nkp + nkn≥−1n≥−1n \geq -1 しかし、誰かが解決策に付属している:一致しない(||+?)\1+ キャプチャグループに一致するように、この表現しようとする(つまりすることができ||、|||、||||などの上の出現箇所)のn ≥ 2回。一致する場合、文字列で表される数はkで割り切れるので、素数ではありません。それ以外の場合です。k≥2k≥2k \geq 2|n≥2n≥2n \geq 2kkk そして、グループ化と後方参照により、正規表現が理論的な意味で...正規表現よりも実際にはるかに表現力豊かになることが明らかになったので、私は愚かに感じました。今では、実際の正規表現を実行するときに私が知らなかったルックアラウンドやその他の演算子も追加されました。 ウィキペディアによると、文脈自由文法によって生成された言語よりもさらに表現力があります。だからここに私の質問があります: 現代の正規表現エンジンを使用して、(文脈自由文法から生成された)代数言語を表現できますか より一般的な説明、または現代の正規表現で説明できる言語の種類の複雑さの少なくとも上限はありますか? より実用的には、その背後に深刻な理論がありますか、それとも有限オートマトンに基づく実際の正規表現の最初のブロックに実装可能と思われるたびに新しい機能を追加するだけですか? 「モダンな正規表現」は質問が具体的ではないことを知っていますが、少なくとも後方参照を使用することを意味します。もちろん、この「現代の正規表現」言語に対する特定の制限を想定している部分的な回答者がいる場合は、遠慮なく投稿してください。

2
MSTの更新
無向、接続、加重グラフが与えられた場合 G=(V、E、w)G=(V,E,w)G = (V,E,w) どこ www 重み関数です w:E→Rw:E→Rw: E \to \mathbb{R}そして最小スパニングツリー(MST)の。 今、私たちは減少によって重量をエッジのんではないに属し。 TTTGGGkkkeeeTTT を効率的に更新してMST(と表記)にする方法TTTT』T′T')の G』=(V、E、w』)G′=(V,E,w′)G'=(V,E,w')、 どこ w』w′w' と同じです www それ以外で w』(e)=w(e)−kw′(e)=w(e)−kw'(e) = w(e) - k? 更新のアルゴリズムTTT に T』T′T' 簡単です:追加 eee に TTT サイクルを作成します CCC に TTT。しましょうe』e′e' サイクルの最大加重エッジになる CCC。もしw(e』)>w』(e)w(e′)>w′(e)w(e') > w’(e)、その後 T』=T∪{e}−{e』}T′=T∪{e}−{e′}T' = T \cup \{e\} - \{e'\}必要に応じてMSTを指定します。さもないと、T』=TT′=TT' = T。 私は矛盾によってその正しさを証明するのが難しい。と思いますT″T′′T'' …

2
配列の要素が同じ回数繰り返されるかどうかを判断するアルゴリズムの正確さの証明
タイトルが長かったことをお詫びしますが、内容についての情報が欠けているので、どうやって別の書き方をするのか本当にわかりませんでした。 最近、並列アルゴリズムに関する大学の試験を受けました。1つの演習で、配列の要素(これを呼び出すとしましょうA)が同じ回数繰り返されているかどうかを判断するアルゴリズムを作成するように求められました。 例えば: 1)A = 1 8 8 1 8 1 1 8:答えは「はい」です。すべての数値が2回繰り返されます。 2)A = 7 8 8 5 5 4 7 8:答えはノーです。 並列計算の特定のモデルであるPRAMのアルゴリズムを作成する必要がありました。このモデルでは、読み取り/書き込みの競合やその他の問題を回避するためにいくつかの手法を使用する必要がありましたが、これは関係ありません。私が最終的に得たのは、新しい配列でしたB。それを次のように定義できます。Given the array A, B[i] contains the number of repetitions of the element A[i] within A. 例えば: 1) A = 1 8 8 1 8 1 1 …

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