Kompleksitas Algoritma

Slides:



Advertisements
Presentasi serupa
Desain Dan Analisis Algoritma
Advertisements

Kompleksitas Algoritma
Algoritma dan Struktur Data
MATERI 9 FUNGSI REKURSIF.
Flow Control & Exception Handling
Algoritma Divide and Conquer
Bahan Kuliah IF3051 Strategi Algoritma Oleh: Rinaldi Munir
Desain dan Analisis Algoritma
sebuah fungsi yang memanggil dirinya sendiri
Tim Matematika Diskrit
Kompleksitas Algoritma
Kompleksitas Algoritma
MATEMATIKA DISKRIT Kompleksitas Algoritma Kelompok 9
Algoritma dan Struktur Data
Kompleksitas Algoritma
Kompleksitas Waktu Asimptotik
2 JAM TEORI dan 1 jam praktek
Algoritma & Struktur Data Linked List Evangs Mailoa.
Pertemuan-3 Laju Pertumbuhan Fungsi : Pengertian, motivasi dan manfaat
Algoritma dan Struktur Data
Pertemuan 3 ALGORITMA & FUNGSI KOMPLEKSITAS
Pertemuan-2 Kriteria kebaikan suatu algoritme Correctness
Pertemuan 10 DIVIDE And CONQUER Lanjutan ….
Analisa Algoritma Running Time.
PART 6 Algoritma DOSEN : AHMAD APANDI, ST.
Algoritma Divide and Conquer (Bagian 1) Wahyul Wahidah Maulida, ST., M.Eng.
12-CRS-0106 REVISED 8 FEB 2013 CSG523/ Desain dan Analisis Algoritma Divide and Conquer Intelligence, Computing, Multimedia (ICM)
Algoritma Brute Force Oleh: Muhammad Musta’in ( )
TEL 2112 Dasar Komputer & Pemograman Contoh Pemecahan Masalah
TEL 2112 Dasar Komputer & Pemograman Contoh Pemecahan Masalah
MATERI PERKULIAHAN ANALISIS ALGORITMA
MATERI PERKULIAHAN ANALISIS ALGORITMA
MATERI PERKULIAHAN ANALISIS ALGORITMA
Algoritma Pencarian (searching)
Kompleksitas Algoritma
KUG1A3 Algoritma& Pemrograman
CSG3F3/ Desain dan Analisis Algoritma
Bahan Kuliah IF2211 Strategi Algoritma Oleh: Rinaldi Munir
Strategi Algoritma Kuliah 2 : Kompleksitas Algoritma
MATERI PERKULIAHAN ANALISIS ALGORITMA
MATERI PERKULIAHAN ANALISIS ALGORITMA
Algoritma Divide and Conquer
PENGANTAR STRUKTUR DATA
CSG523/ Desain dan Analisis Algoritma
MATERI PERKULIAHAN ANALISIS ALGORITMA
Mata kuliah : K0144/ Matematika Diskrit Tahun : 2008
Kompleksitas Algoritma
PART 6 Algoritma DOSEN : AHMAD APANDI, ST.
Rahmat Deddy Rianto Dako, ST, M.Eng
Array 1.
Faktor analisa algoritma
Teknik Informatika - Universitas Muhammadiyah Malang (UMM)
TEL 2112 Dasar Komputer & Pemograman Contoh Pemecahan Masalah
MATERI PERKULIAHAN ANALISIS ALGORITMA
BINARY SEARCH Tim Algoritma Pemrograman Teknik Informatika
Mata kuliah : K0144/ Matematika Diskrit Tahun : 2008
Array dan Matriks.
STRUKTUR DATA (10) recursive function
Flow Control & Exception Handling
Modul 4 : Analisis Algoritma & Struktur Data
ALGORITMA BRUTE FORCE Pertemuan 3.
Algoritma Brute Force.
Algoritma Divide and Conquer
Kompleksitas Algoritma
Algoritma Divide and Conquer
Analisa algoritma rekursif
Algoritma Divide and Conquer
Dr. Mufid Nilmada, SSi., MMSI
Analisis Algoritma E. Haodudin Nurkifli Teknik Informatika
SEARCHING Universitas Dian Nuswantoro Semarang 12/7/2018.
Transcript presentasi:

Kompleksitas Algoritma Mengukur efisiensi sebuah Algoritma

Pendahuluan Sebuah masalah dapat memiliki beberapa algoritma penyelesaian. Misalnya untuk pengurutan (sort) Sebuah algoritma tidak saja harus benar, tetapi juga harus efisien (mangkus) Kemangkusan algoritma diukur dari waktu (time) eksekusi algoritma dan kebutuhan ruang (space) memori

