Rekurensi dan Menghasilkan Fungsi dalam Algoritma

18

Combinatorics memainkan peran penting dalam ilmu komputer. Kami sering menggunakan metode kombinatorial baik dalam analisis maupun desain dalam algoritma. Misalnya satu metode untuk menemukan penutup -vertex yang diatur dalam grafik mungkin hanya memeriksa semua \ binom {n} {k} subset yang mungkin. Sementara fungsi binomial tumbuh secara eksponensial, jika k adalah konstanta tetap kita berakhir dengan algoritma waktu polinomial dengan analisis asimptotik.( nk k(nk)k

Sering kali masalah kehidupan nyata membutuhkan mekanisme kombinatorial yang lebih kompleks yang dapat kita definisikan dalam hal kekambuhan. Salah satu contoh terkenal adalah deret fibonacci (naif) didefinisikan sebagai:

f(n)={1if n=10if n=0f(n1)+f(n2)otherwise

Sekarang menghitung nilai suku ke- n tumbuh secara eksponensial menggunakan pengulangan ini, tetapi berkat pemrograman dinamis, kita dapat menghitungnya dalam waktu linier. Sekarang, tidak semua perulangan meminjamkan diri ke DP (begitu saja, fungsi faktorial), tetapi itu adalah properti yang berpotensi dapat dieksploitasi ketika mendefinisikan beberapa hitungan sebagai perulangan daripada fungsi pembangkit.

Menghasilkan fungsi adalah cara yang elegan untuk memformalkan beberapa hitungan untuk struktur yang diberikan. Mungkin yang paling terkenal adalah fungsi pembangkit binomial yang didefinisikan sebagai:

(x+y)α=k=0(αk)xαkyk

Untungnya ini memiliki solusi bentuk tertutup. Tidak semua fungsi yang menghasilkan mengizinkan deskripsi yang ringkas.

Sekarang pertanyaan saya adalah ini: seberapa sering menghasilkan fungsi yang digunakan dalam desain algoritma? Sangat mudah untuk melihat bagaimana mereka dapat dieksploitasi untuk memahami tingkat pertumbuhan yang dibutuhkan oleh suatu algoritma melalui analisis, tetapi apa yang bisa mereka katakan kepada kami tentang masalah ketika membuat metode untuk memecahkan beberapa masalah?

Jika berkali-kali jumlah yang sama dapat diformulasi ulang sebagai perulangan, maka ia dapat digunakan untuk pemrograman dinamis, tetapi sekali lagi mungkin fungsi pembangkit yang sama memiliki bentuk tertutup. Jadi tidak dipotong secara merata.

Nicholas Mancuso
sumber
Jika fungsi menghasilkan memberikan rumus (misalnya, rumus Binet untuk angka fibonacci) yang dapat digunakan untuk menghitung angka alih-alih menggunakan perulangan (mungkin lebih efisien), apakah Anda menganggap itu sebagai jawaban?
Aryabhata

Jawaban:

11

Menghasilkan fungsi berguna saat Anda merancang algoritma penghitungan. Yaitu, tidak hanya ketika Anda mencari jumlah objek yang memiliki properti tertentu, tetapi juga ketika Anda sedang mencari cara untuk menyebutkan objek-objek ini (dan, mungkin, menghasilkan algoritma untuk menghitung objek). Ada presentasi yang sangat bagus di bab 7 Matematika Beton oleh Ronald Graham, Donald Knuth, dan Oren Patashnik . Contoh-contoh di bawah ini dari buku-buku ini (kesalahan dan kurangnya kejelasan adalah milik saya).

Misalkan Anda mencari cara untuk melakukan perubahan dengan set koin yang diberikan. Misalnya, dengan denominasi AS umum¹, koin yang mungkin adalah . Untuk memberi ¢ 42 dalam perubahan, satu kemungkinan adalah ; kemungkinan lain adalah . Kami akan menulis . Secara lebih umum, kita dapat menulis fungsi pembangkit untuk semua cara untuk memberikan perubahan: Dalam istilah yang lebih teknis, adalah istilah dalam ruang seri daya selama lima variabel[ 25 ] [ 10 ] [ 5 ] [ 1 ] [ 1 ] [ 10 ] [ 10 ] [ 10 ] [ 10 ] [ 10 ] [ 1 ] [ 1 ] 42 [ 25 ] [ 10 ][1],[5],[10],[25],[100][25][10][5][1][1][10][10][10][10][1][1]H = Σ h 0 Σ q 0 Σ d 0 Σ n 0 Σ p 0 [ 100 ] h [ 25 ] q [ 10 ] d [ 5 ] n [ 1 ] p42[25][10][5][1]2=[10]4[1]2

H=h0q0d0n0hal0[100]h[25]q[10]d[5]n[1]hal
[ 100 ] , [ 25 ] , [ 10 ] , [ 5 ] , [ 1 ] [ 100 ] h [ 25 ] q [ 10 ] d [ 5 ] n [ 1 ] p= 100 h + 25 q + 10 d + 5 n + p v v H PH[100],[25],[10],[5],[1]. Tentukan penilaian monomial dalam ruang ini dengan Kemudian cara untuk memberikan sen dalam perubahan adalah jumlah monomial yang penilaiannya adalah . Kita dapat mengekspresikan secara bertahap, dengan terlebih dahulu menuliskan cara untuk memberikan perubahan dalam uang saja, lalu cara untuk memberikan perubahan dalam uang dan nikel, dan seterusnya. ( Maksud tidak ada koin.)
[100]h[25]q[10]d[5]n[1]hal=100h+25q+10d+5n+hal
vvHPNsaya
P=saya+[1]+[1]2+[1]3+...=sayasaya-[1]N=(saya+[5]+[5]2+[5]3+...)P=Psaya-[5]D=(saya+[10]+[10]2+[10]3+...)N=Nsaya-[10]Q=(saya+[25]+[25]2+[25]3+...)D=Dsaya-[25]H=(saya+[100]+[100]2+[100]3+...)Q=Qsaya-[100]
Jika Anda ingin menghitung dan tidak hanya menyebutkan cara untuk melakukan perubahan, maka ada cara sederhana untuk menggunakan seri formal yang kami peroleh. Terapkan homomorfisme Koefisien dalam adalah jumlah cara untuk memberikan sen dalam perubahan.
S:[1]X,[5]X5,[10]X10,[25]X25,[100]X100
XvS(C)v

Contoh yang lebih sulit: misalkan Anda ingin mempelajari semua cara untuk memasang persegi empat dengan 2 × 1 domino. Misalnya, ada dua cara untuk memasang persegi panjang 2 × 2, baik dengan dua domino horizontal atau dengan dua domino vertikal. Menghitung jumlah cara untuk memasang persegi panjang cukup mudah, tetapi case dengan cepat menjadi tidak terlihat. Kita dapat menghitung semua kemungkinan kemiringan pita horizontal dengan tinggi 3 dengan menempelkan domino, yang dengan cepat menghasilkan pola berulang: 2×n3×n

{U=Hai+L.V+ΓΛ+UV=sayaU+=-VΛ=sayaU+-=Λ
di mana bentuk-bentuk lucu mewakili pengaturan domino elementer: bukan domino, adalah domino vertikal di atas bagian kiri domino horizontal, adalah domino vertikal yang disejajarkan dengan bagian bawah pita dengan tinggi 3, adalah domino horizontal yang disejajarkan dengan bagian atas pita ditambah dua domino horisontal di bawahnya dan satu langkah ke kanan, dll. Di sini, perkalian menunjukkan penggabungan horizontal dan tidak komutatif, tetapi ada persamaan antara pola-pola dasar yang membentuk variabel dalam rangkaian kekuatan ini. Seperti sebelumnya dengan koin, kita dapat mengganti untuk setiap domino dan mendapatkan seri penghasil untuk jumlah miring dariHaiL.saya-=X3×(2n/3) persegi panjang (yaitu koefisien adalah jumlah cara untuk memasang persegi panjang area , yang berisi domino dan memiliki lebar ). Serial ini juga dapat digunakan dengan cara yang lebih fleksibel; misalnya, dengan membedakan domino vertikal dan horisontal, kita dapat menghitung tilings dengan jumlah tertentu dari domino vertikal dan horisontal.X3k6k3k2k

Sekali lagi, baca Matematika Beton untuk presentasi yang tidak terburu-buru³.

¹ Saya tahu daftar saya tidak lengkap; anggap AS yang disederhanakan cocok untuk contoh matematika .²
² Juga, jika muncul, anggap koin bulat.
³ Dan pengaturan huruf yang lebih baik.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
8

Saya ingat masalah yang harus saya selesaikan selama kontes pemrograman siswa pada tahun 2001. Masalahnya adalah ini:

Diberikan massa 1, 7, 13, ... (Saya tidak ingat massa mana, tetapi ada massa yang terbatas, determinasi), merancang fungsi yang menentukan apakah bobot yang diberikan dapat ditimbang pada skala dengan ini mengatur massa.

Saya mulai dengan loop bersarang, tetapi dengan cepat menabrak dinding. Kemudian saya menyadari bahwa saya harus mulai dengan menyebutkan apa yang dapat dilakukan dengan massa yang lebih ringan sebelum melanjutkan dengan yang lebih berat. Saya bisa memecahkan masalah dengan banyak loop yang tidak diuji.

Kalau saja saya tidak sombong dan mandiri pada masa itu (dan seandainya saya mengetahui dan mempraktikkan fungsi-fungsi pembangkit), saya mungkin telah mendefinisikan masalah dengan menghasilkan fungsi-fungsi seperti:

Tentukan sebagai OGF untuk jumlah cara yang dapat ditimbang oleh bobot berdasarkan kumpulan massa.nf(x)n

Berapakah berat pada wajan kanan yang dapat saya timbang dengan satu massa 1?

Tiga kemungkinan:

  • Jika saya meletakkan massa di panci kiri, saya bisa menimbang 1.
  • Jika saya meletakkan massa di panci kanan, saya bisa menimbang -1.
  • Jika saya tidak menggunakan massa, saya bisa menimbang 0.

Jadi ada satu cara untuk menimbang , satu cara untuk menimbang , dan satu cara untuk menimbang . Fungsi pembangkit untuk massa ini adalah sesuatu seperti , yang sesuai dengan:0 1 x - 1 + 1 + x-101x-1+1+x

1-x3x(1-x)

Fungsi pembangkit untuk satu massa adalah , yaitu:x - m + 1 + x mmx-m+1+xm

1-x3mxm(1-xm)

Diberi multiset massa, dinyatakan sebagai produk dari fungsi pembangkit massa tunggal:fM.f

f(x)=mM.(1-x3m)xmM.mmM.(1-xm)

Sekarang, mengingat paket yang dapat melakukan operasi pada polinomial, Anda hanya perlu:

  • Hitung kedua produk.
  • Lakukan pembagian produk ini, dimulai dengan tingkat terendah. (yang berakhir)
  • Geser polinomial (pembagian euclidian oleh , menjaga hasil bagi dan membuang sisanya)xk

Dan kamu sudah selesai. Sekarang polinomial Anda memiliki sejumlah cara untuk menimbang pada indeks . Satu-satunya masukan adalah multiset massa .w0wM.

Saya merancang algoritma menggunakan komponen suara secara matematis. Bagian utama dari algoritma, yang merupakan divisi polinomial dengan derajat terendah pertama, adalah linier dan dapat diimplementasikan oleh paket off-the-shelf. Ini mungkin tidak optimal, tetapi tentu saja berkinerja lebih baik daripada yang saya lakukan di kontes, dan dengan cara yang tidak terlalu banyak kesalahan.

Jika Anda mengamati proses pembagian dengan cermat, Anda dengan cepat melihat bahwa sisanya dapat dilihat sebagai "keadaan tersembunyi saat ini" di setiap keadaan proses, dan hasil bagi sebagai hasilnya. Proses berakhir ketika "keadaan tersembunyi saat ini" mencapai nol di mana-mana.

Anda dapat mengimplementasikan polinomial sebagai array atau, jika benar-benar jarang, sebagai daftar indeks-koefisien yang diurutkan, dan ini tidak akan mengubah algoritma.

Laurent LA RIZZA
sumber
3

Saat mengembangkan algoritma untuk maksimisasi submodular monoton di atas matroid, kami harus menyelesaikan perulangan Setelah memperhatikan bahwa , kami mengurangi masalah untuk menghitung beberapa urutan universal . Yang terakhir dicapai menggunakan fungsi menghasilkan, dan dari sana kami mendapat rumus eksplisit untuk , lagi menggunakan fungsi menghasilkan. Anda dapat menemukan solusinya di koran jika Anda penasaran, meskipun kami tidak pernah repot untuk memasukkan derivasi ini.γ ( m ) = m ( γ ( m - 1 ) - γ ( m - 1 ) - 1 ) γ ( 0 ) γ ( m )

γ+1(m)=(2-m)γ(m)+(m-+1)γ-1(m),γ0(m)=1,γm+1(m)=e.
γ(m)=m(γ(m-1)-γ-1(m-1))γ(0)γ(m)
Yuval Filmus
sumber
0

Mungkin studi ekstensif Quicksort, dan banyak variannya, adalah contoh paling jelas. Ada pertimbangan kombinatorik mengatur pertimbangan alternatif, dan menganalisis solusi untuk persamaan yang cukup kompleks menunjukkan keunggulan kinerja (atau tidak) dari mereka.

vonbrand
sumber