Voici une autre façon de voir le problème: Vous avez un réseau engendré par les colonnes de . Utilisez l'algorithme Lenstra – Lenstra – Lovász (LLL) pour obtenir une base réduite de ce réseau. Si vous remplacez par une nouvelle matrice formée par la sortie de LLL, alors les colonnes de généreront toujours le même réseau, mais les vecteurs de base seront plus proches d'être orthogonaux entre eux, et les entrées de devrait avoir une plus petite ampleur.MMMM- 1
À partir de là, il serait également utile de lier chaque composant de séparément: c'est-à-dire que vous pouvez lier le ème composantpar. (Soit dit en passant, le n'est pas correct; nous devons utiliser la somme des éléments sur chaque ligne, pas le maximum.)vje|vje|∑réj = 1| (M- 1)je j|∥ v∥∞≤ ∥M- 1∥
Pour des valeurs de jusqu'à environ 30, l'algorithme LLL se terminera pratiquement instantanément. De manière asymptotique, cela prend , donc cela ralentira pour les très grands , mais en même temps le nombre de points que nous devons vérifier augmente de façon exponentielle en , donc le temps d'exécution du LLL n'est pas vraiment le goulot d'étranglement. En revanche, les économies sur le nombre de points à contrôler peuvent être énormes. J'ai écrit du code GAP pour générer une matrice aléatoire régulière (stochastique) et comparer les limites sur les composants deréO (ré6)réréMv que nous obtenons en utilisant la base d'origine, par rapport à la base réduite en LLL (Soit dit en passant, nous n'avons pas besoin de supposer que la matrice est régulière; j'ai fait cette restriction uniquement parce que c'était le cas dans votre demande):
d: = 8;
M: = IdentityMat (d);
pour i dans [1..d] faire
pour j dans [1..d] do
M [i] [j]: = aléatoire ([- 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;
pour i dans [1..d] faire
pour j dans [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;
Impression ("Limites de la base d'origine:");
uns: = [1..d] * 0 + 1;
v: = MM * uns;
pour i dans [1..d] faire
v [i]: = Int (Floor (v [i]));
Imprimer (v [i]);
Impression(" ");
od;
Imprimer ("\ n (");
Imprimer (produit (v * 2 + 1));
Imprimer ("points à vérifier) \ n");
Print ("Limites pour la base LLL:");
v: = LL * ceux;
pour i dans [1..d] faire
v [i]: = Int (Floor (v [i]));
Imprimer (v [i]);
Impression(" ");
od;
Imprimer ("\ n (");
Imprimer (produit (v * 2 + 1));
Imprimer ("points à vérifier) \ n");
La sortie suivante (basée sur la graine aléatoire par défaut, avec ) n'est pas atypique:ré= 8
Limites de la base d'origine: 9 23 24 4 23 16 23 4
(258370076349 points à vérifier)
Limites pour la base de LLL: 3 3 2 2 3 4 2 3
(2701125 points à vérifier)
Edit : Ce problème est un cas particulier du problème général d'énumération des points de réseau dans les polytopes convexes, qui s'avère être un problème bien étudié, et il existe des algorithmes plus efficaces que celui décrit ci-dessus. Voir cet article pour une enquête.