Menjelaskan relevansi kompleksitas algoritma asimptotik dengan praktik mendesain algoritma

40

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?

Kaveh
sumber
Pertanyaan lain yang relevan adalah: mengapa kita mengabaikan faktor konstan ?
Raphael

Jawaban:

24

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.

  • Hasilnya tidak umum dalam hal mesin. Jalankan benchmark Anda di komputer lain dan Anda mendapatkan hasil yang berbeda dengan pasti, secara kuantitatif, dan bahkan mungkin secara kualitatif.
  • Hasilnya tidak umum dalam hal bahasa pemrograman. Bahasa yang berbeda dapat menyebabkan hasil yang sangat berbeda.
  • Hasilnya tidak umum dalam hal detail implementasi. Anda benar-benar membandingkan program , bukan algoritma; perubahan kecil dalam implementasi dapat menyebabkan perbedaan besar dalam kinerja.
  • Jika kasus terburuk jarang terjadi, sampel input acak mungkin tidak mengandung instance buruk. Itu adil jika Anda peduli dengan kinerja kasus rata-rata, tetapi beberapa lingkungan memerlukan jaminan kasus terburuk.
  • Dalam praktiknya, input set berubah. Biasanya, input menjadi lebih besar dari waktu ke waktu. Jika Anda tidak mengulangi tolok ukur Anda setiap enam bulan (ya, beberapa data tumbuh secepat itu), hasil Anda akan segera tidak berguna¹.

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

  • mempertimbangkan hirarki memori (dan I / O lainnya),
  • menganalisis kasus rata-rata (jika perlu),
  • menganalisis jumlah pernyataan individu (bukan ukuran biaya abstrak) dan
  • menentukan faktor konstan.

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:

if ( input size forever bounded? ) {
  benchmark available implementations, choose best
  schedule new benchmarks for when machine changes
}
else {
  benchmark implementations of all asymptotically good algorithms
  choose the best
  schedule new benchmarks for when machine changes or inputs grow significantly
}

  1. Mungkin ada perubahan gila dalam kinerja absolut dan relatif begitu jumlah cache gagal meningkat, yang biasanya terjadi ketika input tumbuh tetapi mesin tetap sama.
  2. Seperti dalam, para peneliti terkemuka di lapangan tidak mampu melakukannya.
  3. Temukan alat di sini . Contoh penggunaan telah diterbitkan dalam Quicksort Dual Pivot Engineering Java 7 Menggunakan MaLiJAn oleh S. Wild et al. (2012) [ pracetak ]
  4. Analisis Kasus Rata-rata dari Dual 7 Pivot Quicksort Java 7 oleh S. Wild dan M. Nebel (2012) - [ pracetak ]
Raphael
sumber
3
Dapat diperdebatkan, tindakan murni mempelajari teori algoritma akan mempertajam mata Anda dan melatih abstraksi-otak Anda untuk algoritma, memberi Anda alat lain untuk mengevaluasi kode dalam pemrograman setiap hari. Abstrak jauh dari kode, evaluasi prinsip, perbaiki, dan terjemahkan kembali ke kode. Contoh: "Ah, saya mengerti, Anda ingin memprogram kamus. Tetapi Anda pada dasarnya daftar program; mengapa tidak mencoba pohon?"
Raphael
Batasan analisis asimptotik menjadi jelas setelah Anda menggali lebih dalam; Quicksort adalah contoh yang menonjol .
Raphael
1
FWIW, saya telah menulis snapshot terbaru dari pendapat saya tentang notasi Landau di sini .
Raphael
11

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.

Yuval Filmus
sumber
Yuval terima kasih. Motivasi yang terutama menarik adalah bagaimana menjelaskan kepada siswa manfaat analisis asimptotik dan relevansinya dengan praktik merancang dan menggunakan algoritma dalam aplikasi nyata (di mana sebagian besar kali jelas bahwa kita hanya tertarik pada yang terbatas meskipun mungkin sangat banyak contoh), tidak membenarkan kurikulum.
Kaveh
1
Saya bingung dengan premis Anda. Anda tampaknya menganggap kelompok sasaran adalah ahli matematika dan calon programmer, yang merupakan kombinasi aneh dan tidak menjadi ciri ilmuwan komputer. (Juga, saya tidak membagikan pandangan Anda tentang bahasa formal, tapi itu topik lain.)
Raphael
Sebaliknya, saya berasumsi bahwa kelompok sasaran adalah calon programmer. Namun, banyak dari kurikulum itu ada demi para ilmuwan komputer teoretis. Tentu saja, kedua kelompok ini memiliki kebutuhan yang saling bertentangan. Karena sebagian besar sarjana adalah calon programmer, saya pikir kurikulum harus diarahkan kepada mereka, tetapi beberapa akademisi tidak setuju. Mungkin mereka ingin mengajar profesor masa depan. Mungkin Anda bisa menjelaskan sudut pandang mereka.
Yuval Filmus
3
@YuvalFilmus Saya sering menjelaskan bahwa saya tidak percaya bahwa CS = TCS + Programming. Jika Anda mengajar kursus CS (di universitas) dan sebagian besar siswa Anda ingin menjadi programmer, ada yang rusak (imho). Saya berpendapat bahwa setiap ilmuwan komputer dapat mengambil manfaat dari pendidikan yang solid dalam algoritmik, bahasa formal, dan bahkan beberapa teori kompleksitas (dan banyak hal lainnya, seperti cara kerja kompiler dan CPU).
Raphael
2
@ Kartu Memori Arsitektur komputer, grafik komputer, AI, penelitian bahasa pemrograman, ... - daftarnya tidak ada habisnya! TCS benar-benar ceruk, dan pemrograman hanyalah alat untuk (kebanyakan) peneliti CS.
Raphael
7

