コードを数学に変換する
(多かれ少なかれ)正式な操作上のセマンティクスがあれば、アルゴリズムの(擬似)コードを、文字通り、結果を提供する数式に変換できます。これは、比較、スワップ、ステートメント、メモリアクセス、いくつかの抽象的なマシンニーズのサイクル数などの追加コスト測定に適しています。
例:Bubblesortでの比較
与えられた配列をソートするこのアルゴリズムを考えてみましょうA
:
bubblesort(A) do 1
n = A.length; 2
for ( i = 0 to n-2 ) do 3
for ( j = 0 to n-i-2 ) do 4
if ( A[j] > A[j+1] ) then 5
tmp = A[j]; 6
A[j] = A[j+1]; 7
A[j+1] = tmp; 8
end 9
end 10
end 11
end 12
通常のソートアルゴリズム分析を実行するとします。つまり、要素比較の数をカウントします(5行目)。この量は配列の内容に依存せずA
、長さのみ依存することにすぐに注意してください。したがって、(ネストされた)ループを文字通り(ネストされた)合計に変換できます。ループ変数が合計変数になり、範囲が引き継がれます。我々が得る:nfor
Ccmp(n)=∑i=0n−2∑j=0n−i−21=⋯=n(n−1)2=(n2)、
ここで、は5行目の実行ごとのコストです(カウント)。1
例:Bubblesortのスワップ
Iは、によって表すう行で構成サブプログラムへとによってこのサブプログラムを実行するためのコスト(1回)。 C i 、jPi,ji
j
Ci,j
スワップをカウントしたいとしましょう。これは、が実行される頻度です。これは「基本ブロック」、つまり常にアトミックに実行され、一定のコスト(ここでは)を持つサブプログラムです。そのようなブロックを縮小することは、考えたり話したりせずに適用することが多い便利な単純化です。 1P6,81
上記と同様の翻訳で、次の式が得られます。
Cswaps(A)=∑i=0n−2∑j=0n−i−2C5,9(A(i,j))。
A(i,j)は、の番目の反復の前の配列の状態を示します。(i,j)P5,9
パラメーターとしてではなくを使用していることに注意してください。その理由はすぐにわかります。コストはここで(つまり、均一コストモデル)に依存しないため、パラメーターとしてとを追加しません。一般に、彼らはただそうするかもしれません。AnijC5,9
明らかに、コストはの内容(値および、特に)に依存するため、それを考慮する必要があります。今、私たちは課題に直面しています:をどのように「アンラップ」しますか?さて、のコンテンツへの依存関係を明示的にすることができます。P5,9AA[j]
A[j+1]
C5,9A
C5,9(A(i,j))=C5(A(i,j))+{10,A(i,j)[j]>A(i,j)[j+1],else。
どの入力配列でも、これらのコストは明確に定義されていますが、より一般的なステートメントが必要です。より強い仮定をする必要があります。3つの典型的なケースを調べてみましょう。
最悪の場合
合計を見て、に注目するだけで、コストの自明な上限を見つけることができます。C5,9(A(i,j))∈{0,1}
Cswaps(A)≤∑i=0n−2∑j=0n−i−21=n(n−1)2=(n2)。
しかし、これは起こる可能性があります。つまり、この上限のが達成されるのでしょうか。結局のところ、はい:ペアごとに異なる要素の逆ソートされた配列を入力した場合、すべての反復でスワップを実行する必要があります¹。したがって、Bubblesortのスワップの正確な最悪ケース数を導き出しました。A
最高のケース
逆に、簡単な下限があります。
Cswaps(A)≥∑i=0n−2∑j=0n−i−20=0。
これは、すでにソートされている配列でも発生する可能性があります。Bubblesortは単一のスワップを実行しません。
平均的なケース
最悪で最良の場合は、かなりのギャップが生じます。しかし、スワップの典型的な数は何ですか?この質問に答えるためには、「典型的な」が意味するものを定義する必要があります。理論的には、ある入力を別の入力よりも優先する理由はないので、通常、すべての可能な入力にわたって均一な分布を仮定します。つまり、すべての入力が等しく発生する可能性があります。ペアごとに異なる要素を持つ配列に制限しているため、ランダム置換モデルを想定しています。
次に、この²のようにコストを書き換えることができます。
E[Cswaps]=1n!∑A∑i=0n−2∑j=0n−i−2C5,9(A(i,j))
ここで、単純な合計の操作を超えなければなりません。アルゴリズムを見ると、すべてのスワップが 1つの反転のみを削除することに注意してください(私たちは隣人だけをスワップします³)。すなわち、上で行わスワップの数であり、正確に反転数であるの。したがって、内側の2つの合計を置き換えて、AAinv(A)A
E[Cswaps]=1n!∑Ainv(A)。
幸運なことに、反転の平均数は
E[Cswaps]=12⋅(n2)
これが最終結果です。これは最悪の場合のコストのちょうど半分であることに注意してください。
- アルゴリズムは
i = n-1
、何も実行しない外部ループの「最後の」反復が実行されないように慎重に定式化されていることに注意してください。
- 「」は「期待値」の数学表記であり、ここでは単なる平均です。E
- 我々は、道に沿って学習しないだけ隣接する要素をスワップアルゴリズムは(さえ平均して)漸近的に速いバブルソートよりなることはできません-反転の数は、すべてのそのようなアルゴリズムの下限です。これは、たとえばInsertion SortおよびSelection Sortに適用されます。
一般的な方法
例では、制御構造を数学に変換する必要があることがわかりました。翻訳ルールの典型的なアンサンブルを紹介します。また、任意のサブプログラムのコストが現在の状態、つまり(大まかに)変数の現在の値に依存することもわかりました。アルゴリズムは(通常)状態を変更するため、一般的な方法は表記がやや面倒です。混乱し始めたら、例に戻るか、自分で構成することをお勧めします。
で現在の状態を示します(変数の割り当てのセットとして想像してください)。状態で始まるプログラムを実行すると、状態(終了が提供されます)。ψP
ψψ/PP
個別の声明
ステートメントが1つだけのS;
場合、コストを割り当てます。通常、これは定数関数です。CS(ψ)
表現
E
フォームの式E1 ∘ E2
(たとえば、∘
加算または乗算が可能な算術式)がある場合、コストを再帰的に加算します。
CE(ψ)=c∘+CE1(ψ)+CE2(ψ)。
ご了承ください
- 操作コスト一定であるが、の値に依存しないことがありととc∘E1E2
- 式の評価は多くの言語で状態を変えるかもしれません。
そのため、このルールに柔軟に対応する必要があります。
シーケンス
プログラムをプログラムのP
シーケンスとして指定Q;R
すると、コストを
CP(ψ)=CQ(ψ)+CR(ψ/Q)。
条件付き
次P
の形式のプログラムを考えるif A then Q else R end
と、コストは州によって異なります。
CP(ψ)=CA(ψ)+{CQ(ψ/A)CR(ψ/A),A evaluates to true under ψ,else
一般に、評価A
は状態を非常によく変更する可能性があるため、個々のブランチのコストの更新が行われます。
ループ用
次P
の形式のプログラムを指定するfor x = [x1, ..., xk] do Q end
と、コストを割り当てます
CP(ψ)=cinit_for+∑i=1kcstep_for+CQ(ψi∘{x:=xi})
ここで、はvalueの処理前の状態、つまり、...、... に設定された反復後の状態です。ψiQ
xi
x
x1
xi-1
ループメンテナンス用の追加の定数に注意してください。ループ変数を作成し()、その値を割り当てる必要があります()。これは関連しているcinit_forcstep_for
- 次の計算には
xi
コストがかかり、
for
空のボディを持つ-loop(たとえば、特定のコストでベストケース設定で単純化した後)は、反復を実行する場合、ゼロコストになりません。
While-Loops
次P
の形式のプログラムを指定するwhile A do Q end
と、コストを割り当てます
CP(ψ) =CA(ψ)+{0CQ(ψ/A)+CP(ψ/A;Q),A evaluates to false under ψ, else
アルゴリズムを調べることにより、この繰り返しは、forループの場合と同様の合計としてうまく表現できることがよくあります。
例:この短いアルゴリズムを考えてみましょう:
while x > 0 do 1
i += 1 2
x = x/2 3
end 4
ルールを適用することにより、
C1,4({i:=i0;x:=x0}) =c<+{0c+=+c/+C1,4({i:=i0+1;x:=⌊x0/2⌋}),x0≤0, else
個々のステートメントに一定のコストが伴います。これらは状態(およびの値)に依存しないと暗黙的に仮定します。これは「現実」に当てはまる場合も、そうでない場合もあります。c…i
x
この再発を解決する必要があります。ループ本体のコストではなく、反復回数もの値に依存しないことに注意してください。この繰り返しが残っています:C1,4i
C1,4(x)={c>c>+c+=+c/+C1,4(⌊x/2⌋),x≤0, else
これは、と解決基本的な手段に
C1,4(ψ)=⌈log2ψ(x)⌉⋅(c>+c+=+c/)+c>、
完全な状態を象徴的に再導入します。もし、その後。ψ={…,x:=5,…}ψ(x)=5
手続き呼び出し
プログラムを考えるとP
、フォームのM(x)
いくつかのパラメータ(複数可)のための(名前付き)のパラメータと手順があり、コストを割り当てますx
M
p
CP(ψ)=ccall+CM(ψglob∘{p:=x})。
再度、追加の定数注意してください(実際には依存する可能性があります!)。プロシージャコールは、実際のマシンでの実装方法のために高価であり、ランタイムを支配することさえあります(たとえば、フィボナッチ数の繰り返しを単純に評価する)。ccallψ
ここでは、状態に関するセマンティックの問題について説明します。グローバル状態とそのようなローカルプロシージャコールを区別する必要があります。ここでグローバル状態のみを渡しM
、の値を設定することで初期化された新しいローカル状態を取得すると仮定p
しx
ます。さらに、x
渡す前に(通常)評価されると想定される式である場合があります。
例:手順を検討する
fac(n) do
if ( n <= 1 ) do 1
return 1 2
else 3
return n * fac(n-1) 4
end 5
end
ルールに従って、以下を取得します。
Cfac({n:=n0})=C1,5({n:=n0})=c≤+{C2({n:=n0})C4({n:=n0}),n0≤1, else=c≤+{creturncreturn+c∗+ccall+Cfac({n:=n0−1}),n0≤1, else
fac
明らかにアクセスしないため、グローバル状態を無視することに注意してください。この特定の再発は簡単に解決できます
Cfac(ψ)=ψ(n)⋅(c≤+creturn)+(ψ(n)−1)⋅(c∗+ccall)
典型的な擬似コードで発生する言語機能について説明しました。高レベルの擬似コードを分析するときは、隠れたコストに注意してください。疑わしい場合は展開します。表記は面倒に思えるかもしれませんが、確かに好みの問題です。ただし、リストされている概念は無視できません。ただし、ある程度の経験があれば、「問題のサイズ」や「頂点の数」など、状態のどの部分がどのコストメジャーに関連しているかをすぐに確認できます。残りはドロップすることができます-これは物事を大幅に簡素化します!
あなたは、これはあまりにも複雑であることを今考えられる場合は、助言すること:それはあります!実際のマシンに非常に近いモデルでアルゴリズムの正確なコストを導き出して、実行時の予測(相対的なものであっても)を可能にするのは困難な試みです。そして、それは実際のマシンでのキャッシュやその他の厄介な効果を考慮していません。
したがって、アルゴリズム分析は、数学的に扱いやすいという点まで単純化されることがよくあります。たとえば、正確なコストを必要としない場合は、任意の時点で(上限または下限の場合)過大または過小評価することができます:定数セットの削減、条件の削除、合計の単純化など。
漸近コストに関する注意
通常、文献やWebで見つかるのは「Big-Oh分析」です。適切な用語は漸近解析です。これは、例で行ったように正確なコストを導出するのではなく、一定の係数と制限内のコストのみを与えることを意味します(大まかに言うと、「」)。n
マシン、オペレーティングシステム、およびその他の要因に応じて、抽象的なステートメントには実際にはいくつかの(一般に不明な)コストがあるため、これは(多くの場合)公平です。短いランタイムは、最初にプロセスをセットアップするオペレーティングシステムによって支配される場合があります。とにかく、あなたはいくらかの動揺を得る。
漸近解析がこのアプローチにどのように関係するかを以下に示します。
支配的な操作(コストを引き起こす)、つまり最も頻繁に発生する操作(一定の要因まで)を特定します。Bubblesortの例で考えられる選択肢の1つは、5行目の比較です。
または、基本操作のすべての定数を最大値(上から)でバインドします。それらの最小値(下から)と通常の分析を実行します。
- この操作の実行回数をコストとして使用して分析を実行します。
- 簡素化する場合、推定を許可します。目標が上限()である場合にのみ、上からの推定を許可するように注意してください。下限()が必要な場合は、下から。OΩ
Landauシンボルの意味を理解してください。このような境界は3つのケースすべてに存在することを忘れないでください。を使用しても、最悪の場合の分析を意味するわけではありません。O
参考文献
アルゴリズム分析にはさらに多くの課題とコツがあります。ここにいくつかの推奨読書があります。
これに類似した手法を使用するアルゴリズム分析にタグ付けされた質問が数多くあります。