Algoritma yang mangkus adalah algoritma yang meminimumkan kebutuhan ruang dan waktu Kebutuhan waktu dan ruang suatu algoritma bergantung pada ukuran masukan (n), yang menyatakan jumlah data diproses Kemangkusan algoritma dapat digunakan untuk menilai algoritma yang bagus dari sejumlah algoritma penyelesaian masalah.

Model Perhitungan Kebutuhan Waktu Menghitung kebutuhan waktu algoritma dengan mengukur waktu sesungguhnya (dalam satuan detik) ketika algoritma dieksekusi oleh komputer bukan cara yang tepat. Alasan: 1. Setiap komputer dengan arsitektur berbeda mempunyai bahasa mesin yang berbeda  waktu setiap operasi antara satu komputer dengan komputer lain tidak sama. 2. Compiler bahasa pemrograman yang berbeda menghasilkan kode mesin yang berbeda  waktu setiap operasi antara compiler dengan compiler lain tidak sama.

Besaran yang dipakai untuk menerangkan model abstrak pengukuran waktu/ruang disebut dengan kompleksitas algoritma Ada 2 jenis kompleksitas algoritma yaitu Kompleksitas waktu T(n), diukur dari jumlah tahapan komputasi yang dibutuhkan untuk menjalankan algoritma sebagai fungsi dari ukuran masukan n Kompleksitas ruang S(n), diukur dari memori yang digunakan oleh struktur data yang terdapat di dalam algoritma sebagai fungsi dari ukuran masukan n

Ukuran masukan (n): jumlah data yang diproses oleh sebuah algoritma. Contoh: Algoritma pengurutan 1000 elemen larik, maka n=1000 Algoritma perkalian 2 buah matriks berukuran 50 x 50, maka n = 50 Dalam praktek perhitungan kompleksitas, ukuran masukan dinyatakan sebagai variabel n saja

Contoh

Kompleksitas Waktu Jumlah tahapan komputasi dihitung dari berapa kali suatu operasi di dalam sebuah algoritma sebagai fungsi ukuran masukan Di Dalam sebuah algoritma, terdapat bermacam jenis operasi, misalnya: Operasi baca tulis Operasi aritmatika Operasi pengisian nilai Operasi pengaksesan elemen larik Operasi pemanggilan fungsi/prosedur Dalam praktek, kita hanya menghitung jumlah operasi khas (tipikal) yang mendasari suatu algoritma

Contoh : algoritma untuk menghitung perpangkatan dua bilangan f(x,y)= xy def pangkat(x, y): hasil = 1 for i in range(0, y): hasil = x * hasil return hasil

Pada dasarnya yang kita lakukan pada kode di atas adalah mengkalikan x dengan dirinya sendiri sebanyak y kali, dan menyimpan hasil kali tersebut di dalam variabel hasil. Baris hasil = x * hasil melakukan perkalian x dengan dirinya sendiri, dan perulangan dilakukan untuk memastikan baris ini dijalankan sebanyak y kali

Y Proses Jml Langkah 1 2 + 1 3 10 2 + 10 12 100 2 + 100 102 1000 2 + 1000 1002 10000 2 + 10000 10002 Semakin meningkatnya jumlah y, semakin nilai 2 yang ditambahkan menjadi tidak relevan.

Semakin besar nilai Y, jml eksekusi semakin besar, jadi bayangkan jika jml eksekusi yg diperlukan Y2 Jml Langkah (Y) Jml Langkah (Y2) 1 10 100 10000 1000 1000000 100000000

Contoh operasi khas di dalam algoritma Algoritma pencarian di dalam larik Operasi khas: perbandingan elemen larik Algoritma pengurutan Operasi khas: perbandingan elemen dan pertukaran elemen Algoritm penjumlahan 2 buah matriks Operasi khas: penjumlahan Algoritma perkalian 2 buah matriks Operasi khas: perkalian dan penjumlahan

Tinjau algoritma menghitung rerata sebuah larik. sum 0 for i  1 to n do sum  sum + a[i] endfor rata_rata  sum/n Operasi yang mendasar pada algoritma tersebut adalah operasi penjumlahan elemen-elemen ai (yaitu sumsum+a[i]) yang dilakukan sebanyak n kali. Kompleksitas waktu: T(n) = n.

