Generieren Sie algorithmisch alle Gitterpunkte innerhalb eines Hyperwürfels


8

Das Problem kommt direkt aus der Computermathematik und kann sein wie folgt angegeben:

Wenn eine reguläre Matrix , finden Sie effektiv alle Vektoren v \ in \ Z ^ d, so dass \ n {Mv} \ leq1 , wobei \ n {Mv} die maximale Komponente von ist Vektor im Modul. v Z dM v 1 M v MRd×dvZdMv1Mv

Ich gebe unten einen Algorithmus an, der jedoch sehr ineffizient ist, da er viel mehr Schritte als die Anzahl der Gitterpunkte enthält. In meinem Fall ist es für d = 5 immer noch erträglich d=5, aber für d = 6 schlägt es vollständig fehl. d=6Ich habe nicht so viel Zeit. Darüber hinaus möchte ich auch an höheren Dimensionen arbeiten.


Mein aktueller Algorithmus basiert auf Folgendem (Haftungsausschluss: enthält mehr Mathematik): Berechnen Sie zunächst M1 . Dann beobachten wir, dass vM1MvM1 . Dies bedeutet, dass wir L = \ operatorname {floor} \ n {M ^ {- 1}} berechnen L=floorM1und dann alle Vektoren v \ in \ lbrace-L, -L + 1, \ dots, L-1, L \ ausprobieren können } ^ dv{L,L+1,,L1,L}d ; es gibt genau (2L+1)d von ihnen. (Und hier liegt das Problem: Wenn d=6 und L=18 , erhalte ich 2.5E9 Iterationen, was um Größenordnungen größer ist als die Anzahl der Punkte, von denen ich denke, dass sie vorhanden sind.)


1
Haben Sie versucht, Ihr Problem als ganzzahliges lineares Programm zu formulieren und dann Lösungen zu zählen? Ich denke, es gibt Methoden in IP-Solvern (z. B. CPLEX), um dies zu tun, aber ich weiß nicht, wie schnell sie in der Praxis sind. Eine Methode hierfür ist der Barvinok-Algorithmus.
Cornelius Brand

@ C.Brand Danke, ich werde mich darum kümmern (es ist jedoch Ewigkeiten her, seit ich das letzte Mal eine LP / IP gesehen habe). Haben Sie zufällig eine Idee, ob dies in SageMath vorhanden ist?
yo '

In Bezug auf Ihre Bedenken ist die ursprüngliche Formulierung des Problems bereits (fast) ein ganzzahliges Programm. Das einzige, worauf Sie achten müssen, ist die Verwendung der (nichtlinearen) Norm. Ich habe jedoch keine Ahnung, ob in SageMath ein Algorithmus zum Zählen von IP-Lösungen verfügbar ist.
Cornelius Brand

Antworten:


3

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.MMMM1

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|j=1d|(M1)ij|vM1

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.


Ich habe zuerst darüber nachgedacht, eine gute Basis für das Raster zu erhalten, bin mir aber nicht sicher, wie effizient es in hohen Dimensionen ist? (Hinweis: Das Problem ist derzeit für mich nicht interessant, da wir es vollständig umgangen haben, aber ich werde versuchen, diese Frage immer noch im Auge zu behalten.)
yo

Ich habe meiner Antwort einige weitere hinzugefügt, mit einigen Informationen zur Effizienz von LLL sowie Beispielcode und Ausgabe.
Brent Kerby
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.