Mengapa masalah knapsack menjadi polinomial semu?

89

Saya tahu itu KnapsackNP-complete sementara itu bisa diselesaikan dengan DP. Mereka mengatakan bahwa solusi DP adalah pseudo-polynomial, karena eksponensial dalam "panjang masukan" (yaitu jumlah bit yang diperlukan untuk menyandikan masukan). Sayangnya saya tidak mengerti. Adakah yang bisa menjelaskan pseudo-polynomialhal itu kepada saya secara perlahan?

Michael
sumber

Jawaban:

92

Waktu berjalan adalah O (NW) untuk masalah knapsack tidak terbatas dengan N item dan knapsack berukuran W. W bukanlah polinomial dalam panjang input, yang membuatnya menjadi pseudo -polynomial.

Pertimbangkan W = 1.000.000.000.000. Hanya membutuhkan 40 bit untuk mewakili angka ini, jadi ukuran input = 40, tetapi runtime komputasi menggunakan faktor 1.000.000.000.000 yaitu O (2 40 ).

Jadi runtime lebih tepat dikatakan O (N.2 bit dalam W ), yang bersifat eksponensial.

Lihat juga:

moinudin
sumber
1
Link # 3 yang mengacu pada "Kompleksitas pemrograman dinamis untuk masalah knapsack 0-1" sudah mati.
dev_nut
1
Maaf, saya tidak mengerti. Katakanlah jika kita memiliki algoritma dengan kompleksitas waktu O (N), maka kita memiliki O (2 ^ (bit dalam N)), yang eksponensial? Terima kasih ~
Lusha Li
3
@LushaLi Ini membantu saya: youtube.com/watch?v=9oI7fg-MIpE . Jika N adalah array di mana setiap elemen memiliki input ukuran maks tetap (katakanlah setiap elemen dalam array tidak lebih dari 32 bit), dan Anda menjalankan loop for pada array ini sekali, maka itu adalah algoritma waktu polinomial di input ukuran N dari array. Namun, jika N adalah bilangan bulat dan Anda menjalankan loop di atas N, maka N tidak dibatasi dan tumbuh secara eksponensial dalam jumlah bit yang diperlukan untuk mewakilinya. Jadi loop sederhana untuk N sebenarnya eksponensial. Perhatikan bahwa dalam kasus larik, ukuran setiap elemen dalam larik dibatasi atas.
max_max_mir
Saya tidak yakin. Ada banyak algoritme dengan properti yang sama yang bukan "pseudo-polinomial". Katakanlah, apa kerumitan Saringan Eratosthenes (atau penemu bilangan prima lainnya)?
Ofir A.
31

Dalam sebagian besar masalah kami, kami berurusan dengan daftar besar angka yang sesuai dengan nyaman di dalam tipe data int / float standar. Karena cara sebagian besar prosesor dibuat untuk menangani nomor 4-8 byte pada satu waktu tanpa biaya tambahan (relatif terhadap jumlah yang tidak sesuai, katakanlah, 1 byte), kami jarang menemukan perubahan dalam waktu berjalan dari penskalaan atau penskalaan nomor kami atau turun dalam rentang yang kita temui dalam masalah nyata - jadi faktor dominan tetap hanya jumlah titik data, faktor n atau m yang biasa kita gunakan.

(Anda dapat membayangkan bahwa notasi Big-O menyembunyikan faktor konstan yang membagi 32 atau 64 bit-per-datum, hanya menyisakan jumlah titik data setiap kali masing-masing bilangan kami cocok dengan banyak bit atau kurang )

Tapi coba kerjakan ulang dengan algoritma lain untuk bertindak pada kumpulan data yang melibatkan int besar - angka yang membutuhkan lebih dari 8 byte untuk mewakili - dan lihat apa pengaruhnya terhadap runtime. Besarnya angka yang terlibat selalu membuat perbedaan, bahkan dalam algoritma lain seperti binary sort, setelah Anda memperluas buffer keamanan, prosesor konvensional memberi kami "gratis" dengan menangani batch 4-8 byte.

