Saya menggunakan pemecah SAT untuk menyandikan masalah, dan sebagai bagian dari contoh SAT, saya memiliki variabel boolean mana dimaksudkan bahwa salah satu dari ini harus benar dan sisanya harus salah. (Saya terkadang melihat ini digambarkan sebagai pengkodean "satu-panas".)
Saya ingin menyandikan batasan "tepat satu dari harus benar" di SAT. Apa cara terbaik untuk menyandikan batasan ini, untuk membuat pemecah SAT berjalan seefisien mungkin?
Saya dapat melihat banyak cara untuk menyandikan batasan ini:
Kendala berpasangan. Saya dapat menambahkan batasan berpasangan untuk semua untuk memastikan bahwa paling banyak satu adalah benar, dan kemudian menambahkan untuk memastikan bahwa setidaknya satu benar.
Ini menambahkan klausa dan tidak ada variabel boolean tambahan.
Pengkodean biner. Aku bisa memperkenalkan variabel boolean baru untuk mewakili (dalam biner) integer sehingga (menambahkan beberapa kendala boolean untuk memastikan bahwa berada dalam kisaran yang diinginkan ). Lalu, saya dapat menambahkan kendala menegakkan bahwa adalah pohon dan bahwa semua lainnya 's adalah palsu. Dengan kata lain, untuk setiap , kami menambahkan klausa yang menyatakan bahwa .
Ini menambahkan klausa dan saya tidak tahu berapa banyak variabel boolean tambahan.
Hitung jumlah nilai sebenarnya. Saya dapat mengimplementasikan pohon rangkaian boolean adder dan mensyaratkan bahwa , memperlakukan masing-masing sebagai 0 atau 1 sebagai ganti false atau true, dan menggunakan transformasi Tseitin untuk mengubah sirkuit ke SAT klausa. Pohon setengah-adders sudah mencukupi: membatasi output carry masing-masing setengah-penambah menjadi 0, dan membatasi output akhir dari setengah-penambah akhir di pohon menjadi 1. Pohon dapat dipilih dari segala bentuk ( pohon biner seimbang, atau tidak seimbang, atau apa pun).
Ini dapat dilakukan di gerbang dan dengan demikian menambahkan Θ ( n ) klausa dan Θ ( n ) variabel boolean baru.
Kasus khusus dari pendekatan ini adalah untuk memperkenalkan variabel boolean , dengan gagasan bahwa y i harus berisi nilai x 1 ∨ x 2 ∨ ⋯ ∨ x i . Maksud ini dapat ditegakkan dengan menambahkan klausa y i ∨ ¬ x i , y i ∨ ¬ y i - 1 , dan ¬ y i ∨ x i ∨ y i - (di mana kami memperlakukan y 0 sebagai sinonim untuk false) untuki=1,…,n. Selanjutnya, kita dapat menambahkan batasan¬ y i ∨¬ x i + 1 untuki=1,2,…,n-1. Ini pada dasarnya setara dengan transformasi Tseitin dari pohon setengah-penambah, di mana pohon tersebut memiliki bentuk yang tidak seimbang secara maksimal.
Jaringan kupu-kupu. Saya dapat membangun jaringan kupu - kupu pada bit, membatasi input n- bit menjadi 000 ⋯ 01 , membatasi output n- bit menjadi x 1 x 2 ⋯ x n , dan memperlakukan setiap gerbang kupu-kupu 2-bit sebagai gerbang independen yang bertukar atau tidak menukar inputnya dengan keputusan yang harus dilakukan berdasarkan variabel boolean baru yang dibiarkan tidak dibatasi. Lalu, saya bisa menerapkan transformasi Tseitin untuk mengubah rangkaian ke klausa SAT.
Ini membutuhkan gerbang dan dengan demikian menambahkan Θ ( n lg n ) klausa dan Θ ( n lg n ) variabel boolean baru.
Apakah ada metode lain yang saya abaikan? Yang mana yang harus saya gunakan? Adakah yang menguji ini atau mencobanya secara eksperimental, atau adakah yang punya pengalaman dengan semua ini? Apakah jumlah klausa dan / atau jumlah variabel boolean baru metrik stand-in yang baik untuk memperkirakan dampak ini pada kinerja pemecah SAT, atau jika tidak, metrik apa yang akan Anda gunakan?
Saya hanya melihat bahwa jawaban ini memiliki beberapa referensi tentang menegakkan kendala kardinalitas untuk SAT, yaitu, menegakkan kendala yang tepat keluar dari n variabel adalah benar. Jadi, pertanyaan saya sampai pada kasus khusus di mana k = 1 . Mungkin literatur tentang batasan kardinalitas akan membantu menjelaskan pertanyaan saya.
Jawaban:
Untuk kasus khusus k dari n variabel true di mana k = 1, ada pengkodean variabel komandan seperti yang dijelaskan dalam Pengkodean CNF yang Efisien untuk Memilih Objek 1 ke N oleh Klieber dan Kwon. Sederhana: Bagilah variabel menjadi kelompok-kelompok kecil dan tambahkan klausa yang menyebabkan status variabel komandan menyiratkan bahwa sekelompok variabel semuanya salah atau semuanya salah. Kemudian secara rekursif menerapkan algoritma yang sama untuk variabel komandan. Pada akhir proses, tuntutan bahwa salah satu dari segelintir variabel komandan akhir benar. Hasilnya adalah O (n) klausa baru dan O (n) variabel baru.
Mengingat keberadaan dua literal yang ditonton dalam pemecah berbasis DPLL, saya pikir pertumbuhan klausa O (n) adalah keuntungan yang menentukan atas skema pengkodean yang akan menambah lebih banyak klausa.
sumber
Sebuah makalah karya Magnus Björk menjelaskan dua teknik yang layak untuk dicoba.
Untuk 1-out-of- , seseorang dapat menggunakan pengkodean satu-panas dan biner secara bersamaan. Jadi, kita memiliki x 1 , ... , x n sebagai pengkodean satu-panas, dan y 1 , ... , y b sebagai pengkodean biner, di mana b = lg n . Kita dapat mengkodekan batasan "setidaknya satu" dengan mudah, dalam satu klausa tunggal: ( x 1 ∨n x1,…,xn y1,…,yb b=lgn . Kita juga bisa memaksa dua pengkodean agar konsisten dengan 2 lg n(x1∨⋯∨xn) 2lgn klausa: kita hanya menambahkan atau x ixi⟹¬yj , berdasarkan apakahbit j dari pengkodean biner dari i adalah 0 atau 1. Akhirnya, batasan "paling banyak" mengikuti secara otomatis. Ini juga memungkinkan sisa instance SAT untuk menggunakan pengkodean mana pun yang lebih nyaman.xi⟹yj j i
Kertas itu
Magnus Björk. Teknik Penyandian SAT yang Berhasil . 25 Juli 2009.
Alan M. Frisch, Paul A. Giannaros. Pengodean SAT dari At-Most-k Constraint: Some Old, Some New, Some Fast, Some Slow . ModRef 2010.
sumber