Dalam algoritma dan kompleksitas, kami fokus pada kompleksitas algoritma asimptotik, yaitu jumlah sumber daya yang digunakan algoritma ketika ukuran input mencapai tak terhingga.
Dalam praktiknya, yang dibutuhkan adalah algoritma yang akan bekerja cepat pada sejumlah kasus yang terbatas (walaupun mungkin sangat besar).
Algoritme yang bekerja dengan baik dalam praktik pada jumlah hingga terbatas yang kami minati tidak perlu memiliki kompleksitas asimptotik yang baik (kinerja bagus pada sejumlah terbatas hingga tidak menyiratkan apa pun mengenai kompleksitas asimptotik). Demikian pula, suatu algoritma dengan kompleksitas asimptotik yang baik mungkin tidak bekerja dengan baik dalam praktiknya pada jumlah contoh terbatas yang kita minati (misalnya karena konstanta besar).
Mengapa kita menggunakan kompleksitas asimptotik? Bagaimana analisis asimptotik ini terkait dengan perancangan algoritma dalam praktik?
Jawaban:
Pertanyaan yang menarik adalah: apa alternatifnya? Satu-satunya metode lain yang saya tahu adalah pengujian / pembandingan. Kami memprogram algoritme, membiarkannya berjalan pada (sampel representatif) set input terbatas dan membandingkan hasilnya. Ada beberapa masalah dengan itu.
Yang mengatakan, mengabaikan semua jenis efek dan konstanta dalam analisis adalah tipikal, tetapi dapat disebut malas (sehubungan dengan praktik). Ini berfungsi untuk membandingkan ide-ide algoritmik lebih dari untuk menunjukkan kinerja implementasi (bahkan kodesemu) yang diberikan. Sudah diketahui oleh masyarakat bahwa ini kasar dan bahwa pengamatan yang lebih dekat sering diperlukan; misalnya, Quicksort kurang efisien daripada jenis Penyisipan untuk (sangat) input kecil. Agar adil, analisis yang lebih tepat biasanya sulit ².
Lain, pembenaran posteriori untuk sudut pandang formal dan abstrak adalah bahwa pada tingkat ini, hal-hal seringkali lebih jelas. Dengan demikian, beberapa dekade studi teori telah melahirkan sejumlah ide algoritmik dan struktur data yang berguna dalam praktik. Algoritma optimal secara teoritis tidak selalu yang ingin Anda gunakan dalam praktik - ada pertimbangan lain tetapi kinerja yang harus dibuat; pikirkan tumpukan Fibonacci - dan label ini bahkan mungkin tidak unik. Sulit bagi programmer tipikal yang peduli dengan mengoptimalkan ekspresi aritmatika akan muncul dengan ide baru pada tingkat ini (tidak untuk mengatakan itu tidak terjadi); dia bisa (dan harus) melakukan optimasi itu pada ide yang berasimilasi.
Ada alat teoretis formal untuk menutup celah untuk berlatih sampai batas tertentu. Contohnya adalah
Sebagai contoh, Knuth dikenal secara harfiah menghitung jumlah pernyataan yang berbeda (untuk implementasi yang diberikan dalam model tertentu), memungkinkan untuk perbandingan algoritma yang tepat. Pendekatan itu tidak mungkin pada tingkat abstrak, dan sulit dilakukan dalam model yang lebih kompleks (pikirkan Java). Lihat [4] untuk contoh modern.
Akan selalu ada kesenjangan antara teori dan praktik. Kami saat ini sedang mengerjakan alat³ dengan tujuan untuk menggabungkan yang terbaik dari kedua dunia untuk membuat prediksi suara untuk biaya algoritmik dan runtime (rata-rata), tetapi sejauh ini kami belum dapat menghapus skenario yang salah satu algoritme lebih tinggi biaya tetapi runtime yang lebih kecil (pada beberapa mesin) daripada yang setara (meskipun kami dapat mendeteksi itu, dan mendukung menemukan alasannya).
Saya merekomendasikan bagi praktisi untuk menggunakan teori untuk menyaring ruang algoritma sebelum menjalankan tolok ukur:
sumber
Saya berasumsi bahwa pertanyaan ini muncul dari mengajar kursus yang mencakup analisis asimptotik. Ada beberapa jawaban yang memungkinkan mengapa materi ini diajarkan di kelas pengantar:
Analisis asimptotik adalah abstraksi matematis yang menghasilkan dirinya untuk dianalisis. Sebagai (bisa dibilang) ahli matematika, kami ingin dapat menganalisis algoritma, dan mereka hanya cara untuk menjinakkan kompleksitas mereka menggunakan analisis asimptotik.
Mengevaluasi kinerja asimtotik suatu algoritma memang menunjukkan beberapa prinsip yang berguna dalam praktik: misalnya, berkonsentrasi pada bagian kode yang mengambil sebagian besar waktu, dan diskon bagian mana pun dari kode yang mengambil bagian waktu yang dapat diabaikan secara asimptotik. .
Beberapa teknik analisis asimptotik bermanfaat. Saya merujuk di sini terutama pada apa yang disebut "teorema master", yang dalam banyak keadaan merupakan deskripsi realitas yang baik.
Ada juga alasan historis: ketika orang pertama mulai menganalisis algoritma, mereka dengan sungguh-sungguh berpikir bahwa kompleksitas asimptotik mencerminkan penggunaan praktis. Namun, akhirnya mereka terbukti salah. Hal yang sama terjadi dengan P sebagai kelas masalah yang dapat dipecahkan secara efisien, dan NP sebagai kelas masalah yang tidak dapat diselesaikan, yang keduanya menyesatkan dalam praktiknya.
Secara pribadi, saya pikir analisis asimptotik adalah bagian yang masuk akal dari kurikulum. Bagian yang lebih dipertanyakan termasuk teori bahasa formal dan teori kompleksitas (apa pun yang ada hubungannya dengan mesin Turing). Beberapa orang berpendapat bahwa walaupun mata pelajaran ini tidak berguna bagi calon programmer, mereka menanamkan pemikiran pikiran tertentu yang diperlukan untuk menjadi seorang praktisi yang baik. Yang lain berpendapat bahwa teori kadang-kadang mempengaruhi praktik, dan kasus-kasus langka ini cukup untuk membenarkan pengajaran mata pelajaran yang agak misterius ini kepada khalayak ilmu komputer umum. Saya lebih suka mereka belajar sejarah atau sastra, atau subjek lain yang mereka sukai; keduanya sama relevan dengan prospek pekerjaan masa depan mereka, dan lebih penting bagi mereka sebagai manusia.
sumber
Ada dua alasan serius untuk menggunakan analisis asimptotik dari waktu berjalan:
untuk memungkinkan ketertelusuran matematis. Kasus sedemikian rupa sehingga dimungkinkan untuk menemukan ekspresi yang tepat untuk penghitungan operasi adalah luar biasa. Mempelajari asimptotik membuka lebih banyak kemungkinan (seperti perkiraan asimptotik dari fungsi-fungsi rumit sangat berguna).
Dan ada banyak lainnya (seperti independensi mesin, kebermaknaan, komparabilitas ...).
sumber
Seperti dicatat dalam jawaban Raphael, perhitungan yang tepat untuk waktu berjalan terburuk mungkin sangat sulit. Perhitungan yang tepat juga bisa tidak perlu karena model RAM sudah memperkenalkan perkiraan. Misalnya, apakah semua operasi benar-benar membutuhkan waktu yang sama? Implementasi spesifik (perangkat keras, optimisasi) dapat mempercepat algoritme dengan faktor konstan. Kami ingin memahami seberapa efektif suatu algoritma tidak tergantung pada faktor-faktor ini. Ini adalah motivasi besar untuk penggunaan analisis asimptotik.
sumber
Karena asimptotik adalah "sederhana" (yah, lebih sederhana daripada melakukan analisis yang tepat untuk kasus yang terbatas, toh).
Bandingkan misalnya ensiklopedia "The Art of Computer Programming" oleh Knuth, yang melakukan analisis terperinci dari semua algoritma penting (dan banyak yang tidak begitu penting) dengan analisis rule-of-thumb yang seringkali cukup untuk mendapatkan perkiraan asimptotik ( atau hanya terikat), seperti yang dilakukan dalam kebanyakan buku "algoritma".
Anda tentu benar. Jika masalahnya cukup penting, analisis gaya Knuth (atau mungkin sedikit kurang detail) mungkin diperlukan. Dalam banyak kasus, petunjuk pada kompleksitas asimptotik (mungkin rata-rata dengan dispersi) yang sesuai dengan data eksperimental sudah cukup. Dalam kebanyakan kasus , untuk melakukan klasifikasi kasar dari algoritma yang bersaing, sebagai babak penyisihan pertama yang membandingkan asimptotik dapat cukup tepat. Dan jika tidak ada pesaing, mendapatkan berita buruk tentang biaya tepat dalam detail kecil hanyalah masokisme.
sumber
Di sini, dengan analisis asimptotik, saya berasumsi bahwa yang kami maksud adalah perilaku algoritme ketika ukuran input tidak terhingga.
Alasan kami menggunakan analisis asimptotik adalah karena berguna dalam memprediksi perilaku algoritma dalam praktik . Prediksi memungkinkan kita untuk membuat keputusan, misalnya ketika kita memiliki algoritma yang berbeda untuk masalah mana yang harus kita gunakan? (Bermanfaat bukan berarti selalu benar.)
Pertanyaan yang sama dapat ditanyakan tentang model dunia nyata yang disederhanakan. Mengapa kita menggunakan model matematika sederhana dari dunia nyata?
Pikirkan tentang fisika. Fisika Newton klasik tidak sebagus fisika relativistik dalam memprediksi dunia nyata. Tapi itu adalah model yang cukup baik untuk membangun mobil, gedung pencakar langit, kapal selam, pesawat terbang, jembatan, dll. Ada kasus di mana itu tidak cukup baik, misalnya jika kita ingin membangun satelit atau mengirim pesawat ruang angkasa ke Pluto atau memprediksi pergerakan benda langit besar seperti bintang dan planet atau benda berkecepatan sangat tinggi seperti elektron. Penting untuk mengetahui apa saja batasan suatu model.
Ini biasanya merupakan perkiraan yang cukup baik dari dunia nyata. Dalam praktiknya kita sering melihat bahwa suatu algoritma dengan analisis asimptotik yang lebih baik bekerja lebih baik dalam praktik. Jarang terjadi bahwa suatu algoritma memiliki perilaku asimptotik yang lebih baik. Jadi jika inputnya cukup besar maka kita biasanya dapat mengandalkan analisis asimptotik sebagai prediksi pertama perilaku algoritma. Tidak demikian halnya jika kita tahu inputnya akan kecil. Tergantung pada kinerja yang kita inginkan, kita mungkin perlu melakukan analisis yang lebih hati-hati, misalnya jika kita memiliki informasi tentang distribusi input, algoritma akan diberikan, kita dapat melakukan analisis yang lebih hati-hati untuk mencapai tujuan yang kita miliki (mis. Cepat pada 99 % input). Intinya sebagai langkah awal analisis asimptotik adalah titik awal yang baik. Dalam praktiknya kita juga harus melakukan tes kinerja tetapi perlu diingat juga memiliki masalah sendiri.
Singkatnya, kompleksitas asimptotik relatif mudah untuk menghitung perkiraan kompleksitas algoritma aktual untuk tugas-tugas dasar yang sederhana (masalah dalam buku teks algoritma). Ketika kita membangun program yang lebih rumit, persyaratan kinerja berubah dan menjadi lebih rumit dan analisis asimptotik mungkin tidak berguna.
Adalah baik untuk membandingkan analisis asimptotik dengan pendekatan lain untuk memprediksi kinerja algoritma dan membandingkannya. Salah satu pendekatan yang umum adalah tes kinerja terhadap input acak atau benchmark. Adalah umum ketika menghitung kompleksitas asimptotik sulit atau tidak layak, misalnya ketika kita menggunakan heuristik seperti pada pemecahan SAT. Kasus lain adalah ketika persyaratannya lebih rumit, misalnya ketika kinerja suatu program tergantung pada faktor-faktor luar dan tujuan kami mungkin untuk memiliki sesuatu yang selesai di bawah batas waktu tertentu (misalnya berpikir tentang memperbarui antarmuka yang ditampilkan kepada pengguna) pada 99% dari input.
Namun perlu diingat bahwa analisis kinerja juga memiliki masalah. Itu tidak memberikan penerima matematika pada kinerja pada kurang kita benar-benar menjalankan tes kinerja pada semua input yang akan diberikan kepada algoritma (sering kali komputasi tidak menentu) (dan seringkali tidak mungkin untuk memutuskan beberapa input tidak akan pernah diberikan). Jika kami menguji terhadap sampel acak atau benchmark kami secara implisit mengasumsikan beberapa keteraturan tentang kinerja algoritma, yaitu algoritma akan melakukan hal yang sama pada input lain yang bukan bagian dari tes kinerja.
Masalah kedua dengan tes kinerja adalah bahwa mereka bergantung pada lingkungan pengujian. Yaitu kinerja suatu program tidak ditentukan oleh input saja tetapi faktor-faktor luar (misalnya jenis mesin, sistem operasi, efisiensi algoritma kode, pemanfaatan CPU, waktu akses memori, dll.) Yang beberapa di antaranya mungkin berbeda di antara berbagai program yang berbeda. tes pada mesin yang sama. Sekali lagi di sini kita mengasumsikan bahwa lingkungan tertentu yang dilakukan uji kinerja mirip dengan lingkungan aktual kecuali jika kita melakukan tes kinerja pada semua lingkungan di mana kita dapat menjalankan program (dan bagaimana kita dapat memprediksi mesin apa yang seseorang mungkin menjalankan penyortiran Algoritma aktif dalam 10 tahun?).
sumber
sekarang bayangkan menunggu yang diulang dalam kode sebanyak kode dipanggil. bagaimana cara menghitung / membenarkan keunggulan algoritma quicksort ini secara matematis? (Yaitu namanya benar-benar dibenarkan atau itu hanya slogan pemasaran?) melalui pengukuran kompleksitas asimptotik. orang dibiarkan memandangi animasi-animasi yang secara subyektif merasa bahwa bubbleort adalah suatu algoritma yang lebih lemah dan analisis kompleksitas asimptotik dapat membuktikan hal ini secara kuantitatif. tetapi perhatikan bahwa analisis kompleksitas asimptotik hanyalah satu alat dalam kantong alat untuk menganalisis algoritme dan tidak selalu yang paling utama.
dan nilainya melihat kode berdampingan juga. bubblesort tampaknya secara konsep lebih sederhana dan tidak menggunakan rekursi. quicksort tidak segera dipahami terutama prinsip pivot "median 3". BubbleSort dapat diimplementasikan hanya dalam loop tanpa subrutin, sedangkan quicksort biasanya memiliki setidaknya satu subrutin. ini menunjukkan pola bahwa lebih banyak kecanggihan kode kadang-kadang dapat meningkatkan kompleksitas asimptotik dengan mengorbankan kesederhanaan kode. kadang-kadang ada tradeoff ekstrem yang mirip dengan konsep marginal diminishing return (berasal dari ekonomi) di mana amt kompleksitas kode yang sangat besar [membutuhkan seluruh makalah yang penuh dengan thms dan bukti untuk dibenarkan] hanya membeli perbaikan yang sangat kecil dalam kompleksitas asimptotik. ini muncul sebagai contoh esp denganperkalian matriks dan bahkan dapat dibuat grafik .
sumber