Genera algoritmicamente tutti i punti della griglia all'interno di un ipercubo


8

Il problema deriva direttamente dalla matematica computazionale e può essere dichiarato come segue:

Data una matrice regolare MRd×d , trova in modo efficace tutti i vettori vZd tali che Mv1 , dove Mv è il componente massimo del vettore in modulo.

Fornisco un algoritmo di seguito, ma è molto inefficiente, poiché presenta molti più passaggi rispetto al numero di punti della griglia. Nel mio caso è ancora sopportabile per d=5 , ma fallisce completamente per d=6 , non ho molto tempo; inoltre, vorrei lavorare anche su dimensioni più elevate.


Il mio attuale algoritmo si basa su quanto segue (dichiarazione di non responsabilità: contiene più calcoli matematici): in primo luogo, calcolare M1 . Quindi, osserviamo che vM1MvM1 . Questo significa che possiamo calcolare L=floorM1 e quindi provare tutti i vettori v{L,L+1,,L1,L}d ; ce ne sono esattamente (2L+1)d di essi. (E qui sta il problema: se d=6 e L=18 , ottengo 2.5E9 iterazioni, che sono ordini di grandezza maggiori del numero di punti che penso ci siano.)


1
Hai cercato di formulare il tuo problema come un programma lineare intero e quindi contare le soluzioni? Penso che ci siano metodi disponibili nei risolutori IP (ad es. CPLEX) per farlo, ma non so quanto siano veloci nella pratica. Un metodo per farlo è noto come l'algoritmo di Barvinok.
Cornelius Brand

@ C.Brand Grazie, ci penserò su (comunque, sono passati secoli dall'ultima volta che ho visto qualsiasi LP / IP). Per caso, hai idea se questo è presente in SageMath?
yo

Quanto alle tue preoccupazioni, la formulazione originale del problema è già (quasi) un programma intero; l'unica cosa di cui dovrai occuparti è l'uso del (non lineare) -norm. Ma non ho idea se in SageMath sia disponibile un algoritmo per il conteggio delle soluzioni IP.
Cornelius Brand

Risposte:


3

Ecco un altro modo di guardare al problema: Si dispone di un reticolo generato dalle colonne di . Utilizzare l'algoritmo Lenstra – Lenstra – Lovász (LLL) per ottenere una base ridotta di questo reticolo. Se sostituisci con una nuova matrice formata dall'output di LLL, le colonne di genereranno comunque lo stesso reticolo, ma i vettori di base saranno più vicini all'essere ortogonali tra loro e le voci di dovrebbe avere una grandezza inferiore.MMMM1

Da lì, si contribuirebbe anche a vincolati ogni componente del a parte: ad esempio, è possibile legata la esima componentedi. (A proposito, il limite non è corretto; dobbiamo usare la somma degli elementi su ogni riga, non il massimo.)vi|vi|j=1d|(M1)ij|vM1

Per valori di fino a circa 30, l'algoritmo LLL finirà praticamente all'istante. Asintoticamente, prende , quindi rallenterà per molto grande , ma allo stesso tempo il numero di punti che dobbiamo controllare cresce esponenzialmente in , quindi il tempo di esecuzione della LLL non è realmente il collo di bottiglia. D'altra parte, i risparmi nel numero di punti che devono essere controllati possono essere enormi. Ho scritto un codice GAP per generare una matrice casuale (stocastica) casuale e confrontare i limiti sui componenti didO(d6)ddMv che otteniamo utilizzando la base originale, rispetto alla base ridotta LLL (A proposito, non abbiamo bisogno di presumere che la matrice sia regolare; ho fatto questa restrizione solo perché questo era il caso nella tua applicazione):

d: = 8;
M: = IdentityMat (d);
perché io in [1..d] do
  per j in [1..d] do
    M [i] [j]: = Random ([- 10 ^ 8..10 ^ 8]);
  od;
  M [i]: = M [i] / Somma (M [i]);
od;
L: = LLLReducedBasis (M) .basis;
MM: = M ^ -1 * 1.0;
LL: = L ^ -1 * 1.0;
perché io in [1..d] do
  per j in [1..d] do
    MM [i] [j]: = MM [i] [j] * SignFloat (MM [i] [j]);
    LL [i] [j]: = LL [i] [j] * SignFloat (LL [i] [j]);
  od;
od;

Stampa ("Limiti per base originale:");
quelli: = [1..d] * 0 + 1;
v: = MM * quelli;
perché io in [1..d] do
  v [i]: = Int (Piano (v [i]));
  Stampa (v [i]);
  Stampa(" ");
od;
Stampa ( "\ n (");
Stampa (Prodotto (v * 2 + 1));
Stampa ("punti da controllare) \ n");

Stampa ("Bounds for LLL base:");
v: = LL * quelli;
perché io in [1..d] do
  v [i]: = Int (Piano (v [i]));
  Stampa (v [i]);
  Stampa(" ");
od;
Stampa ( "\ n (");
Stampa (Prodotto (v * 2 + 1));
Stampa ("punti da controllare) \ n");

Il seguente output (basato sul seed casuale predefinito, con ) non è atipico:d=8

Limiti per la base originale: 9 23 24 4 23 16 23 4 
(258370076349 punti da controllare)
Limiti per la base LLL: 3 3 2 2 3 4 2 3 
(2701125 punti da controllare)

Modifica : questo problema è un caso speciale del problema generale dell'enumerazione dei punti reticolari nei polipropilene convessi, che risulta essere un problema ben studiato e che esistono algoritmi più efficienti di quello sopra descritto. Vedi questo documento per un sondaggio.


Ho pensato di ottenere prima una buona base della griglia, ma non sono sicuro di quanto sia efficiente in dimensioni elevate? (Nota: il problema non è attualmente interessante per me da quando siamo riusciti ad andare in giro completamente, ma cercherò di mantenere un occhio su questa domanda ancora.)
yo'

Ho aggiunto altro alla mia risposta, con alcune informazioni sull'efficienza di LLL, oltre a codice e output di esempio.
Brent Kerby,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.