Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian Masalah Convex Hull Boy Dewa Priambada Program Pascasarjana Ilmu Komputer Institut Pertanian Bogor Abstrak - Tulisan ini memberikan gambaran tentang implementasi algoritma divide and conquer untuk penyelesaian masalah convex hull. Dengan algoritma divide and conquer masalah convex hull dapat diselesaikan dengan kompleksitas yang cukup rendah yaitu sebesar O(n log n). Pendahuluan Segala bentuk dan wujud yang ada di sekitar manusia didefinisikan ke dalam geometri. Permasalahan geometri komputasional biasanya melingkupi objek-objek geometri seperti himpunan titik, himpunan garis, himpunan segmen, dan juga poligon. Permasalahan yang berkaitan dengan penentuan bentuk geometri dapat diselesaikan dengan menggunakan algoritma pencarian convex hull. Usaha pencarian algoritma yang efisien untuk pencarian convex hull sudah dilakukan sejak lama dan masih dilakukan sampai sekarang. Satu dari berbagai algoritma yang dapat dimanfaatkan dalam pencarian convex hull adalah divide and conquer. Divide and Conquer adalah metode pemecahan masalah yang bekerja dengan membagi masalah menjadi beberapa submasalah yang lebih kecil, kemudian menyelesaikan masing-masing submasalah tersebut secara independen, dan akhirnya menggabungkan solusi masing-masing submasalah sehingga menjadi solusi dari masalah semula (Noorzaman, 2007). Tulisan ini memberikan gambaran tentang implementasi algoritma divide and conquer untuk penyelesaian masalah convex hull. Convex Hull Menurut Novandi (2007), sebuah subset S dari bidang R disebut konveks jika dan hanya jika pada seluruh dua buah titik sembarang p, q є S dibentuk garis yang seluruhnya berada dalam S[1].
Gambar 1. Convex set Pencarian convex hull dari sebuah himpunan titik Q (CH(Q)) adalah mencari sebuah convex set terkecil yang memuat seluruh titik pada Q. Convex hull dari dari sebuah himpunan titik Q (CH(Q)) pada n dimensi adalah seluruh irisan dari semua convex set yang
0|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull mengandung Q. Lebih lanjut, untuk N buah titik p1, p2, ... pN. convex hull merupakan himpunan convex combination yang dinyatakan dengan:
Definisi lain dari convex hull adalah poligon yang disusun dari subset titik sedemikian sehingga tidak ada titik dari himpunan awal yang berada di luar poligon tersebut (semua titik berada di batas luar atau di dalam area yang dilingkupi oleh poligon tersebut). Petunjuk untuk menyelesaikan persoalan ini adalah persamaan garis pada bidang. Persamaan garis pada bidang memisahkan bidang menjadi dua bagian yaitu area di sebelah kanan bidang (relatif terhadap orientasi garis). Sebagai contoh garis berorientasi adalah sumbu koordinat. Misalkan saja sumbu vertikal (ordinat, arah orientasi ke atas), seluruh titik di sebelah kanan garis ini memiliki nilai komponen koordinat horizontal (X) yang positif sedangkan seluruh titik di sebelah kiri garis memiliki nilai komponen koordinat horizontal negatif. Petunjuk di atas dimanfaatkan dengan membuat definisi bahwa garis yang dibentuk oleh titik-titik poligon jika diasumsikan memiliki orientasi yang sama, maka setiap titik berada di sebelah kanan seluruh garis batas tersebut. Definisi ini kemudian dimanfaatkan untuk menentukan aksi awal yaitu memilih titik yang berada paling luar pertama. Mencari titik pertama cukup mudah yaitu cukup memilih titik yang memiliki nilai komponen koordinat (horizontal atau vertikal) yang ekstrim (minimum atau maksimum). Titik-titik convex hull lainnya ditentukan berdasarkan titik pertama tadi.
Gambar 2. Inisiasi permasalahan dari Convex Hull Banyak sekali algoritma yang dapat digunakan untuk menyelesaikan permasalahan convex hull dengan kompleksitas yang berbeda-beda, misalnya saja dengan pendekatan brute force didapat kompleksitas sebesar O(n4), gift wrapping dengan kompleksitas sebesar O(nh), incremental methods dengan kompleksitas sebesar O(n log n), sweeping dengan kompleksitas sebesar O(n log n), divide-and-conquer dengan kompleksitas sebesar O(n log n), Monotone Chain dengan kompleksitas sebesar O(n log n) ( J. O'Rourke, 1998). Grafika komputer, otomasi desain, pengenalan pola (pattern recognition), dan penelitian operasi merupakan contoh aplikasi terapan yang menggunakan permasalahan convex hull untuk mencari suatu solusi yang dapat diolah menggunakan aplikasi komputer (Noorzaman, 2007). Algoritma Divide and Conquer
1|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull Algoritma divide and conquer adalah metode pemecahan masalah dengan membagi masalah ke menjadi submasalah yang lebih kecil, memecahkan setiap submasalah secara rekursif dan menggabungkan hasil yang sesuai untuk sebuah solusi lengkap. Pada algoritma divide and conquer ini memiliki tiga proses utama yaitu: - Divide: membagi masalah menjadi beberapa submasalah yang memiliki kemiripan dengan masalah semula namun berukuran lebih kecil (idealnya berukuran hampir sama), - Conquer: memecahkan (menyelesaikan) masing-masing submasalah (secara rekursif), dan - Combine: mengabungkan solusi masing-masing submasalah sehingga membentuk solusi masalah semula. Objek masalah yang dibagi adalah masukan (input) atau instances yang berukuran n: tabel, matriks, dan sebagainya, bergantung pada masalahnya. Tiap-tiap submasalah mempunyai karakteristik yang sama dengan karakteristik masalah semula, sehingga metode divide and conquer lebih natural diungkapkan dalam skema rekursif. Sesuai dengan karakteristik pembagian dan pemecahan masalah tersebut, maka algoritma ini dapat berjalan baik pada persoalan yang bertipe rekursif (perulangan dengan memanggil dirinya sendiri). Dengan demikian, algoritma ini dapat diimplementasikan dengan cara iteratif (perulangan biasa), karena pada prinsipnya iteratif hampir sama dengan rekursif. Penggunaan secara spesifik algoritma ini adalah untuk mencari nilai minimal dan maksimal serta untuk mengurutkan elemen array. Dalam hal pengurutan ini ada empat macam algoritma pengurutan yang berdasar pada algoritma divide and conquer, yaitu merge sort, insert sort, quick sort, dan selection sort. Merge sort dan quick sort mempunyai kompleksitas algoritma O(n log n). Hal ini lebih baik jika dibandingkan dengan pengurutan biasa dengan menggunakan algoritma brute force. Secara umum, algoritma divide and conquer memiliki skema sebagai berikut: procedure DIVIDE_and_CONQUER(input n : integer) { Menyelesaikan masalah dengan algoritma divide and conquer Masukan: masukan yang berukuran n Keluaran: solusi dari masalah semula } Deklarasi r, k : integer Algoritma if n ≤ n0 then {ukuran masalah sudah cukup kecil } SOLVE submasalah yang berukuran n ini else Bagi menjadi r submasalah, masingmasing berukuran n/k for masing-masing dari r submasalah do DIVIDE_and_CONQUER(n/k) endfor COMBINE solusi dari r submasalah menjadi solusi masalah semula endif Pemecahan Masalah Convex Hull dengan Algoritma Divide and Conquer Pada penyelesaian masalah pencarian Convex Hull dengan menggunakan algoritma Divide and Conquer, hal ini dapat dipandang sebagai generalisasi dari algoritma pengurutan merge sort. Berikut ini merupakan garis besar gambaran dari algoritmanya: 2|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull -
-
Lakukan pengurutan p1, p2, ... pN dalam koordinat X |S| Buat partisi himpunan titik-titik tersebut menjadi 2 himpunan A dan B, dimana A terdiri dari setengah jumlah dari |S| dan titik dengan koordinat X yang terendah dan B terdiri dari setengah dari jumlah |S| dan titik dengan koordinat X terbesar Secara rekursif lakukan penghitungan terhadap HA = conv(A) dan HB = conv(B) Gabungkan (merge) kedua hull tersebut menjadi convex hull, H, dengan menghitung dan mencari upper dan lower hull (tangents) untuk HA dan HB. Setiap titik searah jarum jam untuk himpunan yang berada di sebelah kanan, dan berlawanan arah jarum jam pada himpunan yang berada di sebelah kiri. dengan mengabaikan semua titik yang berada diantara dua buah tangen ini
Gambar 3. Divide And Conquer.
Gambar 4. Menggabungkan 2 buah upper hull. Untuk mencari upper hull dan lower hull dapat digunakan algoritma sebagai berikut: Algorithm UpperHull(P) if |P| 2 then return the obvious answer else begin Compute the median xmed of x-coordinates of points in P. 3|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull Partition P into two sets L and R each of size about n/2 around the median xmed . Find the upper bridge pq of L and R, p L, and q R L { r L x(r) x(p) } R { r R x(r) x(q) } LUH UpperHull(L ) RUH UpperHull(R ) return the concatenated list LUH, pq, RUH as the upper hull of P. end Waktu yang diperlukan untuk menjalankan algoritma tersebut dapat dijelaskan dengan relasi rekursi sebagai berikut:
Algoritma tersebut menghasilkan kompleksitas waktu sebesar O(n log n). Kesimpulan Grafika komputer, otomasi desain, pengenalan pola (pattern recognition), dan penelitian operasi merupakan contoh aplikasi terapan yang menggunakan permasalahan convex hull untuk mencari suatu solusi yang dapat diolah menggunakan aplikasi komputer. Algoritma divide and conquer adalah metode pemecahan masalah dengan membagi masalah ke menjadi submasalah yang lebih kecil, memecahkan setiap submasalah secara rekursif dan menggabungkan hasil yang sesuai untuk sebuah solusi lengkap. Algoritma divide and conquer merupakan salah satu algoritma yang dapat memecahkan masalah convex hull dengan kompleksitas yang cukup rendah yaitu sebesar O(n log n). Daftar Pustaka http://pagesperso-orange.fr/colin.barker/lpa/div_conq.htm Nopember 2009 Pukul 23.00.
Diakses
pada
tanggal
23
http://www.cse.unsw.edu.au/ Diakses pada tanggal 17 Nopember 2009 Pukul 12.00. J. O'Rourke. Computational Geometry in C (2nd ed.). Cambridge University Press, 1998 M. C. Timothy. A Minimalist's Implementation of the 3-d Divide-and-Conquer Convex Hull Algorithm. School of Computer Science, University of Waterloo, Canada. 2003. N. Stefan and Daniel Schmitt. A Framework for Multi-Core Implementations of Divide and Conquer Algorithms and its Application to the Convex Hull Problem. Department of Computer Science, University of Trier, Germany. 2008. Noorzaman Geri. Analisis dan Penerapan Algoritma Divide and Conquer Dalam Penyelesaian Masalah Convex Hulls. Jurusan Informatika, Sekolah Teknik Elektro dan Informatika Institut Teknologi Bandung. 2007. Novandi Petra. Analisis Kompleksitas Algoritma Pencarian Convex Hull Pada Bidang Planar. Program Studi Teknik Informatika, Institut Teknologi Bandung. 2007.
4|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull Lampiran This algorithm is due to Preparata and Hong. /* * Convex Hull * The convex hull of a set of points is the smallest convex region * containing the points */ /* divide_and_conquer(Points, ConvexHullVertices) is true if Points is a */ /* list of points in the form p(X,Y), and ConvexHullVertices are the */ /* vertices in the form p(X,Y) of the convex hull of the Points, in */ /* clockwise order, starting and ending at the smallest point (as */ /* determined by X-values, and by Y-values to resolve ties). No three */ /* vertices of the convex hull will be collinear. */ /* e.g.divide_and_conquer([p(0,6),p(3,7),p(4,6),p(4,5),p(3,4),p(2,4),p(5,0)],* / /* [p(0,6),p(3,7),p(4,6),p(5,0),p(0,6)]). */ divide_and_conquer(Ps, Qs):sort(Ps, Ps1), % Duplicated points are discarded length(Ps1, N), divide_and_conquer_1(N, Ps1, Qs, []). divide_and_conquer_1(1, [X|Ps], [X,X], Ps):-!. divide_and_conquer_1(2, [X,Y|Ps], [X,Y,X], Ps):-!. divide_and_conquer_1(3, [X,Y,Z|Ps], [X,Y,Z,X], Ps):strictly_to_right(Z, X, Y), !. divide_and_conquer_1(3, [X,Y,Z|Ps], [X,Z,Y,X], Ps):strictly_to_left(Z, X, Y), !. divide_and_conquer_1(3, [X,_,Z|Ps], [X,Z,X], Ps):-!. divide_and_conquer_1(N, Ps, Qs, Rs):N1 is N // 2, N2 is N - N1, divide_and_conquer_1(N1, Ps, Left, Temp), divide_and_conquer_1(N2, Temp, Right, Rs), union(Left, Right, Qs). /* length(Xs, L) is true if L is the number of elements in the list Xs. */ %length(Xs, L):-length_1(Xs, 0, L). /* length_1(Xs, L0, L) is true if L is equal to L0 plus the number of */ /* elements in the list Xs. */ %length_1([_|Xs], L0, L):-L1 is L0 + 1, length_1(Xs, L1, L). %length_1([], L, L). /* strictly_to_left(Pa, Pb, Pc) is true if Pa is strictly to the left of the */
5|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull /* directed line from Pb to Pc. */ strictly_to_left(p(Xa,Ya), p(Xb,Yb), p(Xc,Yc)):(Xb-Xa) * (Yc-Ya) - (Xc-Xa) * (Yb-Ya) > 0.0. /* strictly_to_right(Pa, Pb, Pc) is true if Pa is strictly to the right of */ /* the directed line from Pb to Pc. */ strictly_to_right(p(Xa,Ya), p(Xb,Yb), p(Xc,Yc)):(Xb-Xa) * (Yc-Ya) - (Xc-Xa) * (Yb-Ya) < 0.0. /* are_collinear(Pa, Pb, Pc) is true if Pa, Pb and Pc are collinear. */ are_collinear(p(Xa,Ya), p(Xb,Yb), p(Xc,Yc)):(Xb-Xa) * (Yc-Ya) - (Xc-Xa) * (Yb-Ya) =:= 0.0. /* is_nearer(Pa, Pb, Pc) is true if the distance from Pa to Pc is strictly */ /* less than the distance from Pb to Pc. */ is_nearer(p(Xa,Ya), p(Xb,Yb), p(Xc,Yc)):Xa_Xc is Xa - Xc, Ya_Yc is Ya - Yc, Xb_Xc is Xb - Xc, Yb_Yc is Yb - Yc, (Xa_Xc)*(Xa_Xc) + (Ya_Yc)*(Ya_Yc) < (Xb_Xc)*(Xb_Xc) + (Yb_Yc)*(Yb_Yc). /* * Union of disjoint convex hulls */ /* Given P1, find Q2, the */ /* If P2 is strictly to */ /* Given Q2, find P2, the */ /* If Q3 is strictly to */
first point in Qs s.t. P1-Q2 is a tangent for Qs. the right of P1-Q2, return P1-Q2. first point in Ps s.t. P2-Q2 is a tangent for Ps. the right of P2-Q2, return P2-Q2.
/* union(Ps, Qs, Rs) is true if Ps and Qs are disjoint convex hulls, all */ /* vertices of Ps being to the left of all the vertices of Qs, and Rs is */ /* the convex hull of the union of the vertices of Ps and Qs. For each */ /* convex hull, the vertices are in the form p(X,Y), in clockwise order, */ /* starting and ending at the smallest point (as determined by X-values, */ /* and by Y-values to resolve ties), and no three vertices are collinear. */ /* This is a O(n) time algorithm. */ /* This may not work for some degenerate convex hulls, but should work in */ /* all cases when called by divide_and_conquer_1/4. */
6|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull /* e.g. union([p(0,1),p(1,3),p(2,3),p(3,0),p(0,1)], */ /* [p(4,0),p(4,1),p(5,2),p(7,2),p(4,0)], */ /* [p(0,1),p(1,3),p(2,3),p(7,2),p(4,0),p(3,0),p(0,1)]). */ union(Ps, Qs, Rs):split_left_hull(Ps, [], Ps1, Ps2), split_right_hull(Qs, Qs2), bridge(Ps1, Qs, A, B, Qs3), bridge(Qs2, Ps2, C, D, Ps3), concatenate([B|Qs3], C, [D|Ps3], Rs0), concatenate(Ps, A, Rs0, Rs). /* split_left_hull(Ps, [], Xs, Ys) is true if Xs is the reverse of the */ /* points in Ps up to and including the rightmost point, and Ys are the */ /* remaining points in Ps starting at the rightmost point. */ /* e.g. split_left_hull([p(0,1),p(1,3),p(2,3),p(3,0),p(0,1)], [], */ /* [p(3,0),p(2,3),p(1,3),p(0,1)], [p(3,0),p(0,1)]). */ split_left_hull(Ps, Xs, [P1|Xs], Ps):- % For a one-point hull Ps=[P1,P2|_], P1=P2, !. split_left_hull(Ps, Xs, [P1|Xs], Ps):Ps=[P1,P2|_], lt(P2, P1), !. split_left_hull([P1|Ps], Xs0, Xs, Ys):split_left_hull(Ps, [P1|Xs0], Xs, Ys). /* split_right_hull(Qs, Ys) is true if Ys is the reverse of the points in Qs */ /* starting at the rightmost point. */ /* e.g. split_right_hull([p(4,0),p(4,1),p(5,2),p(7,2),p(4,0)], */ /* [p(4,0),p(7,2)]). */ split_right_hull(Qs, Ys):- % This clause is probably redundant Qs=[Q1,Q2|_], Q2=Q1, !, reverse(Qs, Ys). split_right_hull(Qs, Ys):Qs=[Q1,Q2|_], lt(Q2, Q1), !, reverse(Qs, Ys). split_right_hull([_|Qs], Ys):split_right_hull(Qs, Ys). lt(p(X,_), p(X1,_)):-X < X1, !. lt(p(X,Y), p(X,Y1)):-Y < Y1. /* bridge(Ps, Qs, P, Q, Qs1) is true if Ps are the vertices of the left */ /* convex hull starting at the rightmost point going anti-clockwise to the */
7|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull /* leftmost point, Qs are the vertices of the right convex hull starting */ /* and ending at the leftmost point going clockwise, the line from P (a */ /* point in Ps) to Q (a point in Qs) is a left tangent for the convex */ /* hulls, and Qs1 are the points following Q in Qs. */ /* e.g. bridge([p(3,0),p(2,3),p(1,3),p(0,1)], */ /* [p(4,0),p(4,1),p(5,2),p(7,2),p(4,0)], */ /* p(2,3), p(7,2), [p(4,0)]). */ bridge(Ps, Qs, P, Q, Qs1):Ps=[P1|_], tangent_to_right_hull(Qs, P1, Qs0), bridge_1(Ps, Qs0, P, Q, Qs1). bridge_1([P], [Q|Qs], P, Q, Qs):-!. bridge_1([P,P1|_], [Q|Qs], P, Q, Qs):strictly_to_right(P1, P, Q), !. bridge_1([_|Ps], Qs, P, Q, Qs1):Qs=[Q1|_], tangent_to_left_hull(Ps, Q1, Ps1), bridge_2(Qs, Ps1, P, Q, Qs1). bridge_2([Q], [P|_], P, Q, []):-!. bridge_2([Q,Q1|Qs], [P|_], P, Q, [Q1|Qs]):strictly_to_right(Q1, P, Q), !. bridge_2([Q,Q1|Qs], [P|_], P, Q, [Q1|Qs]):- % For some 2-vertex Qs are_collinear(P, Q, Q1), is_nearer(Q1, Q, P), !. bridge_2([_|Qs], Ps, P, Q, Qs1):Ps=[P1|_], tangent_to_right_hull(Qs, P1, Qs2), bridge_1(Ps, Qs2, P, Q, Qs1). /* tangent_to_right_hull(Qs, P, Qs1) is true if the head of Qs1 is the last */ /* element (and the tail of Qs1 are the remaining elements) of Qs (a */ /* convex chain going clockwise) such that the line from P to Q is a */ /* tangent for Qs. */ /* e.g. tangent_to_right_hull([p(4,0),p(4,1),p(5,2),p(7,2),p(4,0)], p(3,0), */ /* [p(5,2),p(7,2),p(4,0)]). */ tangent_to_right_hull([Q], _, [Q]):-!. tangent_to_right_hull(Qs, P, Qs):Qs=[Q,Q1|_], strictly_to_right(Q1, P, Q), !. tangent_to_right_hull(Qs, P, Qs):- % For some 2-vertex Qs Qs=[Q,Q1|_], are_collinear(P, Q, Q1), is_nearer(Q1, Q, P), !. tangent_to_right_hull([_|Qs], P, Qs1):tangent_to_right_hull(Qs, P, Qs1).
8|Page
Implementasi Algoritma Divide and Conquer Untuk Penyelesaian 2009 Masalah Convex Hull
/* tangent_to_left_hull(Ps, Q, Ps1) is true if the head of Ps1 is the first */ /* element (and the tail of Ps1 are the remaining elements) of Ps (a */ /* convex chain going anti-clockwise) such that the line from Q to P is a */ /* tangent for Ps. */ /* e.g. tangent_to_left_hull([p(3,0),p(2,3),p(1,3),p(0,1)], p(5,2), */ /* [p(2,3),p(1,3),p(0,1)]). */ tangent_to_left_hull([P], _, [P]):-!. tangent_to_left_hull(Ps, Q, Ps):Ps=[P,P1|_], strictly_to_right(P1, P, Q), !. tangent_to_left_hull([_|Ps], Q, Ps1):tangent_to_left_hull(Ps, Q, Ps1). /* concatenate(Ps, P, Qs0, Qs) is true if the list Qs consists of the */ /* elements of Ps up to and including the element P, followed by the */ /* elements of Qs0. */ /* e.g. The goal */ /* concatenate([9,10,11,12,13], 11, [], Y), */ /* concatenate([5,6,7,8,9], 7, [-8|Y], Z), */ /* concatenate([1,2,3,4,5], 3, [-4|Z], A). */ /* gives Y=[9,10,11] Z=[5,6,7,-8,9,10,11] A=[1,2,3,-4,5,6,7,-8,9,10,11] */ concatenate([P|_], P, Qs, [P|Qs]):-!. concatenate([Q|Ps], P, Qs0, [Q|Qs]):concatenate(Ps, P, Qs0, Qs). /* reverse(Xs, Ys) is true if Ys is the result of reversing the order of */ /* the elements in the list Xs. */ %reverse(Xs, Ys):-reverse_1(Xs, [], Ys). %reverse_1([], As, As). %reverse_1([X|Xs], As, Ys):-reverse_1(Xs, [X|As], Ys).
9|Page