Kompleksitas waktu dibedakan atas tiga macam: Tmax(n): Kompleksitas waktu untuk kasus terburuk (worst case)  kebutuhan waktu maksimum Tmin(n): Kompleksitas waktu untuk kasus terbaik (best case)  kebutuhan waktu minimum Tavg(n): Kompleksitas waktu untuk kasus rata-rata (average case)  kebutuhan waktu secara rata-rata

Jumlah operasi perbandingan elemen tabel: 1. Kasus terbaik: ini terjadi bila a1 = x Tmin(n) = 1 2. Kasus terburuk: bila an = x atau x tidak ditemukan. Tmax(n) = n 3. Kasus rata-rata: Jika x ditemukan pada posisi ke-j, maka operasi perbandingan (ak = x) akan dieksekusi sebanyak j kali.

Notasi Asimtotik Perhitungan pertumbuhan fungsi seperti yang kita lakukan sebelumnya sangat krusial dalam menghitung efisiensi sebuah algoritma Penulisan fungsi pertumbuhan dilakukan dengan menggunakan notasi asimtotik

Jenis Notasi Asimtotik Keadaan terbaik (best case) Dilambangkan dengan notasi (...) dibaca Theta Keadaan rata-rata (average case) Dilambangkan dengan notasi (...) dibaca Omega Keadaan terburuk (worst case) Dilambangkan dengan notasi O(...) dibaca Big-O

Kinerja sebuah algoritma biasanya diukur dengan menggunakan patokan keadaan terburuk (worst case) yang dinyatakan dengan Big-O. Big-O dipilih karena merupakan notasi yang paling populer dan paling banyak digunakan pada kalangan peneliti ilmu komputer Fungsi Big-O Nama O(1) Konstan O(Log n) Logaritmik O(n) Linier O(n log n) n log n O(n2) Kuadratik O(nm) Polinomial O(n!) Faktorial

O(1), Konstan Sebuah algoritma yang memiliki kompleksitas konstan tidak bertumbuh berdasarkan ukuran dari data atau masukan yang diterima algoritma tersebut. Bahkan, algoritma dengan kompleksitas ini tidak akan bertumbuh sama sekali. Berapapun ukuran data atau masukan yang diterima, algoritma dengan kompleksitas konstan akan memiliki jumlah langkah yang sama untuk dieksekusi

void add_list(node *anchor, node *new_list) { new_list->next = anchor->next; anchor->next = new_list; } untuk menambahkan elemen baru ke dalam linked list tidak memerlukan perulangan, percabangan, ataupun banyak langkah

O(log n): Kompleksitas Logaritmik Algoritma dengan kompleksitas logaritmik merupakan algoritma yang menyelesaikan masalah dengan membagi-bagi masalah tersebut menjadi beberapa bagian, sehingga masalah dapat diselesaikan tanpa harus melakukan komputasi atau pengecekan terhadap seluruh masukan

def binary_search(lst, search): lower_bound = 0 upper_bound = len(lst) - 1   while True: if upper_bound < lower_bound: print("Not found.") return -1 i = (lower_bound + upper_bound) // 2 if lst[i] < search: lower_bound = i + 1 elif lst[i] > search: upper_bound = i - 1 else: print("Element " + str(search) + " in " + str(i)) return 0

Langkah yang akan selalu dieksekusi pada awal fungsi, yaitu inisialisasi lower_bound dan upper_bound:  2 langkah. Pengecekan kondisi while (pengecekan tetap dilakukan, walaupun tidak ada perbandingan yang dijalankan): 1 langkah. Pengecekan awal (if upper_bound < lower_bound): 1 langkah. Inialisasi i: 1 langkah. Pengecekan kondisi kedua (if lst[i] < search: ...), kasus terburuk (masuk pada else dan menjalankan kode di dalamnya): 4 langkah.

Setelah melalui langkah kelima, jika elemen belum ditemukan maka kita akan kembali ke langkah kedua. Perhatikan bahwa sejauh ini, meskipun elemen belum ditemukan atau dianggap tidak ditemukan, kita minimal harus menjalankan 2 langkah dan pada setiap perulangan while kita menjalankan 7 langkah. Sampai di titik ini, model matematika untuk fungsi Big-O yang kita dapatkan adalah seperti berikut: f(n)=2+7(jumlah perulangan)

Pertanyaan berikutnya, tentunya adalah berapa kali kita harus melakukan perulangan?  Berhentinya kondisi perulangan ditentukan oleh dua hal, yaitu: Kondisi upper_bound < lower_bound, dan Pengujian apakah lst[i] == search, yang diimplikasikan oleh perintah else. Perhatikan juga bagaimana baik nilai upper_bound maupun lower_bound dipengaruhi secara langsung oleh i, sehingga dapat dikatakan bahwa kunci dari berhentinya perulangan ada pada i

