Coding Memorandum

プログラミングに関する備忘録

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

動的計画法 その1

イントロダクション

動的計画法(Dynamic Programing:以下「DP」と記述)は,ある種の最適化問題を効率的に(少ない計算時間で)解くための方法である。

アルゴリズム関連の参考書籍では,次のように説明される。

 k 個の要素だけをとったときの最適解が表の形で与えられているとする。これに要素を1個付け加えたときに,最適解がどのように変わるかをこの表をもとに計算し,表を書き換える。
 この操作を続けて,n 個の要素すべてを使った最適解が求まればよい。表の添え字としては,問題の性格を規定するパラメータのうち要素の個数以外のものを選ぶ。
アルゴリズムとデータ構造 (岩波講座 ソフトウェア科学) より
問題を細かく小さい問題に分けて,それぞれにベストの解答を見つけよ。それらの回答を張り合わせて,全体の問題の回答を導け。
プログラマのための論理パズル 難題を突破する論理思考トレーニング より

DPをインターネットで検索して得られる情報も概ねこのような説明であると思う。これらの説明と,いくつかの例題を見ることでDPのやりたいこと(方法)を(ある程度)理解することはできるであろう

しかしながら,実際に問題の解法としてDPを適用しようとした場合,「何を“小さい問題”として定義するのか?」,「何を“(k 個の)要素”とするのか?」を考え付くことが難しく(そもそもDPで解くべき問題であるかも見抜けないことも多い),解を得るまでに至らないのである。

ここでは,DPを数学面から見直し*1,各種例題を数学的に捉えなおすことでDPの理解を深める。「DPで考える」ための考え方を習得することを目指す。

DPの数学表現

動的計画法は「離散値を取る変数で表される関数の最大値または最小値(最適値)」を効率的に求める方法である。

変数 xi が 離散値{ a1,a2,・・・,an }をとるとき,

式1
の最大値,最小値を求める問題を考える。

一般的には,この関数の最適値を求めるには xi の全ての組み合わせについて関数の評価を行わなければならない。しかしながら,関数 f が次のような形で表されるとき,全件評価を行わずに最適値を求める方法が存在する。

式2
ここでは,この関数の最大値を求めることを考える。

x1 に着目すると, x1f1(x1),h1(x1,x2) にのみに関係する。変数 x2 に対して,f1(x1)+h1(x1,x2)の最大値を値とする関数f2(x2)を考える。

式3
式(1)が最大値をとるとき,次式
式4
も最大値をとり,式(1)の最大値と同じ値となる。

続いて式(2)について同様に,変数x3に対して,f2(x2)+h2(x2,x3)の最大値を値とする関数f3(x3)を考える。

式5
式(2)が最大値をとるとき,次式
式6
も最大値をとり,同じ値となる。

以下,同様の式の置きかけを続けることで,最終的には関数fn(xn)を次のように導くことができる。

式7
fn(xn)の最大値は式(1),(2),(3)の最大値と同じである。 このようにして部分ごとの最大値の計算を積み重ねることで,最終的に式(1)の最大値を求めることができる。

上述の説明は“最大値/max”を“最小値/min”に言い換えても成立する。(関数値の最小値を求めるときにも使える)

DPの計算手順は次の通りとなる。

関数f1(x1),hi(xi,xi+1) (i=1,n-1)が与えられたとき
1. f2 = max(f1(x1)+h1(x1,x2))を求める。
    x1, x2は離散値なので,f2(x2)も離散値となる。==> 配列へ保存

f2(x2)の値を用いて,
2. f3 = max(f2(x2)+h2(x2,x3))を求める。

以下,f4f5と求め,最終的には fnを求める。

fn の最大値が式(1)の最大値となる。

DPの適用

変数xi, xi+1を“問題”で定義される何らかの状態を表す値として捉えると,hi(xi,xi+1) は現在の状態 xi から次の状態 xi+1 へ遷移すると得られる値(得点)として考えられる。

DPは,この状態を進めることで得られる値(得点)の和について,その最適値を求める問題に適用することができる。

