Dynamic Programming
Dynamic Programming
VII.1 Pendahuluan
Teknik Dynamic Programming memiliki prinsip yang sama dengan divide and conquer,
dimana keduanya menyelesaikan suatu problem dengan cara memecahnya menjadi sub-sub
problem yang dapat diselesaikan secara rekursif.
Sebaliknya, pada divide and conquer lebih menekankan pada teknik yang disebut top-down
dimana problem utama diselesaikan dengan cara memecahnya menjadi sub-sub problem
tanpa berusaha untuk menggunakan kembali solusi/nilai dari sub problem tersebut bila
diperlukan pada proses sub problem lain yang memerlukannya. Dengan demikian sub
problem yang lebih besar diperoleh dengan menggabung solusi-solusi dari sub problem yang
lebih kecil, begitu seterusnya hingga diperoleh solusi dari persoalan utama.
Pada gambar 7.1 diberikan contoh, dua buah algoritma untuk menentukan barisan Fibonacci,
dimana pada gambar 7.1a diberikan algoritma secara top-down yang kurang efisien, dan pada
gambar 7.1b diberikan algoritma secara bottom-up yang lebih efisien. Adanya redundansi
proses pada algoritma 7.1a ditunjukkan pada gambar 7.2.
ANALISA ALGORITMA 42
F6
F5 F4
F4 F3 F3 F2
F3 F2 F2 F1 F2 F1 F1 F0
F2 F1 F1 F0 F1 F0 F1 F0
F1 F0
Catatan: teknik dynamic programming biasa digunakan untuk persoalan optimisasi (yang
biasa memiliki beberapa kemungkinan solusi) yang memenuhi prinsip optimal, yakni bila
sebarisan solusi menghasilkan hasil optimal, maka sub barisan tersebut juga bernilai optimal.
Bila diperlukan menghitung suatu operasi perkalian dari beberapa matriks sbb.:
M = M1.M2. ... Mn
maka karena perkalian matrik bersifat asosiatif, maka M dapat dihitung dengan menggunakan
beberapa cara, misalnya:
Contoh 7.1:
Misal diberikan 4 buah matrik A, B, C dan D yang masing-masing berukuran 13x5, 5x89, 89x3
dan 3x34. Maka matrik M = A.B.C.D dapat dihitung dengan beberapa cara seperti pada
gambar 7.3, dimana banyaknya perkalian skalar yang diperlukan untuk mengalikan 2 matrik A
(pxq) dan B (qxr) adalah p.q.r.
Pada gambar 7.3 tampak bahwa total operasi terkecil lebih cepat 19 kali dari pada total
operasi terbesar.
Untuk mengetahui urutan perkalian yang paling cepat, kita dapat lakukan secara sederhana
dengan mencoba semua urutan perkalian yang mungkin dan menentukan banyaknya operasi
perkalian skalar yang diperlukan masing-masing. Namun hal ini menjadi tidak efisien karena
memiliki pertumbuhan berorder eksponensial. Hal ini dapat ditunjukkan sebagai berikut:
ANALISA ALGORITMA 43
Misal T(n) adalah banyaknya cara/urutan untuk mengalikan n buah matrik. Ini berarti kita
memiliki T(1) = T(2) = 1, T(3) = 2 dan seperti contoh di atas T(4) = 5 cara. Bila kita lakukan:
maka terdapat T(i) cara untuk mengalikan suku pertama di ruas kanan dan T(n-i) cara
untuk suku ke dua. Karena 1 ≤ i ≤ (n-1), maka secara umum banyaknya cara tersebut
dapat ditulis secara rekursif sbb.:
1 , n =1
n −1
T ( n) =
∑
(7.1)
T (i ). T (n − i ) , n≥2
i =1
Nilai-nilai dari T(n) pada persamaan (7.1) dikenal dengan bilangan Catalan, yang memiliki
order eksponensial sebesar Ω(4n / n2). Waktu yang diperlukan untuk menghitung jumlah
operasi skalar untuk suatu cara adalah Ω(n). Dengan demikian cara sederhana ini
memerlukan waktu Ω(4n / n), yang menjadi tidak efisien lagi untuk nilai n yang besar.
Untuk menghindari cara yang kurang efisien di atas, kita dapat menerapkan teknik
dynamic programming. Hal ini terutama karena persoalan perkalian matrik berantai di
atas memenuhi prinsip optimal, yaitu bila cara terbaik (optimal) untuk mengalikan n matrik
di atas adalah dengan memotong antara matrik ke-i dan ke-(i+1), maka haruslah (M1.M2.
... Mi ) dan ( Mi+1.Mi+2. ... Mn ) diproses dengan cara optimal pula. Hal ini dapat dilakukan
sbb.:
Misal di , 0 ≤ i ≤ n, adalah suatu vektor yang berisi dimensi dari Mi ∋ dimensi dari Mi
adalah di-1 x di . Akan dibentuk suatu matrik/tabel mij , 0 ≤ i ≤ j ≤ n, dimana elemen-
elemen mij menunjukkan banyaknya operasi perkalian skalar yang diperlukan dalam
proses (Mi .Mi+1.Mi+2. ... Mj ). Dengan demikian solusi optimal (jumlah perkalian skalar
yang paling sedikit dalam M1.M2. ... Mn ) diperoleh dari m1n .
ANALISA ALGORITMA 44
Pembentukan Matrik/Table mij
• s = 0: mii = 0 , i = 1, 2, ... , n.
• 1 < s < n : mi,i+s = min ( mik + mk+1, i+s + di-1 . dk . di+s ), i = 1, 2, ... , n-s.
i ≤ k <i + s
catatan: kasus ke tiga menunjukkan bahwa untuk memperoleh jumlah perkalian skalar
yang paling sedikit dalam proses (Mi .Mi+1.Mi+2. ... Mi+s ), maka harus dilihat semua
kemungkinan proses ( Mi .Mi+1.. ... Mk ).( Mk+1 ... Mi+s ), untuk i ≤ k < i+s.
Pada gambar 7.4 diberikan pseudo-code untuk membentuk matrik mij . Pada algoritma
tersebut diberikan pula matrik LastChange yang digunakan untuk menentukan urutan
proses perkalian M1.M2. ... Mn yang akan memberikan jumlah perkalian skalar terkecil
(lihat gambar 7.5).
ANALISA ALGORITMA 45
Algoritma Menentukan Urutan Perkalian Matrik Berantai
function OrderMult( M : set of matrices { M1.M2. ... Mn }, LastChange: TwoArray, i, j: integer): Urutan;
{ LastChange adalah matrik yang diperoleh dari Algoritma pada gambar 7.4. Prosedur OrderMult ini dimulai
dengan pemanggilan OrderMult(M, LastChange, 1, n) }
1 if ( j > i ) then
2 X ← OrderMult( M, LastChange, i, LastChange[ i, j ] )
3 Y ← OrderMult( M, LastChange, (LastChange[ i, j ]+1), j )
4 return ( X. Y )
5 else return ( i )
Contoh 7.2:
Perkalian matrik pada contoh 7.1 akan memberikan d = (13, 5, 89, 3, 34) dan untuk:
dari sini akan diperoleh matrik mij seperti pada gambar 7.6 dan matriks LastChange pada
gambar 7.7.
mij j=1 2 3 4
3 0 9.078 s=1
4 0 s=0
ANALISA ALGORITMA 46
LC j=1 2 3 4
i=1 1 1 3
2 2 3
3 3
Analisa:
Untuk menentukan elemen mij , pada setiap diagonal s > 0, diperlukan menghitung (n - s)
elemen, yang masing-masing elemen dipilih diantara s kemungkinan (sebanyak nilai k).
Dari sini algoritma di atas memiliki waktu:
n −1 n −1 n −1
∑ (n − s). s = n. ∑ s − ∑ s
s =1 s =1 s =1
2
= (n 3 − n) / 6.
Persoalan penjaja keliling adalah persoalan mencari sirkuit terpendek dari suatu graph
yang berbobot non-negatif. Sirkuit tersebut dapat dikatakan menggambarkan perjalanan
seorang penjaja keliling yang bermula dari suatu kota/node dan harus kembali ke kota
tersebut dengan hanya melalui sekali dan hanya sekali kota-kota/node yang lain yang
menjadi anggota graph tersebut.
Misalkan G = <N, A> adalah suatu graph berarah, dan misal N = {1, 2, ... , n}.
Panjang/bobot dari setiap edge ditandai dengan Lij dengan Lii = 0 dan Lij ≥ 0 untuk i ≠ j
serta Lij = ∞ bila tidak terdapat edge antara node i dan j.
Teknik dynamic programming dapat digunakan untuk memecahkan masalah ini, karena
persoalan tersebut memenuhi prinsip optimal, yakni misalkan sirkuit yang akan dicari
bermula dan berakhir pada node 1, maka terdapat sebuah edge (1, j), j ≠ 1 yang diikuti
oleh suatu path dari j ke 1 yang tepat melalui hanya satu kali setiap node i ∈ N \ {1, j }.
Bila sirkuit tersebut adalah optimal, maka path dari j ke 1 pastilah optimal pula.
ANALISA ALGORITMA 47
• Definisikan g(i, S) sebagai panjang path terpendek dari node i ke node 1 yang
melalui tepat satu kali setiap node di S. Ini berarti g( 1, N \ {1} ) menunjukkan panjang
dari sirkuit optimal.
dan
g( i, ∅ ) = L i1 , i = 2, 3, ... , n (7.4)
• Tentukan nilai g mulai dari S = ∅ (dengan menggunakan 7.4), dan S berisi satu node,
berisi dua node dst. (dengan menggunakan persamaan 7.3)
• Bila nilai dari g(j, N \ {1, j}) telah diketahui untuk semua node j ≠ 1, maka dengan
menggunakan persamaan 7.2 kita dapat selesaikan persoalan penjaja keliling
dengan memperoleh nilai g(1, N \ {1}).
Contoh 7.3:
Suatu graph berarah G yang terdiri dari 4 buah node memiliki matrik Lij sbb.
0 10 15 20
5 0 9 10
L=
6 13 0 12
8 8 9 0
Untuk menentukan panjang dari sirkuit optimal dapat dilakukan sesuai algoritma di atas
sbb.:
g(2, {3}) = L23 + g(3, ∅) = 15, g(2, {4}) = L24 + g(4, ∅) = 18,
g(3, {2}) = L32 + g(2, ∅) = 18, g(3, {4}) = L34 + g(4, ∅) = 20,
g(4, {2}) = L42 + g(2, ∅) = 13, g(4, {3}) = L43 + g(3, ∅) = 15,
g(2, {3, 4}) = min(L23 + g(3, {4}) , L24 + g(4, {3} )) = min (29, 25) = 25,
g(3, {2, 4}) = min(L32 + g(2, {4}) , L34 + g(4, {2} )) = min (31, 25) = 25,
ANALISA ALGORITMA 48
g(4, {2, 3}) = min(L42 + g(2, {3}) , L43 + g(3, {2} )) = min (23, 27) = 23
g(1, {2, 3, 4}) = min(L12 + g(2, {3, 4}), L13 + g(3, {2, 4}), L14 + g(4, (2, 3}))
J(2, {3, 4}) = 4, J(3, {2, 4}) = 4, J(4, {2, 3}) = 2, J(1, {2, 3, 4}) = 2
10
1 2
10
6
9
4 3
Analisa:
ANALISA ALGORITMA 49
n−2
n − 2 r
r
Θ( 2.(n - 1) + ∑ (n − 1). k . ) = Θ( n .2 ),
2 n
(karena ∑ k . k = r.2 r −1
)
k =1 k k =1
meskipun algoritma ini memiliki waktu eksponensial, namun masih lebih baik
dibandingkan dengan cara mencoba semua bentuk sirkuit yang mungkin, yang
memerlukan waktu Ω( n! ).
Sebagai ilustrasi, pada gambar 7.9 diberikan perbandingan waktu dari keduanya.
10 3.628.800 102.400
Catatan:
Soal-soal :
1. Bila dilakukan perkalian berantai dari 6 buah matrik: A1. A2. A3.A4. A5. A6 yang masing-
masing memiliki dimensi: A1 (30 x 35), A2 (35 x 15), A3 (15 x 5), A4 (5 x 10), A5 (10 x
20), A6 (20 x 25), maka tentukan:
2. Tentukan panjang dan rute optimal dari perjalanan penjaja keliling pada graph yang
memiliki matrik Lij sbb.:
0 10 15 20
5 0 9 10
L=
6 13 0 12
8 8 9 0
ANALISA ALGORITMA 50