i = (lower_bound + upper_bound) / 2 Melalui baris kode ini: i = (lower_bound + upper_bound) / 2 Terlihat bahwa pada setiap iterasinya nilai i dibagi 2, sehingga untuk setiap iterasinya kita memotong jumlah data yang akan diproses (n) sebanyak setengahnya.

Sejauh ini kita memiliki model matematika seperti berikut (konstanta 2 dihilangkan karena tidak berpengaruh): Jika diturunkan lebih lanjut

kita ketahui kondisi dari pemberhentian perulangan adalah ketika sisa elemen list adalah 1 Artinya : Sehingga dapat dikatakan bahwa binary search memiliki kompleksitas Atau sederhananya

O(n): Kompleksitas Linear Algoritma dengan kompleksitas linear bertumbuh selaras dengan pertumbuhan ukuran data. Maka algoritma ini memerlukan 10 langkah untuk menyelesaikan kalkulasi data berukuran 10, dan ia akan memerlukan 100 langkah untuk data berukuran 100

Contoh lain dari algoritma dengan kompleksitas linear adalah linear search Linear search melakukan pencarian dengan menelusuri elemen-elemen dalam list satu demi satu, mulai dari indeks paling rendah sampai indeks terakhir

def linear_search(lst, search): for i in range(0, len(lst)): if lst[i] == search: print("Nilai ditemukan pada posisi " + str(i)) return 0 print("Nilai tidak ditemukan.") return -1

Dengan menggunakan cara perhitungan yang sama pada perhitungan pangkat, kita bisa mendapatkan jumlah eksekusi kode seperti berikut (dengan asumsi n = len(lst)): Sehingga nilai kompleksitas dari linear search adalah (5 + n) Atau ditulis O(n)

O(n log n) Algoritma dgn kompleksitas (n log n) memiliki cara perhitungan yang sangat mirip dengan algoritma (log n). Pada dasarnya algoritma kelas ini merupakan algoritma log n yang dijalankan sebanyak n kali.

Contoh kasus misalkan kita diminta untuk mencari sepasang bilangan di dalam sebuah list yang jika ditambahkan akan bernilai 0. Asumsikan list yang diberikan sudah terurut.

Salah satu solusi yang paling sederhana ialah dengan menelusuri seluruh list, satu demi satu (kompleksitas: n) lalu mencari elemen yang bernilai invers dari elemen sekarang menggunakan binary search (kompleksitas: log n).

def zero_sum(lst): n = len(lst) for i in range(0, n): j = binary_search(lst, -1 * lst[i]) if j > i: n1 = str(lst[i]) n2 = str(lst[j]) print("Zero sum: " + n1 + " and " + n2 + "\n")

Perhatikan bagaimana kita melakukan binary search sebanyak n kali, sehingga secara sederhana kompleksitas yang akan kita dapatkan adalah  n∗log n=n log n.

O(nm): Kompleksitas Polinomial Algoritma dengan kompleksitas polinomial merupakan salah satu kelas algoritma yang tidak efisien, karena memerlukan jumlah langkah penyelesaian yang jauh lebih besar daripada jumlah data

def kali(a, b): res = 0 for i in range(a): for j in range(b): res += 1 return res

Algoritma di atas melakukan perkalian antara a dan b, dengan melakukan penambahan 1 sebanyak b kali, yang hasilnya ditambahkan sebanyak a kali. Mengabaikan dua langkah, yaitu awal (res = 0) dan akhir (return res) kode, kita dapat melihat total langkah yang diperlukan oleh perulangan bersarang yang ada seperti berikut:

Total langkah karena pada setiap iterasi kita harus menjalankan kode for i in range(b), maka dapat dikatakan kompleksitas dari kode di atas adalah a * b, Jika harga a = b maka kompleksitasnya adalah a2 Dengan bentuk umum nm dengan m=2

Perbandingan Pertumbuhan Seluruh Kompleksitas n log n n log n

Kesimpulan Pengembangan algoritma idealnya diusahakan mendapatkan kompleksitas O(1) atau O(logn). Tetapi pada kenyataannya kita tidak akan selalu mendapatkan kompleksitas terbaik dalam merancang algoritma. Jika tidak dapat mencapai kompleksitas maksimal, hal terbaik yang dapat kita lakukan ketika mengembangkan solusi dari masalah adalah melihat apakah masalah yang ada dapat diselesaikan dengan algoritma yang ada terlebih dahulu, sebelum mengembangkan algoritma baru.