III-1
BAB III
ANALISIS
Mula-mula, Bab ini akan mengemukakan analisis yang dilakukan terhadap algoritma PrefixSpan [PEI01]. Kemudian dilakukan rancangan dan implementasi algoritma tersebut. Setelah itu, program hasil implementasi dievaluasi untuk didapatkan alternatif-alternatif implementasi yang dapat meningkatkan kinerja program. Selanjutnya alternatif tersebut akan dianalisis apakah memang dapat mengurangi waktu proses dari algoritma PrefixSpan.
III.1 Analisis Algoritma PrefixSpan [PEI01]
Agar dapat membangun program yang telah dijelaskan di Subbab II.4.2, terdapat beberapa hal yang perlu diperhatikan, antara lain:
1. Mekanisme pengambilan dan penyimpanan sequence. Mekanisme ini diperlukan untuk memasukkan sequence dari persistent memory ke dalam volatile memory.
2. Mekanisme proyeksi sequence terhadap suatu prefix. Mekanisme ini diperlukan untuk melakukan proyeksi suatu sequence dengan suatu proyektor. 3. Mekanisme penggabungan Prefix dengan Postfix pada suatu sequence.
Mekanisme ini diperlukan untuk menangani kasus-kasus khusus pada mekanisme proyeksi dan penggabungan elemen untuk menghasilkan sequential pattern yang lebih panjang dari sequential pattern sebelumnya. 4. Mekanisme pencarian frequent sequence dengan satu elemen. Mekanisme ini
diperlukan untuk menghasilkan sequential pattern. Berikut akan diberikan penjelasan empat hal diatas.
III.1.1 Mekanisme Penyimpanan dan Pengambilan Sequence
Sequence yang terdapat dalam database harus disimpan dalam main memory terlebih dahulu sebelum dapat diproses. Pada algoritma PrefixSpan yang tercantum dalam [PEI01], disebutkan secara implisit bahwa seluruh sequence awal disimpan di dalam main memory. Untuk implementasi PrefixSpan pada tugas akhir ini, jika dilakukan hal yang sama seperti yang disebutkan diatas, prosesnya menjadi sederhana, yaitu dengan memasukkan seluruh sequence dalam main memory komputer. Namun hal ini dapat
III-2
menimbulkan masalah jika seluruh sequence yang ada tidak cukup untuk disimpan di dalam main memory.
Jika dipikirkan sekilas, tipe data yang digunakan untuk menyimpan sequence tersebut adalah list of list of string, dimana setiap elemen dalam sequence tersebut adalah elemen dari list. Contohnya, bila terdapat sequence <(a,b,c),(a,c,e)>, (a,b,c) dan (a,c,e) akan menjadi elemen dari list dimana elemen tersebut juga merupakan list yang berisikan objek-objeknya. Namun karena sequence yang akan disimpan cukup panjang, tipe data string dapat menjadi alternatif penyimpanan sequence tersebut, karena kebutuhan memory untuk menyimpan string lebih kecil daripada list of list of string.
Karena sequence disimpan sebagai string, sehingga untuk pengolahannya dapat diterapkan cara-cara yang biasa dilakukan untuk pengolahan string. Selain itu, karakteristik string dapat dianalogikan dengan sequence, maksudnya misalkan pada sequence <a,b,c>, yang berarti seorang pelanggan membeli a terlebih dahulu sebelum b, dan membeli b terlebih dahulu sebelum c. Hal ini sama dengan string “a,b,c”, dimana waktu kemunculan a lebih dulu daripada b, dan kemunculan b lebih dulu daripada c.
III.1.2 Mekanisme Proyeksi Sequence terhadap suatu Prefix
Dengan didapatkannya himpunan frequent sequence satu elemen, tahap selanjutnya adalah memroyeksi seluruh sequence untuk masing-masing elemen dalam himpunan tersebut. Contoh proyeksi diilustrasikan dalam Tabel III.1-3.
Tabel III-1 Contoh Proyeksi 1
No Sequence Awal Proyektor Sequence Posfix
1. <a(abc)(ac)d(cf)> <a> <(abc)(ac)d(cf)>
2. <(abc)(ac)d(cf)> <a> <(_bc)(ac)d(cf)>
3. <a(abc)(ac)d(cf)> <b> <(_c)(ac)d(cf)>
4. <a(abc)(ac)d(cf)> <(ab)> <(_c)(ac)d(cf)>
5. <(_c)(ac)d(cf)> <c> <d(cf)>
III-3
Perhatikan bahwa pada sequence nomor 5, proyeksi dengan <c> menghasilkan <d(cf)>, bukan <(ac)d(cf)> seperti pada nomor 6. Hal ini dikarenakan <c> tidak sama dengan <(_c)>, karena jika digabung dengan proyektor-nya, <c> menghasilkan <bc> jika digunakan prefix nomor 3 atau <(ab)c> jika nomor 4, sedangkan untuk <(_c)>, akan menghasilkan <(bc)> untuk nomor 3 dan <(abc)> untuk nomor 4.
Pada kasus nyata, terdapat dua kemungkinan bentuk dari proyektor, yaitu 1. Elemen yang tidak mengandung karakter ‘_’
2. Elemen yang mengandung karakter ‘_’
Sedangkan untuk masing-masing elemen, akan terdapat tiga kemungkinan bentuk awal dari sequence yang akan diproyeksi, yaitu:
1. Sequence-nya memiliki awalan yang hanya terdiri dari satu elemen saja, contohnya <ab(bdc)cdc>
2. Sequence-nya memiliki awalan yang terdiri lebih dari satu, contohnya <(abc)ada>
3. Sequence-nya memiliki awalan yang terdiri lebih dari satu elemen, dan merupakan kejadian yang memiliki waktu yang sama dengan elemen, contohnya <(_c)adcd>
Dengan begitu akan terdapat enam kemungkinan bentuk yang harus ditangani.
Untuk kasus proyektor yang tidak mengandung ‘_’ dan sequence memiliki awalan satu elemen, apabila elemen tersebut adalah elemen yang sama dengan proyektor, proyeksinya cukup dengan menghapus elemen tersebut. Pada kasus kedua, yaitu sequence-nya memiliki awalan yang terdiri lebih dari satu elemen, apabila salah satu dari kumpulan elemen itu sama dengan proyektor, maka proyeksinya dilakukan dengan menghapus awal sekumpulan elemen hingga elemen yang sama dengan proyektor. Apabila hasil dari penghapusan tersebut menyisakan satu atau lebih elemen, maka di posisi depan elemen tersebut harus ditambahkan ‘_’, namun bila tidak menyisakan satupun, dilakukan penghapusan seluruh elemen tersebut.
Untuk kasus proyeksi yang mengandung ‘_’, proyeksi termudah adalah apabila awal sequence-nya hanya memiliki satu elemen. Kasus seperti ini mudah, karena sub-sequence satu elemen tidak sama dengan proyeksi meskipun salah satu elemen
III-4
proyeksi sama dengan satu elemen tersebut. Kasus selanjutnya, yaitu apabila sequence yang awalnya terdiri lebih dari satu elemen, proyeksinya dilakukan dengan langkah-langkah sebagai berikut:
1. gabungkan proyektor dengan prefixnya,
2. ambil sequence terakhir dari hasil gabungan tersebut, dan cek apakah sub-sequence tersebut merupakan himpunan bagian dari sub-sub-sequence yang sedang diperiksa.Jika iya, hapus sampai pada elemen terakhir yang terkandung dalam sub-sequence terakhir hasil gabungan.
3. Jika hasil akhir menyisakan satu elemen atau lebih, tambahkan ‘_’ pada sub-sequence yang sedang diproyeksi.
Kasus terakhir, yaitu apabila proyektor dan awal sequence mengandung ‘_’. Caranya hampir sama dengan kasus awal sequence yang tidak mengandung ‘_’, hanya saja penggabungan harus dilakukan baik oleh proyektor maupun sub-sequence-nya, tidak hanya pada proyektor seperti pada kasus sebelumnya.
III.1.3 Mekanisme Penggabungan Prefix dengan Postfix
Yang dimaksud dengan penggabungan adalah menyatukan dua sequence, yaitu prefix dan postfix, menjadi satu sequence. Untuk itu, terdapat beberapa kemungkinan yang didasari oleh berbagai jenis prefix dan postfix yang akan digabungkan. Tabel III-2 menunjukkan keseluruhan kemungkinan.
Tabel III-2 Tabel Kemungkinan Penggabungan
Elemen terakhir Prefix terdiri dari satu objek Terdiri dari satu objek Terdiri dari banyak objek Mengandung karakter spesial Elemen Pertama Postfix terdiri dari banyak objek Terdiri dari satu objek
Terdiri dari banyak objek Mengandung karakter spesial
III.1.3.1 Elemen terakhir prefix satu objek
Pada kasus ini, penggabungan yang dilakukan pada postfix yang terdiri dari satu elemen dan beberapa elemen sama, yaitu menambahkan elemen postfix ke akhir dari
III-5
prefix. Dengan demikian, akan terbentuk sequence baru yang terdiri dari prefix pada awalnya kemudian postfix di belakangnya.
Untuk postfix yang elemen terakhirnya mengandung ‘_’, penggabungan dilakukan dengan mengganti ‘_’ dengan elemen terakhir prefix, menghapus elemen tersebut dari prefix, dan kemudian menggabungkannya seperti pada kasus-kasus sebelumnya.
III.1.3.2 Elemen terakhir prefix lebih dari satu objek
Pada kasus ini, penanganan untuk postfix satu elemen atau lebih sama dengan satu elemen, yaitu dengan menambahkan postfix dengan prefixnya, sehingga tercipta satu sequence yang memiliki awalan prefix dan akhiran postfix.
Untuk elemen terakhir postfix yang mengandung ‘_’, penggabungan dilakukan dengan dua langkah, yaitu
1. mengganti ‘_’ pada postfix dengan elemen terakhir dari prefix, 2. menghapus elemen terakhir tersebut dari prefix,
3. menggabungkan prefix dan postfix yang telah dirubah.
Untuk elemen terakhir prefix mengandung ‘_’, karena arti dari ‘_’ adalah akhir dari prefix terjadi dalam waktu yang sama dengan awal dari postfix, maka prefix tidak akan mengandung ‘_’. Hal ini dikarenakan prefix merupakan awalan, yang artinya tidak ada lagi objek atau elemen yang posisinya berada didepan prefix.
III.1.4 Mekanisme Pencarian 1-Sequence yang Frequent
Dengan asumsi bahwa main memory mencukupi, seluruh sequence disimpan ke dalam main memory. Tahap selanjutnya adalah menemukan frequent sequence yang berisikan satu elemen. Hal ini mudah dilakukan untuk pencarian frequent sequence yang pertama, karena hanya mencari karakter yang berbeda dan menghitung berapa sequence yang mengandung karakter tersebut.
Mekanisme ini berkembang menjadi lebih sulit jika telah mengalami banyak proyeksi, setidaknya terdapat dua kasus utama yang perlu ditangani secara khusus. Untuk kasus pertama, sebagai ilustrasi, misalnya terdapat basis data Tabel III-2:
III-6
Tabel III-3 Contoh Proyeksi 2
No Sequence awal Hasil proyeksi dengan prefix aa
1 <a(ad)ab(bc)> <(_d)ab(bc)> 2 <(abc)ada> <da>
Dari tuple-tuple atribut hasil proyeksi diatas, ingin didapatkan frequent sequence satu elemen. Misalkan nilai theshold yang diinginkan pada kasus ini adalah dua. Dengan melihat sepintas saja, akan ditemukan dua sequence, yaitu <a> dan <d>, namun sebenarnya tidak demikian kenyataannya, pada <d> ada sequence <(_d)ab(bc)> tidak membentuk sequence <aad>, melainkan <a(ad)> (hal ini dapat dilihat di sequence awal). Oleh karena itu, setiap serangkaian sequence yang muncul dalam waktu bersamaan “()” mengandung “_” di dalamnya, rangkaian tersebut tidak memberikan kontribusi pada elemen lain yang terdapat didalamnya.
Untuk ilustrasi kasus kedua, misalkan pada Tabel III-3 sequence nomor dua, <(abc)ada>, diubah menjadi <(abc)a(acd)da>, sehingga proyeksinya adalah <(acd)da>.
Tabel III-4 Contoh Proyeksi 3
No Sequence awal Hasil proyeksi dengan prefix aa
1 <a(ad)ab(bc)> <(_d)ab(bc)> 2 <(abc)a(acd)da> <(acd)da>
Dengan kondisi seperti ini, sekilas terdapat tiga frequent sequence, yaitu <a>, <d> dan <c>. Memang ketiga sequence ini merupakan frequent sequence, namun masih kurang satu lagi, yaitu <(_d)>. Sequence tersebut merupakan frequent sequence, karena jika digabungkan dengan prefixnya, hasil gabungannya, <a(ad)>, juga merupakan sequential pattern. Hal ini dikarenakan <a(ad)> merupakan subset dari <(abc)a(acd)a>. Oleh karena itu, subset sequence dua, <(acd)>, memberikan kontribusi pada sequence <(_d)>.
Pada implementasinya, suatu sequence diiterasi dari sub-sequence awal sampai akhir, dan ada tiga kemungkinan bentuk dari sequence yang akan muncul, yaitu
sub-III-7
sequence yang terdiri dari satu elemen, sub-sequence yang terdiri dari beberapa elemen, dan sub-sequence yang mengandung ‘_’.
Penanganan ketika sub-sequence hanya memiliki satu elemen, elemen tersebut disimpan dalam suatu list penghitung yang menyimpan elemen untuk menghitung jumlah kemunculannya dan list penyimpan untuk menyimpan informasi bahwa elemen tersebut telah terhitung sehingga tidak akan dihitung apabila muncul lagi dalam sequence yang sama. Hanya ada satu instance list penghitung untuk satu sequence database, sedangkan list penyimpan akan selalu di kosongkan bila sequence baru akan diproses.
Penanganan sub-sequence yang memiliki banyak elemen adalah dengan memecah sub-sequence tersebut menjadi seluruh himpunan bagiannya. Himpunan bagiannya yang terdiri dari satu elemen, langsung dimasukkan ke dalam list yang menghitung kemunculan elemen. Untuk himpunan bagian yang memiliki elemen lebih dari satu, meski tidak dimasukkan ke dalam list penghitung, harus tersimpan dalam suatu list untuk persiapan apabila nantinya akan terdapat sub-sequence yang mengandung ‘_’. Fungsi list persiapan ini merupakan gabungan dari list penyimpan dan list penghitung, yaitu menyimpan seluruh himpunan bagian dari sub-sequence sekaligus menghitung jumlah sequence yang mengandung himpunan bagian tersebut. Namun himpunan bagian ini tidak akan masuk ke dalam list penghitung apabila sampai sequence terakhir diproses, tidak terdapat sequence yang mengandung ‘_’ atau sub-sequence tersebut tidak mendukung himpunan bagian yang terdapat pada list persiapan. List persiapan ini lingkupnya sama dengan list penghitung, dan hanya ada satu list untuk setiap sequence database.
Pada kasus sub-sequence yang mengandung ‘_’, caranya adalah dengan memecahnya menjadi himpunan bagian-himpunan bagian yang hanya mengandung dua elemen saja, yaitu elemen ‘_’ dan elemen lainnya dalam sub-sequence. Kemudian dari setiap himpunan bagian yang telah terbentuk tadi, gabungkan dengan prefixnya untuk menghilangkan tanda ‘_’, setelah itu, dilakukan pengecekan terhadap list persiapan untuk mendapatkan informasi mengenai jumlah kemunculannya dalam sequence database.
III-8
Setelah seluruh sequence database diperiksa, isi list penghitung diiterasi untuk di periksa apakah jumlah kemunculan objek yang tersimpan melebihi nilai threshold atau tidak. Jika tidak, objek tersebut akan dihapus dari list. Sisa dari proses penghapusan nantinya merupakan frequent sequence dengan satu elemen.
III.2 Analisis Rancangan Implementasi PrefixSpan [PEI01]
Dengan langkah-langkah global algoritma PrefixSpan seperti yang disebutkan sebelumnya, rancangan implementasinya berupa fungsi rekursif yang ditulis dalam notasi prosedural yang dapat dilihat pada Algortima III-1.Dari definisi yang diberikan sebelumnya, implementasi Algoritma PrefixSpan adalah sebuah fungsi yang rekursif. Hal ini dikarenakan proses yang dilakukan untuk mendapatkan sequential pattern pada length berapapun adalah sama saja, yaitu dengan mencari 1-length frequent sequence dari database yang diberikan untuk kemudian digabungkan atau ditambahkan ke akhir sequential pattern yang menjadi prefix dari database tersebut.
Dengan langkah algoritma seperti pada Algoritma III-1, dapat disimpulkan bahwa setiap database yang dibentuk diakses pada dua tahap untuk setiap pemanggilan fungsi PrefixSpan. Pertama adalah mencari 1-length frequent sequence untuk menjadi sequential pattern yang akan di-output-kan.
Tahap akses ini hanya membaca saja dan melakukan scan seluruh tupple pada database sekali. Sedangkan yang kedua adalah untuk membentuk projected database yang memiliki prefix setiap anggota list 1-length frequent sequence. Pada tahap kedua ini, akses tidak dapat dipastikan apakah hanya membaca atau melakukan proyeksi karena anggota list 1-length frequent sequence dapat beragam tergantung data yang diberikan. Tipe data yang menyimpan sequential pattern adalah pohon n-ary. Contoh bentuk dapat dilihat pada Gambar III.1.
Pemilihan tipe data pohon adalah untuk memudahkan penelurusan sequential pattern yang dihasilkan dari fungsi PrefixSpan. Sebenarnya tipe pohon ini sama dengan tipe
III-9
Function PrefixSpan(input: a: Sequence, l: integer, S: Sequence database)-> Pohon {
Mencari Sequential Pattern pada sequence database S } Deklarasi Root : Pohon D : Sequence Database Lst : List a' : Sequence
Algoritma Root.nama <- a
If S.length = 0 then
Set anak Root dengan null -> null
Else
Lst <- frequent 1-length Sequence dari S
If Lst.length == 0 then
Set anak Root dengan null -> Root
Else
Foreach Lstmember anggota Lst do
D <- proyeksi S berdasarkan Lstmember a'<- gabungan a dengan Lstmember
tambahkan PrefixSpan(a', l + 1, D) ke anak Root Endfor
-> Root Endif
endif
data list dari segi penggunaannya, namun pohon memberikan keunggulan yang tidak terdapat pada list, yaitu setiap simpul yang terdapat pada pohon memiliki awalan simpul atasnya dan memiliki simpul anak yang awalannya adalah simpul tersebut. Hal ini memberikan kemudahan dari segi penelusuran sequential pattern yang dihasilkan. Selain itu, setiap tingkat juga mencerminkan ukuran panjang dari sequential pattern yang berada pada tingkat tersebut. Penggunaan pohon yang n-ary didasari oleh keadaan bahwasanya sequential pattern yang merupakan supersequence dari sequence yang ada berjumlah acak untuk setiap sequence, sehingga penggunaan pohon n-ary lebih cocok daripada pohon yang biner.
Algoritma III-1 PrefixSpan
Dengan proses seperti ini, terdapat beberapa hal pada PrefixSpan yang memerlukan pengkajian lebih lanjut, yaitu:
III-10
1. Pembangkitan projected database.
Untuk setiap frequent sequence yang dihasilkan, dilakukan pembangkitan projected database dimana frequent sequence tersebut sebagai prefixnya. Jika proses pencarian sequential pattern menghasilan 100 frequent sequence, maka akan terjadi pembangkitan sequence database sebanyak 100 kali. Apabila projected database disimpan pada main memory, besar kemungkinan memory yang tersedia tidak cukup untuk ukuran database besar. Dengan menggunakan alternatif lain, yaitu menyimpan projected database sebagai file atau database yang dibangun sementara untuk keperluan proses, waktu prosesnya algoritmanya akan semakin lama, karena waktu akses main memory jauh lebih cepat daripada akses file.
Gambar III-1 Contoh Penggunaan Pohon n-ary untuk Sequential Pattern
2. Penggunaan prinsip rekursif.
Prinsip rekursif adalah prinsip yang praktis dan kuat, karena pembuat program hanya perlu menentukan basis dan rekurens, kemudian selanjutnya diserahkan kepada komputer untuk mengeksekusi program tersebut. Namun di lain pihak, bila proses yang dilakukan terus menerus memanggil tahap rekurens, akan dicapai kondisi dimana terlalu banyak proses yang menunggu hasil dari tahap rekurens yang dipanggil, dan apabila proses yang menunggu telah melebihi batasnya, program tersebut akan hang dan tidak menghasilkan output.
<ab>
<a>
<b>
<ac>
<>
<b(ab)>
<c>
III-11
Karena PrefixSpan [PEI01] merupakan algoritma yang rekursif, untuk selanjutnya dalam tugas akhir ini, PrefixSpan tersebut akan disebut PrefixSpan rekursif
III.3 Analisis Implementasi PrefixSpan Rekursif
Agar algoritma PrefixSpan dapat berjalan sebagaimana seharusnya, terdapat dua hal harus dilakukan terlebih dahulu, yaitu mengatur nilai threshold yang diinginkan dan membungkus seluruh data pada sequence database ke dalam kelas Sequence. Untuk membungkus sequence database ke dalam kelas Sequence, yang diperlukan adalah nama file yang menyimpan sequence database tersebut. Dengan cara kerja umum seperti ini, diagram use case untuk aplikasi ini dapat dilihat pada Gambar III-2.
user
Mencari Sequent ial Pat t ern
Gambar III-2 Use Case program
Aktor yang terlibat dalam sistem ini adalah orang yang akan menggunakan program ini. Sebagaimana yang terlihat pada diagram use case, satu-satunya yang bisa dilakukan oleh user adalah mencari sequential pattern, dan skenarionya sebagai berikut:
1. Pengguna memasukkan nama file yang merupakan sequence database, nilai threshold dari sequential pattern yang diinginkan dan nama file untuk menyimpan sequential pattern yang dihasilkan
2. Kelas utama akan memanggil method findOneSequence ( ) yang merupakan method milik kelas yang membungkus sequence database untuk mencari frequent sequence satu elemen dari sequence database yang diberikan.
3. Untuk setiap frequent sequence yang ditemukan, dibentuk projected database dimana frequent sequence tersebut dijadikan prefix dari projected database-nya. Selain itu, setiap frequent sequence yang ditemukan digabungkan dengan prefixnya untuk mendapatkan sequential pattern.
III-12
Sequence diagram skenario dapat dilihat pada Gambar III-3
Gambar III-3 Sequence Diagram program
Pada implementasikan, proses-proses seperti proyeksi, pencarian 1-sequence dan lainnya adalah proses yang bisa dilakukan per sequence, karena sama sekali tidak memerlukan informasi apa sequence sebelumnya dan apa sequence sesudahnya. Oleh karena itu perlu dibangun suatu kelas yang membungkus sequence.
Namun terdapat suatu proses yang memerlukan seluruh sequence sebagai suatu kesatuan. Sehingga diperlukan kelas yang memiliki akses terhadap serluruh sequence yang ada. Selain itu, terdapat satu kelas lagi yang perlu untuk dibangun yang berfungsi untuk melakukan pencarian dan penyimpanan Sequential Pattern. Oleh karena itu, rancangan program dari algoritma PrefixSpan terdapat dalam Gambar III.2
Berikut akan diberikan penjelasan lebih lanjut mengenai kelas-kelas yang telah dibangun.
III.3.1 Kelas Sequence
Sequence adalah kelas yang menyimpan sequence. Pada kelas ini terdapat method projected( ) dan method concat( ) yang merupakan implementasi dari mekanisme proyeksi sequence terhadap suatu prefix dan penggabungan prefix dengan postfixnya.
III.3.2 Kelas Data
Kelas ini dibangun untuk membungkus sequence-sequence yang ada, sehingga pemrosesan terhadapnya lebih mudah untuk dilakukan. Di dalam kelas ini terdapat dua fungsi utama, yaitu findOneSequence() dan projected(). findOneSequence()
III-13
adalah untuk menemukan sekumpulan frequent item a yang terdapat didalam list of sequence, dan merupakan implementasi dari mekanisme pencarian satu frequent sequence, sedangkan projected() adalah untuk memroyeksi sequence-sequence tersebut dengan a.
Gambar III-4 Gambar Class Diagram implementasi PrefixSpan
III.3.3 Kelas FSequence
FSequence adalah kelas yang dibangun untuk keperluan internal kelas Data. Fungsinya adalah menyimpan sequence-sequence yang nantikna akan menjadi 1-length frequent sequence. Penggunakan kelas ini hanya terdapat pada method findOneSequence() milik kelas Data.
III.3.4 Kelas PTree
Kelas adalah kelas yang dibangun untuk menyimpan sequential pattern dan mengimplementasikan fungsi PrefixSpan. Struktur penyimpanan sequential pattern adalah dengan menggunakan pohon, karena dengan struktur ini, dapat ditelusuri pembentukan sequential pattern melalui prefix-nya.
III-14
III.4 Evaluasi Implementasi PrefixSpan
Pada implementasi yang dijelaskan pada III.3, terdapat beberapa hal didalamnya yang akan menyebabkan program tidak berjalan sebagaimana mestinya, atau bahkan tidak berjalan sama sekali. Hal-hal tersebut antara lain:
1. Algoritma rekursif. Algoritma memberikan kemudahan pada beberapa kasus, namun seiring dengan kemudahan yang diberikan, terdapat pula resiko yang mungkin akan muncul, yaitu resiko berhentinya program karena call stack komputer yang penuh yang disebabkan oleh terlalu banyak penundaan pemamggilan algoritma rekursif tersebut.
2. Penyimpanan sequence database pada main memory. Hal ini tentu saja menjadi riskan apabila memory yang tersedia tidak lagi mencukupi untuk menyimpan seluruh sequence database yang ada.
3. Pembuatan sequence database sejumlah sequential pattern yang ada. Setiap suatu frequent sequence satu elemen ditemukan, program akan membentuk projected database dengan prefix frequent sequence tersebut. Padahal, terdapat kemungkinan hasil proyeksi tersebut menghasilkan database yang jumlah instance-nya kurang dari nilai threshold atau bahkan tidak ada instance-nya sama sekali. Jika kondisinya seperti ini, tidak mungkin ada frequent sequence yang dihasilkan dari projected database tersebut, karena tidak memenuhi nilai threshold yang ditemukan.
4. Pencarian frequent sequence 1 elemen yang sangat memakan proses pada sequence yang mengandung tanda kurung didalamnya. Hal ini dikarenakan setiap terdapat elemen yang bertanda kurung, penanganan khusus harus dilakukan karena elemen seperti ini mengandung banyak objek. Penanganan khusus ini mengharuskan pembentukan himpunan bagian dari objek pada elemen tersebut. Apabila elemen tersebut terdiri dari 10 objek, maka akan dibentuk 210 himpunan bagian. Apabila terdapat 10 elemen yang seperti ini dalam satu sequence, 10 x 210 himpunan bagian akan dibentuk untuk memroses satu sequence saja. Oleh karena itu, cara pencarian frequent sequence satu elemen perlu diperbaharui.
III-15
III.5 Strategi Implementasi untuk Peningkatan Kinerja
Berdasarkan rancangan implementasi pada III.2, diusulkan beberapa alternatif implementasi untuk peningkatan waktu proses. Kemudian dari usul tersebut, dilakukan percobaan yang terdapat pada Lampiran A untuk mendukung analisis, dan akhirnya disimpulkan usulan yang mana yang layak untuk digunakan.
III.5.1 Alternatif Strategi Implementasi
Beberapa alternatif strategi peningkatan kinerja yang diusulkan antara lain:
1. Perubahan algoritma dari bentuk rekursif menjadi bentuk iteratif. Ketika fungsi rekursif berjalan lama sehingga menjadi terlalu sering memanggil bagian rekurens, akan mengakibatkan error stack overflow, oleh karena itu, bentuk rekursif harus diubah menjadi bentuk iteratif.
2. Data yang digunakan setiap pencarian satu frequent sequence sebenarnya berasal dari sumber yang berbeda dan tidak memiliki keterkaitan satu sama lain. Kondisi seperti ini memungkinkan digunakannya multithreading, karena proses-proses yang terjadi dapat berjalan secara pararrel.
3. Sequence yang diambil dari sequence database tidak disimpan di dalam main memory, hanya dipanggil saja ketika diperlukan. Sebagai gantinya, untuk keperluan proyeksi, kelas Sequence menyimpan dua informasi yang berkaitan dengan sequence yang direpresentasikan olehnya, yaitu satu nilai boolean untuk menentukan apakah postfix tersebut ditambahkan saja di belakang prefix atau digabungkan, dan nilai lainnya adalah integer untuk menyimpan karakter keberapa yang menjadi karakter pertama pada saat tertentu. Misalnya Sequence dari basis data adalah <(ab)cda>, instance kelas Sequence yang bersesuaian berisi false untuk nilai boolean, 1 untuk nilai integer. Beberapa contoh lainnya:
Dengan sequence asalnya adalah <(ab)cda>:
<(_b)cda> = boolean bernilai true, integer bernilai 3 <cda> = boolean bernilai false, integer bernilai 5 <> = boolean bernilai false, integer bernilai 0
Sedangkan untuk sequence aslinya, disimpan di dalam file external atau basis data relasional.
III-16
4. Scan terhadap sequence database adalah proses yang menghabiskan waktu bila ukurannya besar, karena dilakukan pembacaan satu per satu dari awal sampai akhir. Oleh karena itu, dengan diterapkannya algoritma scaning dengan konsep divide and conquer, diharapkan dapat menurunkan waktu proses yang dibutuhkan.
5. Apabila terdapat suatu himpunan sequence satu elemen yang beranggotakan frequent sequence 1 elemen dari suatu sequence database, nantinya keseluruhan sequential pattern tidak mungkin akan mengandung elemen diluar himpunan tersebut. Oleh karena itu, proses pencarian frequent sequence satu elemen yang dapat diubah dari yang sebelumnya mencari elemen yang jumlah kemunculannya melewati threshold menjadi penghitungan berapa kemunculan elemen yang terdapat dalam himpunan tersebut dalam database.
III.5.2 Analisis terhadap Alternatif
Dari usulan yang dikemukakan pada pada III.4.1, terdapat beberapa usulan yang telah diuji melalui percobaan untuk membuktikan kebenarannya. Sedangkan untuk lainnya, hanya dilakukan analisis saja.
1. Perubahan rekursif menjadi iteratif
Usulan ini tidak dilakukan percobaan, karena dari analisis saja sudah dapat diketahui dengan pasti bahwa jika mengunakan rekursif maka akan memiliki kemungkinan error jika rekurens yang terjadi terlalu banyak. Namun implementasi ini akan mengakibatkan output yang tadinya berupa tipe data pohon menjadi list biasa saja. Tidak ada efek yang berarti untuk perubahan ini, hanya saja penelurusan keterurutan penghasilan sequential pattern tidak akan semudah apabila dengan menggunakan tipe data pohon.
2. Penggunaan multithreading
Dilakukan percobaan sederhana untuk usulan ini yang tertera pada Lampiran A-1, namun pada percobaan tersebut tingkat relevansi dengan program adalah rendah. Hal ini disebabkan belum ada rancangan iteratif dari program. Sedangkan Lampiran B menunjukkan bahwa multithreading dapat meningkatkan kinerja dari segi waktu proses suatu program.
III-17
Implementasi alternatif nomor tiga yang diungkapkan pada III.5.1 sangat kompleks dan rentang terhadap bug, sehingga implementasinya nanti hasil proyeksi akan disimpan di file external atau database. Percobaan dilakukan untuk mengetahui mana yang lebih cepat antara akses file external atau akses database. Dari hasil percobaan yang tertera pada Lampiran A-2, file external terbukti lebih baik dari segi kecepatan maupun efisiensi memory.
4. Scan Sequence database dilakukan dengan metode Divide and Conquer akan dapat dilakukan apabila penyimpanan sequence database pada DBMS tertentu. Namun apabila disimpan dalam file, untuk melakukan akses tidak dari awal file diperlukan suatu acuan yang menunjukkan karakter suatu sequence adalah karakter ke berapa dalam file tersebut, atau yang lebih primitif lagi, pada byte ke berapa karakter pertamanya. Oleh karena itu, perlu diciptakan file lain yang menjadi sejenis index untuk memungkinan divide and conquer diimplementasikan.
5. Dengan membatasi pencarian frequent sequence 1 elemen hanya pada himpunan frequent sequence 1 elemen yang ditemukan sebelumnya, penyimpanan sementara elemen yang dihitung dapat dibatasi dari yang semula seluruh elemen menjadi sebagian kecil elemen saja. Selain itu, elemen yang memiliki banyak objek didalamnya tidak perlu dibangkitkan himpunan bagiannya. Permasalahan mengenai kemungkinan membangkitkan ratusan ribu himpunan bagian dapat terselesaikan, karena dengan cara ini tidak perlu dibangkitkan sama sekali himpunan bagian untuk elemen tersebut.
III.6 Analisis Penggunaan Multithreading
Terdapat dua cara untuk mengimplementasikan multithreading dalam permasalahan ini. Yang pertama adalah dengan menciptakan satu thread untuk setiap sequential pattern yang dihasilkan. Nantinya di setiap thread tersebut, dilakukan pemrosesan terhadap sequential pattern tersebut yang akan menghasilkan sequential pattern lainnya apabila memang masih dapat menghasilkan. Cara kedua yaitu dengan menciptakan beberapa thread dalam jumlah yang tetap. Thread-thread ini nantinya akan memproses sequential pattern bergantian. Prinsipnya, setiap thread akan diberikan satu sequential pattern untuk diproses. Apabila masih terdapat sequential
III-18
pattern yang belum diberikan kepada suatu thread untuk diproses, program akan menunggu thread-thread yang sedang berjalan untuk selesai melakukan proses. Bila nanti terdapat thread yang telah selesai memproses, sequential pattern tersebut akan diberikan kepadanya.
Pada Lampiran B, dilakukan percobaan untuk membandingkan kecepatan proses suatu program yang diimplementasikan dengan cara single thread, multithread cara pertama dan multithread cara kedua. Hasilnya menunjukkan bahwa cara kedua memiliki waktu proses yang lebih kecil. Oleh karena itu, perancangan program multithread yang dibangun akan menggunakan cara tersebut.