Ada dua alasan serius untuk menggunakan analisis asimptotik dari waktu berjalan:

  • n

  • 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 ...).

Yves Daoust
sumber
n
Yah, saya tidak berpikir itu aturan sama sekali. Semakin banyak data yang Anda buang, semakin lemah pernyataan yang bisa Anda buat. Perspektif asimptotik (dan, lebih dari itu, "besar-oh") menciptakan pernyataan seperti "Quicksort lebih cepat daripada Insertionsort" yang, jika tidak salah, tidak sepenuhnya benar juga. (Ya, saya katakan bahwa analisis algoritma sering diajarkan salah, imho.)
Raphael
6

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.

Juho
sumber
3

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.

vonbrand
sumber
2
Ini hanya setengah kebenaran: pertama, tampaknya Anda menulis dengan "big-oh" dalam pikiran (yang pertanyaannya tidak disebutkan). Kedua, asimtotik "besar-oh" terkenal karena gagal secara spektakuler untuk "putaran gulma" ketika memilih algoritma: input terbatas pada kenyataannya.
Raphael
3

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.

  1. 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.

  2. SEBUAHSEBUAHSEBUAHmemiliki kompleksitas asimptotik yang lebih baik. Apa yang tidak satupun dari mereka yang lebih baik dari yang lain di semua input? Maka itu menjadi lebih rumit dan tergantung pada apa yang kita pedulikan. Apakah kita peduli dengan input besar atau input kecil? Jika kita peduli dengan input besar maka tidak umum bahwa suatu algoritma memiliki kompleksitas asimptotik yang lebih baik tetapi berperilaku terburuk pada input besar yang kita pedulikan. Jika kita lebih peduli dengan input kecil maka analisis asimptotik mungkin tidak berguna. Kita harus membandingkan waktu berjalan dari algoritma pada input yang kita pedulikan. Dalam praktiknya, untuk tugas-tugas rumit dengan persyaratan rumit, analisis asimptotik mungkin tidak berguna. Untuk masalah dasar yang sederhana yang dibahas buku teks algoritme cukup berguna.

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?).

Θ(nlgn)Θ(n2)Θ(lgn)HAI(n)

Kaveh
sumber
Saya suka jawaban ini cukup untuk mendukung sekarang. Dua catatan: 1) Saya akan menggunakan "biaya" daripada "kompleksitas" di sini. Sebagian karena alasan kesal, tetapi juga karena ada banyak ukuran biaya yang dapat dibayangkan (yang merumitkan semua pertimbangan yang Anda sebutkan). 2) Anda mungkin ingin melakukan lulus bahasa-Polandia. ;)
Raphael
@ Raphael, terima kasih. Saya berencana untuk melakukan edit lagi segera. :)
Kaveh
-2

HAI(n2)HAI(nlogn)HAI(n2) untuk itu selesai dibandingkan dengan quicksort.

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 .

vzn
sumber
Ada banyak wilayah antara "melihat animasi" dan analisis formal, seperti tolok ukur runtime yang luas. Mereka sebenarnya adalah area yang valid sendiri, karena kami tidak memiliki teori untuk menjelaskan semua hal yang memengaruhi runtimes.
Raphael
@raphael Anda membahas tolok ukur dalam jawaban Anda; itu jawaban yang bagus. tetapi perhatikan bahwa animasi / visualisasi dapat terkait erat dengan pembandingan. sebenarnya ada banyak penjelasan tentang apa yang mempengaruhi runtimes [tercakup dalam jawaban lain] tetapi sampai taraf tertentu "noise" dan kompleksitas asymptotic "smooths / averages out the noise". Itulah latihan lain untuk melihat bagaimana sebenarnya itu terjadi.
vzn
Animasi tidak menyaring suara. Plus, mata manusia mudah ditipu, dan itu tidak layak untuk menonton animasi untuk sampel berukuran wajar dari daftar berukuran wajar (katakanlah, 1.000 daftar untuk ukuran dalam jutaan ke tolok ukur pengurutan algoritma) dan memutuskan algoritma mana yang lebih cepat (rata-rata).
Raphael
nn
n