最適値に対応する各変数の値

式(1)が最適値をとるときの変数 xi の値が必要な場合には,次のように求める。

変数 xi+1 の関数,

式8
を求めるときに変数 xi+1 の各値に対して,最大値を与える xi を記録しておく。これを mi(xi+1) とする。

fn(xn) の最大値(pnとする)が求まると,mn-1(pn) から xn-1 の値が求まる。これをpn-1とする。 以下,同様にmn-2(pn-1) から pn-2 を求め,pn-3pn-4,・・・を順番に求める。pixi の値である。

例題1

TopCoder Tutorialから
http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg

このTutorialのIntermediateの問題では,次の例題が挙がっている。

N×Mの表の各マスに,それぞれいくつかのリンゴが置かれている。左上のマスからスタートして,右もしくは下へ進み,通ったマスのリンゴを集めながら右下のマスまで行く。リンゴは最大で何個集められるか?

マスを進む各ステップ(1ステップで1マス移動)の状態(状態=どのマスの上にいるか)を x0, x1, ・・・, xN+M-2 とする。i ステップ目にいるマス xi は,左上のマスを(0,0),右下のマスを(N-1, M-1)とする座標系を考えたとき,(p, q) :p+q=i のマスとなる。 x0は左上のマスであり,xN-1+M-1 は右下のマスである。

fig1

この最適化(最大値)問題は,xi における獲得リンゴ数を f(xi) とすれば,

式1-1
を最大化する問題となる。

ここで,xixi+1 の間には進む方向に関するルールからの依存関係があることに注意が必要である。
xi 上のマス(p, q)は,xi-1 においてマス (p-1, q),もしくは(p, q-1) のときのみ移動可能である。

fig2
xi の位置に関わらず xi+1 上の任意のマスに移動できるのであれば,各ステップでf(xi) の最大値のマスを選択していけば良いこととなる(貪欲法となる)

ここで次の関数h(xi,xi+1)を考える。

式1-3
ここでN/Aは評価されない値である。プログラミングする場合は,この関数値は評価対象から外すこと(行けない経路は評価しない)となる。
進む方向の依存関係を考慮した獲得リンゴ数の式は次のように書くことができる。
式1-4
獲得リンゴ数を最大化するには,この式を最大化すればよい。

この式は前述の式(1)と同等の形式であり,DPを用いて最大値を計算することができる。f1(x1)を次のように定義すると,

式1-5
前述の式の最大値は,次式の最大値と一致する。
式1-6
これを繰り返し fN+M-2(xN+M-2) を求める。この値が求めるべき最大値となる。

例題2

有向グラフの経路最適化問題を考える。

Fig.2-1
SからスタートしてEまで進む経路を考える。進む方向は左から右へのみ進めることとし,i ステップ目にいる頂点を xi で表す。各枝には得点が与えられて,SからEの経路で枝を通過すると得点を獲得する。このとき,得点を最大化する経路を求める。

各枝は2頂点 xixi+1 を結ぶものであるので,枝の得点は次のように表すことができる。

式2-2
この値は,iステップ目の頂点 xi から i+1ステップ目の頂点 xi+1 を結ぶ枝の得点を示す。
SからEまでの経路で得られる得点は次のように書き表せる。
式2-3
この式の最大値は,これまでの説明通りにDPで解くことができる。式(1)に対応する初期値f(x0) は0であると考えればよい。

ここで,グラフの枝ではなく頂点に得点が与えられているケースを考える。この場合は,各ステップ i において,頂点 xi のうち最大値をとる頂点を訪問すれば良いことは自明である。このケースは各ステップで最大となるものを選択していく“貪欲法”となる。

動的計画法は,あるステップの値が1つ前のステップの状態に依存するよう定義されるときに,それらの値の組み合わせ(これまでの例では加算)を最適化するときに用いることができると捉えることができる。


*1参考文献:これなら分かる最適化数学―基礎原理から計算手法まで
スポンサーサイト

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。