Hier ist eine andere Sichtweise auf das Problem: Sie haben ein Gitter, das durch die Spalten von erzeugt wird . Verwenden Sie den Lenstra-Lenstra-Lovász-Algorithmus (LLL), um eine reduzierte Basis dieses Gitters zu erhalten. Wenn Sie M durch eine neue Matrix ersetzen, die durch die Ausgabe von LLL gebildet wird, erzeugen die Spalten von M immer noch dasselbe Gitter, aber die Basisvektoren sind näher daran, orthogonal zueinander zu sein, und die Einträge von M - 1 sollten haben kleinere Größe.MMMM−1
Von dort aus wäre es auch hilfreich, jede Komponente von separat zu binden : dh Sie können die i- te Komponente | binden v i | durch ∑ d j = 1 | ( M - 1 ) i j | . (Übrigens ist die Grenze ‖ v ‖ ∞ ≤ ‖ M - 1 ‖ nicht korrekt; wir müssen die Summe der Elemente in jeder Zeile verwenden, nicht das Maximum.)vi|vi|∑dj=1|(M−1)ij|∥v∥∞≤∥M−1∥
Für Werte von bis etwa 30 wird der LLL-Algorithmus praktisch sofort beendet. Asymptotisch dauert es O ( d 6 ) , so dass es für sehr große d langsamer wird , aber gleichzeitig wächst die Anzahl der Punkte, die wir überprüfen müssen, exponentiell in d , so dass die Laufzeit der LLL nicht wirklich die ist Engpass. Andererseits kann die Einsparung bei der Anzahl der zu prüfenden Punkte enorm sein. Ich habe einen GAP-Code geschrieben, um eine zufällige reguläre (stochastische) Matrix M zu erzeugen und die Grenzen der Komponenten von v zu vergleichendO(d6)ddMv dass wir auf der ursprünglichen Basis im Vergleich zur LLL-reduzierten Basis erhalten (Übrigens müssen wir nicht davon ausgehen, dass die Matrix regelmäßig ist; ich habe diese Einschränkung nur vorgenommen, weil dies in Ihrer Anwendung der Fall war):
d: = 8;
M: = IdentityMat (d);
für ich in [1..d] tun
für j in [1..d] tun
M [i] [j]: = zufällig ([- 10 ^ 8..10 ^ 8]);
od;
M [i]: = M [i] / Summe (M [i]);
od;
L: = LLLReducedBasis (M) .basis;
MM: = M ^ -1 * 1,0;
LL: = L ^ -1 * 1,0;
für ich in [1..d] tun
für j in [1..d] tun
MM [i] [j]: = MM [i] [j] * SignFloat (MM [i] [j]);
LL [i] [j]: = LL [i] [j] * SignFloat (LL [i] [j]);
od;
od;
Drucken ("Grenzen für Originalbasis:");
Einsen: = [1..d] * 0 + 1;
v: = MM * Einsen;
für ich in [1..d] tun
v [i]: = Int (Etage (v [i]));
Drucken (v [i]);
Drucken(" ");
od;
Drucken ("\ n (");
Drucken (Produkt (v * 2 + 1));
Drucken ("zu prüfende Punkte) \ n");
Drucken ("Grenzen für LLL-Basis:");
v: = LL * Einsen;
für ich in [1..d] tun
v [i]: = Int (Etage (v [i]));
Drucken (v [i]);
Drucken(" ");
od;
Drucken ("\ n (");
Drucken (Produkt (v * 2 + 1));
Drucken ("zu prüfende Punkte) \ n");
Die folgende Ausgabe (basierend auf dem Standard-Zufallsstartwert mit ) ist nicht untypisch:d=8
Grenzen für die ursprüngliche Basis: 9 23 24 4 23 16 23 4
(258370076349 zu überprüfende Punkte)
Grenzen für die LLL-Basis: 3 3 2 2 3 4 2 3
(2701125 zu überprüfende Punkte)
Bearbeiten : Dieses Problem ist ein Sonderfall des allgemeinen Problems der Aufzählung von Gitterpunkten in konvexen Polytopen, das sich als gut untersuchtes Problem herausstellt, und es gibt effizientere Algorithmen als den oben beschriebenen. In diesem Artikel finden Sie eine Umfrage.