Trik dengan algoritma Knapsack yang kita diskusikan adalah bahwa algoritma ini sangat sensitif (relatif terhadap algoritma lain) terhadap besarnya parameter tertentu, W. Tambahkan satu bit ke W dan Anda menggandakan waktu berjalan algoritma. Kami belum pernah melihat respons dramatis semacam itu terhadap perubahan nilai dalam algoritme lain sebelum yang ini, itulah sebabnya mengapa kami memperlakukan Knapsack secara berbeda - tetapi itu adalah analisis asli tentang bagaimana responsnya dalam mode non-polinomial untuk perubahan ukuran input.

shaunak1111
sumber
8

Run-time algoritma Knapsack tidak hanya terikat pada ukuran input (n - jumlah item) tetapi juga pada besarnya input (W - kapasitas knapsack) O (nW) yang eksponensial dalam bagaimana itu direpresentasikan dalam komputer dalam biner (2 ^ n). Kompleksitas komputasi (yaitu bagaimana pemrosesan dilakukan di dalam komputer melalui bit) hanya berkaitan dengan ukuran input, bukan besaran / nilainya .

Abaikan sejenak daftar nilai / bobot. Misalkan kita memiliki sebuah instance dengan kapasitas knapsack 2. W akan mengambil dua bit sebagai input data. Sekarang kita akan meningkatkan kapasitas knapsack menjadi 4, dengan mempertahankan sisa input. Masukan kami hanya bertambah satu bit, tetapi kompleksitas komputasi telah meningkat dua kali lipat. Jika kita meningkatkan kapasitas menjadi 1024, kita hanya akan memiliki 10 bit input untuk W, bukan 2, tetapi kompleksitas telah meningkat dengan faktor 512. Kompleksitas waktu tumbuh secara eksponensial dalam ukuran W dalam representasi biner (atau desimal) .

Contoh sederhana lainnya yang membantu saya memahami konsep pseudo-polinomial adalah algoritme pengujian primality naif. Untuk bilangan tertentu n kita memeriksa apakah itu dibagi rata dengan setiap bilangan bulat dalam rentang 2..√n, sehingga algoritma mengambil langkah √ (n − 1). Tapi di sini, n adalah besarnya input, bukan ukurannya.

                     Now The regular O(n) case

Sebaliknya, mencari larik untuk elemen tertentu berjalan dalam waktu polinomial: O (n). Diperlukan paling banyak n langkah dan di sini n adalah ukuran input (panjang array).

[ Lihat disini ]

Menghitung bit yang diperlukan untuk menyimpan bilangan desimal

shaunak1111
sumber
3
Jadi untuk contoh pencarian terakhir Anda, mengapa tidak menganggap n sebagai biner juga? jika n = 1024, itu juga hanya membutuhkan 10 bit, jadi bukankah itu semu polinomial?
pengguna1024
7

Cara saya memahami ini adalah bahwa kapasitas akan menjadi O (W) jika input kapasitas adalah array [1,2, ..., W] , yang memiliki ukuran W. Tetapi input kapasitas tidak array angka, itu bukan bilangan bulat tunggal. Kompleksitas waktu adalah tentang hubungan dengan ukuran input. The ukuran dari integer adalah TIDAK nilai integer, namun jumlah bit yang mewakili itu. Kami kemudian mengubah bilangan bulat W ini menjadi larik [1,2, ..., W] dalam algoritme, membuat orang salah mengira W adalah ukurannya, tetapi larik ini bukanlah masukan, melainkan bilangan bulat itu sendiri.

Pikirkan input sebagai "larik barang", dan ukurannya sebagai "berapa banyak barang dalam larik". Input item sebenarnya adalah array dari n item dalam array jadi size = n. Input kapasitas BUKAN larik angka W di dalamnya, tetapi bilangan bulat tunggal , diwakili oleh larik bit log (W). Tingkatkan ukurannya sebesar 1 (menambahkan 1 bit bermakna), W berlipat ganda sehingga waktu berjalan berlipat ganda, sehingga kompleksitas waktu eksponensial.

lineil
sumber