Hasilkan secara algoritma semua titik kisi di dalam hypercube

8

Masalahnya datang langsung dari matematika komputasi, dan dapat berupa dinyatakan sebagai berikut:

Diberi matriks reguler MRd×d , temukan secara efektif semua vektor vZd sedemikian rupa sehingga Mv1 , di mana Mv adalah komponen maksimal dari vektor dalam modulus.

Saya memberikan algoritma di bawah ini, tetapi sangat tidak efisien, karena ia memiliki langkah lebih banyak daripada jumlah titik kisi. Masih tertahankan untuk d=5 dalam kasus saya, tetapi gagal sepenuhnya untuk d=6 , saya tidak punya banyak waktu; selain itu, saya juga ingin membuat beberapa pekerjaan pada dimensi yang lebih tinggi.


Algoritma saya saat ini didasarkan pada yang berikut (penafian: mengandung lebih banyak matematika): Pertama, hitung M1 . Kemudian, kami mengamati bahwa vM.-1M.vM.-1 . Ini berarti bahwa kita dapat menghitung L.=lantaiM.-1 dan kemudian mencoba semua vektor v{-L.,-L.+1,...,L.-1,L.}d ; ada persis (2L.+1)d dari mereka. (Dan inilah masalahnya: jika d=6 dan L.=18 , saya mendapatkan iterasi 2.5E9 , yang merupakan urutan besarnya lebih besar dari jumlah poin yang saya pikir ada.)

yo'
sumber
1
Sudahkah Anda melihat ke dalam merumuskan masalah Anda sebagai program linear integer dan kemudian menghitung solusi? Saya pikir ada metode yang tersedia dalam IP solver (misalnya CPLEX) untuk melakukan ini, tetapi saya tidak tahu seberapa cepat mereka dalam praktek. Salah satu metode untuk melakukannya dikenal sebagai Algoritma Barvinok.
Cornelius Brand
@ C.Brand Terima kasih, saya akan memeriksanya (namun, sudah lama sejak saya terakhir melihat LP / IP). Kebetulan, apakah Anda punya ide apakah ini ada di SageMath?
yo '
Mengenai masalah Anda, formulasi asli masalah sudah (hampir) merupakan program integer; satu-satunya hal yang harus Anda urus adalah penggunaan (non-linear) -norm. Tapi saya tidak tahu apakah algoritma untuk menghitung solusi IP tersedia di SageMath.
Cornelius Brand

Jawaban:

3

Berikut cara lain untuk melihat masalah: Anda memiliki kisi yang dihasilkan oleh kolom . Gunakan algoritma Lenstra – Lenstra – Lovász (LLL) untuk mendapatkan basis pengurangan dari kisi ini. Jika Anda mengganti dengan matriks baru yang dibentuk oleh output LLL, maka kolom akan tetap menghasilkan kisi yang sama, tetapi vektor basis akan lebih dekat menjadi ortogonal satu sama lain, dan entri harus memiliki besaran lebih kecil.M.M.M.M.-1

Dari sana, itu juga akan membantu untuk mengikat setiap komponen secara terpisah: yaitu, Anda dapat mengikat komponen ke-oleh. (Omong-omong, ikatan tidak benar; kita perlu menggunakan jumlah elemen pada setiap baris, bukan maksimum.)vsaya|vsaya|j=1d|(M.-1)sayaj|vM.-1

Untuk nilai hingga sekitar 30, algoritma LLL akan langsung selesai secara praktis. Secara asimtotik, dibutuhkan , sehingga akan melambat untuk sangat besar , tetapi pada saat yang sama jumlah titik yang perlu kita periksa tumbuh secara eksponensial dalam , sehingga run-time LLL tidak benar-benar kemacetan. Di sisi lain, penghematan dalam jumlah poin yang perlu diperiksa bisa sangat besar. Saya menulis beberapa kode GAP untuk menghasilkan matriks reguler (stokastik) acak dan membandingkan batas-batas pada komponendHAI(d6)ddM.v yang kami peroleh menggunakan basis asli, dibandingkan dengan basis tereduksi LLL (Ngomong-ngomong, kita tidak perlu mengasumsikan bahwa matriksnya teratur; saya membuat batasan ini hanya karena ini adalah kasus dalam aplikasi Anda):

d: = 8;
M: = IdentityMat (d);
untuk saya di [1..d] lakukan
  untuk j dalam [1..d] lakukan
    M [i] [j]: = Acak ([- 10 ^ 8..10 ^ 8]);
  od;
  M [i]: = M [i] / Sum (M [i]);
od;
L: = LLLReducedBasis (M) .basis;
MM: = M ^ -1 * 1.0;
LL: = L ^ -1 * 1.0;
untuk saya di [1..d] lakukan
  untuk j dalam [1..d] lakukan
    MM [i] [j]: = MM [i] [j] * SignFloat (MM [i] [j]);
    LL [i] [j]: = LL [i] [j] * SignFloat (LL [i] [j]);
  od;
od;

Cetak ("Batas untuk dasar asli:");
yang: = [1..d] * 0 +1;
v: = MM * yang;
untuk saya di [1..d] lakukan
  v [i]: = Int (Lantai (v [i]));
  Cetak (v [i]);
  Cetak ("");
od;
Cetak ("\ n (");
Cetak (Produk (v * 2 + 1));
Cetak ("poin untuk diperiksa) \ n");

Cetak ("Batas untuk basis LLL:");
v: = LL * yang;
untuk saya di [1..d] lakukan
  v [i]: = Int (Lantai (v [i]));
  Cetak (v [i]);
  Cetak ("");
od;
Cetak ("\ n (");
Cetak (Produk (v * 2 + 1));
Cetak ("poin untuk diperiksa) \ n");

Output berikut (berdasarkan pada seed acak default, dengan ) tidak atipikal:d=8

Batas untuk basis asli: 9 23 24 4 23 16 23 4 
(258370076349 poin untuk diperiksa)
Batas untuk dasar LLL: 3 3 2 2 3 4 2 3 
(2701125 poin untuk diperiksa)

Sunting : Masalah ini adalah kasus khusus dari masalah umum penghitungan titik-titik kisi dalam poltop cembung, yang ternyata merupakan masalah yang dipelajari dengan baik, dan ada algoritma yang lebih efisien daripada yang dijelaskan di atas. Lihat ini makalah ini untuk survei.

Brent Kerby
sumber
Saya berpikir untuk mendapatkan basis grid yang baik terlebih dahulu, tetapi saya tidak yakin seberapa efisiennya dalam dimensi tinggi? (Catatan: Masalahnya saat ini tidak menarik bagi saya karena kami berhasil mengatasinya sepenuhnya, tetapi saya akan mencoba untuk mengawasi pertanyaan ini.)
yo
Saya menambahkan beberapa jawaban saya, dengan beberapa informasi tentang efisiensi LLL, serta contoh kode dan output.
Brent Kerby