Université Louis Pasteur U.F.R. de Mathématiques et dInformatique |
Mémoire de Maîtrise de Mathématiques Pures
Algorithme LLL
présenté par
Sébastien DIEUDONNÉ
et
Jean-Sébastien GOETSCHY
Direction du mémoire : M. Raymond SEROUL
Année 1997
Nous tenons à remercier tout particulièrement M. Raymond Seroul, qui a suivit lélaboration de ce mémoire.
Nous remercions également le personnel de la bibliothèque de lInstitut de Mathématiques de Strasbourg.
Egalement, les salles C12, C15 du même Institut de Mathématiques dont les tableaux nous ont souvent éclairés !
Remerciements *
Sommaire *
Notations, Conventions *
Introduction *
I. Méthode de travail *
II. Conventions *
III. Langages utilisés *
IV. Plan *
Première Partie : Algèbre Linéaire *
I. Bases Mathématiques *
A. Introduction *
B. Représentation matricielle *
II. Algorithmes classiques *
A. Introduction *
B. Pivot de Gauss / Résolution de systèmes linéaires *
C. Déterminant *
D. Noyau et image *
Deuxième Partie : Le vif du sujet *
I. Contexte théorique *
A. Matrices à coefficients entiers *
B. Modules *
1.
Z-Modules *2.
Z-Modules libres de rang fini *C. Algèbre bilinéaire *
1. Forme bilinéaire, forme quadratique
*2. Représentation matricielle
*D. Réseaux *
II. Algorithmes élémentaires *
A. Forme Normale dHermite *
B. Procédé dorthogonalisation de Gram-Schmidt *
III. Algorithme LLL *
A. Réduction de réseaux *
1. Algorithme LLL original
*2. Algorithme LLL avec insertions profondes
*3. Algorithme LLL intégral
*B. Algorithme MLLL pour des vecteurs dépendants *
Troisième Partie : Applications *
I. Dépendance linéaire *
II. Recherche de petits vecteurs dun réseau *
A. Recherche de petits vecteurs de n *
B. Algorithme de Cholesky *
C. Recherche de petits vecteurs dun réseau *
Conclusion *
Bibliographie *
Résumé *
I. Mots Clefs *
II. Condensé *
Le travail que nous proposons est une étude détaillée de lalgorithme de réduction des réseaux proposé par A.K. Lenstra, H.W. Lenstra et L. Lovacz en 1982. Cette étude est essentiellement basée sur louvrage de H. Cohen qui rassemble de nombreux algorithmes mathématiques.
La méthode de travail utilisée consiste en une description théorique des problèmes et objets, puis une mise en pratique au niveau algorithmique et programmation. La partie théorique tentera de pas être trop exhaustive : il nest pas ici question dun cours dalgèbre général. Quant à la partie pratique, elle se veut la plus claire et la plus simple possible.
Les conventions et notations adoptées dans ce mémoire sont énumérées au fil du besoin, outre les signifiants relevés plus haut dans le lexique.
Le choix dun langage de programmation des algorithmes est un problème délicat. Nous avons décidé de retenir le langage Pascal de par son universalité dans le milieu mathématique. La programmation restera simple, voire simpliste dans la plupart des cas. Il ne sagit pas ici dun mémoire dinformatique, mais de mathématiques.
Ce choix se justifie également en opposition à celui de H. Cohen : celui-ci implémente en effet ses algorithmes en GP (programme de calcul), ce qui le conduit à une description " logique " (à la Knuth), faite de renvois enchevêtrés et inextricables. La lisibilité informatique de ces algorithmes savère très délicate.
Pour des raisons de confort de programmation, les premiers tests sont faits avec Mathematica.
Le travail se décompose en trois grands axes. Dans un premier temps, nous donnerons quelques rappels dalgèbre linéaire : les bases théoriques nécessaires à une bonne compréhension du problème et quelques algorithmes classiques.
Par la suite, nous entrerons dans le vif du sujet : la théorie, essentiellement algébrique, et la mise en pratique de quelques algorithmes qui servirons de base par la suite et une étude plus détaillée des algorithmes LLL.
Enfin, nous envisagerons deux applications parmi les plus importantes de cet algorithme.
Nous aurons ici besoin des notions de corps, despace vectoriels et de base. Nous rappelons a ce propos, que tout espace vectoriel admet une base. Nous travaillerons exclusivement avec des espaces vectoriels de dimension finie.
Nous nous intéresserons également à la structure despace euclidien, cest-à-dire, despace vectoriel muni dun produit scalaire. La plupart du temps, nous considérerons des espaces réels muni du produit scalaire usuel, bien que cette théorie sétende à des espaces plus généraux.
Un K espace vectoriel V étant un objet abstrait, on le modélise par la donnée dune base sous forme de matrice à coefficients dans K. On peut alors également représenter un sous-espace (sous-ensemble stable) W de V par une matrice.
Une fonction linéaire f dun espace vectoriel V dans un espace vectoriel W est représentée par la donnée dune matrice A dont les colonnes représentent les coordonnées des images des vecteurs de base de V dans W.
Dans la pratique, nous ne manipulerons donc que des matrices, mais il ne faudra pas perdre de vue linterprétation des calculs effectués.
On notera M(V) la matrice représentant V dans la base canonique, Mn,m(K) lensemble des matrices n ´ m à coefficients dans K et GL(n,K) lensemble des matrices à coefficients dans K carrées de dimension n inversibles.
Les quelques algorithmes qui suivent donnent des outils de base sur les objets introduits plus haut.
On cherche à résoudre le problème :
trouver x tel que Ax = b où A Î GL(n,K), x et b sont deux vecteurs colonnes.
On recherche dans la première colonne un " pivot " non nul. On échange les lignes pour faire venir le pivot en première position et on normalise la ligne. Par combinaisons linéaires, on annule les coefficients de la ligne autres que le pivot qui vaut alors 1. On effectue les opérations simultanément sur une matrice identité. Et on passe à la ligne suivante. Finalement, on aura par des opérations élémentaires transformé la matrice A en identité et la matrice identité de départ en A-1. Ainsi, on a x = A-1.b .
Ce qui donne un code pascal semblable à ce qui suit. Les fonctions asinitrotantes ne figurent pas ici.
Function FirstPivot(Var A : Matrix; dA : Dimension; j : Byte) : Byte;
(***********************************************************************)
(* Cherche le 1er pivot dans la colonne j, renvoie 0 si il n'y en a pas *)
(***********************************************************************)
Var
k,FP : Byte;
Begin
FP:=0;
k:=j;
While (FP=0) And (k<=dA) Do
If A[k,j]<>0
Then FP:=k
Else k:=k+1;
FirstPivot:=FP;
End;
Procedure Gauss(A : Matrix; dA : Dimension;
Var InvA : Matrix; Var Inversible : Boolean);
(***********************************************************************)
(* Inverse la matrice A dans InvA. Inversible est True si A inversible *)
(***********************************************************************)
Const
Introuvable = 0;
Var
j,LignePivot : Byte;
Procedure WorkLine(i,j : Byte; Var A,InvA : Matrix; dA : Dimension);
(*****************************)
(* Travaille avec la ligne j *)
(*****************************)
Var
Coef : Real;
Procedure DoTheWash(c : Byte; Var A, InvA : Matrix; dA : Dimension);
(************************************************)
(* Elimine les coef de la colonne c sauf A[c,c] *)
(************************************************)
Var
k : Byte;
Coef : Real;
Begin
For k:=1 To dA Do
If k<>c
Then
Begin
Coef:=-A[k,c];
LinearCombination(c,k,A,dA,Coef);
LinearCombination(c,k,InvA,dA,Coef);
End;
End;
Begin
If i<>j
Then
Begin
SwapLines(i,j,A,dA);
SwapLines(i,j,InvA,dA);
End;
Coef:=1/A[j,j];
ScalarLine(j,A,dA,Coef);
ScalarLine(j,InvA,dA,Coef);
DoTheWash(j,A,InvA,dA);
End;
Begin
UnitMatrix(InvA,dA);
j:=1;
Inversible:=True;
While Inversible And (j<=dA) Do
Begin
LignePivot:=FirstPivot(A,dA,j);
If LignePivot=Introuvable
Then Inversible:=False
Else
Begin
WorkLine(LignePivot,j,A,InvA,dA);
j:=j+1;
End;
End;
End;
On peut toujours rendre triangulaire supérieure, une matrice A à coefficients dans un corps, par la méthode Gauss. Le déterminant est alors le produit des éléments diagonaux au signe près (on multiplie par 1 à chaque échange de colonnes).
Etant donnée une matrice A, on définit son noyau par la donnée des vecteurs x tels que Ax=0.
Limage est le supplémentaire du noyau dans lespace (en dimension finie, toujours ).
On note GL(n, Z) lensemble des matrices inversibles à coefficients entiers
Théorème : GL(n, Z) = {A Î Mn,n(Z), Det(A)= ±1}
Démonstration : On a A.A-1=1
Comme la fonction Det est un morphisme, on a :
Det(A.A-1)=Det(1)
Û Det(A).Det(A-1)=1
Û Det(A)=Det(A-1)-1
Or, les seuls éléments inversibles de Z sont 1 et 1. þ
On appelle Z-Module de rang fini un groupe abélien isomorphe à un produit de quotients Z/niZ et de Zn.
On appelle Z-Module libre de rang fini n un groupe abélien isomorphe à Zn.
On représente un Z-Module par la matrice de représentation dune base dans la base canonique. On voudrait alors définir les mêmes notions que pour les corps : inversion, noyau, etc.
Définition : Une forme bilinéaire b est une application de V dans K, où V est un espace vectoriel de dimension 2, linéaire en les deux variables.
Définition : Soit K un corps de caractéristique différente de 2, et soit V en K-espace vectoriel. On dit quun application q de V dans K est une forme quadratique si elle satisfait les conditions suivantes :
" l Î K, " x Î V, q(l x)=l 2q(x)
En posant b(x,y)= (q(x+y)-q(x)-q(y)) alors b est une forme bilinéaire (symétrique).
On a alors q(x)=b(x,x).
Remarque : Si K= , on dit que q est définie positive (strictement) si " x Î V, q(x)>0.
On représente une forme bilinéaire par la donnée de la matrice b(ei,ej) où (ei)iÎ une base de V.
On appellera réseau, un -module libre de rang fini muni dune forme quadratique définie positive.
Un cas particulier est de prendre un produit scalaire pour forme bilinéaire et donc la norme associée pour forme quadratique. Cest dans ce cadre essentiellement que nous poursuivrons.
Définition : on dit quune matrice M est en Forme Normal dHermite (ou HNF pour Hermite Normal Form) si elle est de la forme :
Théorème : Soit A Î Mn,m(). Il existe une unique matrice H = (bi,j) Î Mn,m() en HNF telle que H = AU où U Î GL(n,).
Remarque : U nest pas forcément unique.
Théorème (Gram-Schmidt) : Un espace vectoriel euclidien admet une base orthogonale.
Démonstration : On définit par récurrence la nouvelle base où , avec les notations usuelles.
La nouvelle base ainsi définie est trivialement orthogonale. þ
Il est évident que lalgorithme de Gram-Schmidt ne peut se généraliser aux -modules à cause de la division : on ne retombe généralement pas sur un point du réseau Cependant, on peut espérer approcher une base qui soit le plus orthogonale possible, en un sens quil reste définir. Cest cette définition et un algorithme pour trouver cette base qui font lobjet central de ce mémoire.
Définition : En gardant les notation plus haut, une base b1, b2, , bn dun réseau est dite LLL-réduite si :
½ m i,j ½ " 1 j < i n
et b + m i,i-1b 2 b 2 " 1 < i n
Remarque : la deuxième inégalité est équivalente à b 2 ( -m )b 2
Cette inégalité est appelée condition de Lovasz.
Une version Pascal de lalgorithme mettant en uvre cette réduction est proposée ici.
On suppose que (bk) est une base. On procède alors par récurrence : on suppose que les k-1 premiers vecteurs sont déjà LLL-réduits. On peut initialiser cette récurrence pour k=2. On cherche maintenant à réduire le k-ième vecteur, de sorte que ½ m i,j ½ " 1 j < i n. Ceci peut être fait en remplaçants bk par , aj Î : on suppose ½ m i,j ½ " l j <k (vrai pour l=k). En posant alors q comme larrondi de m k,l, bk=bk-q.bl, m k,j nest pas modifié pour j>l (car b est orthogonal à bl pour l<j). On remplace alors m k,l par m k,l-q et ½ m k,l-q½ . On a alors ½ m k,j½ pour l-1<j<k.
Maintenant que la réduction a été effectuée, il faut aussi que bk vérifie la condition de Lovasz. Si (par miracle !) bk satisfaisait cette condition, on passe au vecteur suivant, sil existe. Sinon, on échange les vecteurs bk et bk-1 et on décrémente k, considérant que seuls les k-2 premiers vecteurs sont LLL-réduits.
Pour le calcul des coefficients de Gram (m i,j), la solution retenue est un calcul au fur et à mesure que les coefficients sont nécessaires.
Remarques :
ü
léchange des vecteurs bk et bk-1 induit des changements sur les coefficients de Gram.ü
On calcule tout au long de lalgorithme la matrice de passage H.Ceci donne lalgorithme qui suit
Procedure BasisLLL(b_in : Vector; Var b_out : Vector;
Var H : Matrix);
k, kmax : Integer;
B : Vector;
Lovasz : Boolean;
Begin
(* Begin of Reduction *)
(* Variables Initialization *)
k:=2;
kmax:=1;
SetVectors(b_out[1], b_int[1]);
B[1]:=Dot(b_in[1], b_in[1]);
IdentityMatrix(H, n);
(* Main Loop *)
Repeat
If k>kmax Then Gram(k, kmax);
(* Lovasz's Loop *)
Repeat
Red(k, k-1);
Lovasz:=B[k]>=(0.75-Mu[k,k-1]^2)*B[k-1];
If Not Lovasz
Then Begin
Swap(k);
k:=max(2, k-1);
End;
Until Lovasz;
(* End Lovasz's Loop *)
For l:=k-2 DownTo 1 Do Red (k,l)
k:=k+1;
Until k>n;
(* End Main Loop *)
(* End of Reduction *)
End;
Procedure Red(k, l : Integer);
Var i, q : Integer;
Begin
If Mu[k,l]>0.5 Then
Begin
q:=Round(Mu[k,l]);
"b_in[k]:=b_in[k]-q*b_in[l]";
"Hk:=Hk-q*Hl"; (* Hk est la K-ieme colonne de H *)
Mu[k,l]:=Mu[k,l]-q;
For i:=1 To n-1 Do
Mu[k,i]:=Mu[k,i]-q*Mu[l,i];
End;
End;
Procedure Swap(k : Integer);
Var i,j : Integer;
BT, Temp, Mu : Real;
Begin
ExchangeVectors(b_in[k],b_in[k-1]);
ExchangeMatrixCol(H, k, k-1);
If k>2 Then
For j:=1 To k-2 Do
Begin
Temp:=Mu[k,j];
Mu[k,j]:=Mu[k-1,j];
Mu[k-1,j]:=Temp;
End;
Mu:=Mu[k,k-1];
BT:=B[k]+Mu^2*B[k-1];
Mu[k,k-1]:=Mu*B[k-1]/BT;
B[k]:=B[k-1]*B[k]/BT;
B[k-1]:=BT;
For i:=k+1 To kmax Do
Begin
Temp:=Mu[i,k];
Mu[i,k]:=Mu[i,k-1]-Mu*Temp;
Mu[i,k-1]:=Temp+Mu[k,k-1]*Mu[i,k];
End;
End;
Détails :
La procédure Red : Si m k,l 0,5 , bk est déjà de norme minimale. Sinon, on va soustraire le multiple maximum de bl pour obtenir un m k,l 0,5. On fait les mêmes opérations sur H et il faut rectifier les m k,i pour i<l.
La procédure Swap : En changeant les vecteurs bk et bk-1 (les colonnes k et k-1 de H), il faut modifier les relations de Gram-Schmidt. Pour j<k-2, il suffit déchanger m k,j avec m k-1,j. Pour m k,k-1, m k,kmax, il faut inverser le système :
pour k-1 l kmax. (ce qui induit des changements sur Bk).
Cest-à-dire, en échangeant bk et bk-1 dans ce système.
Ce qui donne le code optimisé plus haut.
Remarques :
ü
On peut modifier lalgorithme pour récupérer uniquement la base ou la matrice H.ü
Cet algorithme faisant intervenir des quantités réelles, dans la pratique, il se peut que le résultat ne soit pas LLL-réduit, mais en général, ce sera le cas. On pourra se référer à lalgorithme LLL intégral plus loin pour contourner cette difficulté.Preuve de lalgorithme : On suppose pour la preuve les b initialisés aux bj. Il est alors clair que (b ) est une base du réseau, tout au long de lalgorithme.
Soit et . Il est évident que D est à valeurs entières.
Lunique partie de lalgorithme ou les Bj sont modifiés (et donc D) est le sous-algorithme SWAP dans lequel on modifie un seul Bk que lon diminue au moins dun facteur par la condition de Lovasz. Donc D est diminuée dun facteur également et reste bien entendu à valeurs entières (les Bj sont toujours des normes au carré de vecteurs à coordonnées entières). Ceci montre que la boucle centrale mettant en jeu lalgorithme SWAP est finie. Comme cest le seul endroit où k est decrémenté, on a montré que lalgorithme se termine. Il est évident que la base obtenue est LLL-réduite.
þ
A la place déchanger simplement bk et bk-1, on peut directement échanger bk avec bi, i<k tel que : . Ceci donne alors lalgorithme schématique qui suit, dont nous ne donnerons pas déquivalent Pascal (il ne nous sera pas utile par la suite).
Le but de cet algorithme est de proposer une version de lalgotihme LLL original ne faisant intervenir que des calculs sur entiers, ce qui garantit la stabilité de lalgorithme.
Théorème et Corollaire :
On suppose que la matrice de Gram (<bi,bj>) est à coefficients entiers (cest le cas ici).
Soit di=det(<br, bs> 1 r, s i) = B1 Bi
Alors pour tout i fixé et pour tout j < i, on a :
di-1Bi Î ,
dim i,j Î ,
pour tout m tel que j < m i, Î .
Soit l i,j = dj m i,j pour j < i et l i,i=di. Alors pour j i fixé, on a :
Alors uk Î et uj-1=l i,j.
Preuve : cf. Ouvrage H. Cohen p. 91-92.
Avec ces notations, on aboutit à lalgorithme suivant :
Procedure IntegralLLL(b_in : Vector; Var b_out : Vector; Var H : Matrix);
Var k, kmax, l : Integer;
Lovasz : Boolean;
Begin
(* Begin Of Reduction *)
(* Gram-Schmidt(b_in, b_out, H); *)
(* ou H=IdentityMatrix(n); b_our:=b_in; *)
(* Variables Initialization *)
k:=2; kmax:=1;
B[0]:=1;
d[1]:=Dot(b_out[1],b_out[1]);
(* Main Loop *)
Repeat
If k>kmax Then
IntegralGram(k, kmax);
(* Lovasz's Loop *)
Repeat
RedI(k, k-1);
Lovasz:=d[k]*d[k-2]>=(0.75*d[k]^2-Lambda[k,k-1]^2);
If Not Lovasz Then
Begin
SwapI(k);
k:=Max(2,k-1);
End;
Until Lovasz;
(* End Of Lovasz's Loop *)
For l:=k-2 DownTo> 1 Do
RedI(k,l);
k:=k+1;
Until k>n;
End;
Procedure RedI(k, l : Integer);
Var i,q : Integer;
Begin
If Abs(2*Lambda[k,l]>d[l]) Then
Begin
q:=Round(Lambda[k,l]/d[l]);
(* Hk:=Hk-q*Hl; *)
Lambda[k,l]:=Lambda[k,l]-q*d[l];
For i:=1 To l-1 Do
Lambda[k,i]:=Lambda[k,i]-q*Lambda[l,i];
End;
End;
Procedure SwapI(k : Integer);
Var i, j, Temp, LambdaT, BT : Integer;
Begin
ExchangeMatrixCol(H, k, k-1);
If k>2 Then
For j:=1 To k-2 Do
Begin
Temp:=Lambda[k,j];
Lambda[k,j]:=Lambda[k-1,j];
Lambda[k-1,j]:=Temp;
End;
LambdaT:=Lambda[k,k-1];
BT:=(d[k-2]*d[k]+LambdaT^2)/d[k-1];
For i:=k+1 To kmax Then
Begin
Temp:=Lambda[i,k];
Lambda[i,k]:=(d[k]*Lambda[i,k-1]-LambdaT*Temp)/d[k-1];
Lambda[i,k-1]:=Temp+LamdaT*Lambda[i,k]/BT;
End;
d[k-1]:=BT;
End;
Procedure IntegralGram(k : Integer; Var kmax : Integer);
Var i,j : Integer;
u : Integer;
Begin
kmax:=k;
For j:=1 To k Do
Begin
u:=Dot(b_in[k],b_in[j]);
For i:=1 To j-1 Do
u:=(d[i]*u-Lambda[k,i]*Lambda[j,i])/d[i-1];
If j<k Then Lambda[k,j]:=u;
If j=k Then d[k]:=u;
End;
If d[k]=0 Then
Begin
Writeln('Les b_in ne forment pas une base.');
Halt(0);
End;
End;
Cet algorithme nappelle pas de commentaire particulier. Sa preuve est identique à celle du précédent.
On peut légèrement modifier lalgorithme LLL pour que celui-ci fonctionne avec une famille de vecteurs ne formant pas nécessairement une base. Lalgorithme devra à ce moment renvoyer la base LLL-réduite formée de p vecteurs indépendants et la matrice de passage, dont les n-p premières colonnes donnerons les relations entre les vecteurs, i.e. des vecteurs v tels que <v,bi> = 0.
Ceci donne lalgorithme qui suit, très voisin du premier algorithme auquel on pourra se référer pour certains détails.
Procedure MLLL(b_in : Vector; Var b_out : Vector;
Var H : Matrix);
Var k, kmax : Integer;
B : Vector;
Lovasz : Boolean;
Begin
(* Begin of Reduction *)
(* Variables Initialization *)
k:=2;
kmax:=1;
SetVecTors(b_out[1], b_int[1]);
B[1]:=Dot(b_in[1], b_in[1]);
IdentityMatrix(H, n);
(* Main Loop *)
Repeat
If k>kmax Then GramM(k, kmax);
(* Lovasz's Loop *)
Repeat
Red(k, k-1);
Lovasz:=B[k]>=(0.75-Mu[k,k-1]^2)*B[k-1];
If Not Lovasz
Then Begin
SwapG(k);
k:=max(2, k-1);
End;
Until Lovasz;
(* End Lovasz's Loop *)
For l:=k-2 DownTo 1 Do Red (k,l)
k:=k+1;
Until k>n;
(* End Main Loop *)
(* End of Reduction *)
End;
Procedure SwapG(k : Integer);
Var i,j : Integer;
BT, Temp, Mu : Real;
Begin
ExchangeVectors(b_in[k],b_in[k-1]);
ExchangeMatrixCol(H, k, k-1);
If k>2 Then
For j:=1 To k-2 Do
Begin
Temp:=Mu[k,j];
Mu[k,j]:=Mu[k-1,j];
Mu[k-1,j]:=Temp;
End;
Mu:=Mu[k,k-1];
BT:=B[k]+Mu^2*B[k-1];
If BT=0 Then
Begin
Temp:=B[k];
B[k]:=B[k-1];
B[k-1]:=Temp;
For i:=k+1 To kmax Do
Begin
Temp:=Mu[i,k];
Mu[i,k]:=Mu[i,k-1];
Mu[i,k-1]:=Temp;
End;
End;
If (B[k]=0) And (Mu<>0)
Then Begin
B[k-1]:=BT;
Mu[k,k-1]:=1/Mu;
For i:=k+1 To kmax Do Mu[i,k-1]:=Mu[i,k-1]/Mu;
End;
If B[k]<>0
Then Begin
Temp:=B[k-1]/BT;
Mu[k,k-1]:=Mu*Temp;
B[k]:=B[k]*Temp;
B[k-1]:=BT;
For i:=k+1 To kmax Do
Begin
Temp:=Mu[i,k];
Mu[i,k]:=Mu[i,k-1]-Mu*Temp;
Mu[i,k-1]:=Temp+Mu[k,k-1]*Mu[i,k];
End;
End;
End;
Procedure GramM(k : Integer; Var kmax : Integer);
Var i,j : Integer;
Begin
kmax:=k;
For j:=1 To k-1 Do
Begin
If B[j]<>0
Then Mu[k,j]:=Dot(b_in[k],b_in[j])/B[j];
Else Mu[k,j]:=0;
End;
For l:=1 To n Do b_out[k,l]:=b_in[k,l];
For j:=1 To k-1 Do
For l:=1 To n Do
b_out[k,l]:=b_out[k,l]-Mu[k,j]*b_out[j,l];
Bk:=Dot(b_out[k],b_out[k]);
End;
Les coefficients de Gram correspondant aux vecteurs nuls sont annulés. Les échanges conduisent à mettre les vecteurs nuls en première position.
On cherche à découvrir une dépendance -linéaire entre les n nombres complexes (z1, , zn), si il en existe une.
Supposons tout dabord que ces nombres soient réels. Pour un entier N assez grand, on considère la forme quadratique en les ai suivante :
Cette forme est définie positive car elle est toujours positive (somme de carrés) et est nulles si et seulement si tous les carrés sont nuls, i.e. et donc a1 = 0 et a est nul. Q définit donc un produit scalaire euclidien sur n si z1 ¹ 0.
Soit a lordre des ai. On peut choisir a n < N < a 2n, par exemple : N = [a 1,5n].
En petit vecteur pour Q vérifie alors : est petit ainsi que les ai pour i > 1. Si les zi sont effectivement -linéaire dépendants, alors on aura trouvé une relation si est nul.
On va en fait appliquer lalgorithme LLL a la base canonique (ei) de n pour la forme quadratique Q. On a alors le lemme suivant :
Lemme : Avec les notations introduites plus haut, si on exécute lalgorithme dorthogonalisation de Gram-Schmidt (pour Q) sur la base (ei), on a :
m i,1 = zi/z1, pour 2 i n
m i,j = 0, pour 2 j < i n
e = ei - (zi/z1) e1
B1 = Nz et Bk = 1 pour 2 k n.
Démonstration : soit b la forme bilinéaire définie par Q. On rappelle que
b(x,y) = (Q(x+y)-Q(x)-Q(y)) pour deux vecteurs x et y.
soit k 2, on a :
Or : Q(e1) = N z , Q(ek) = 1 + N z , Q(e1+ek) = 1 + N(z1+zk)2
Doù : m k,1 = zk/z1.
Soit 2 j < i n :
Q(ei) = 1 + N z , Q(e ) = 1, Q(ei+e ) = 2 + N z
Doù m i,j = 0.
B1 = Q(e1) = N z et Bj = Q(e ) = 1. þ
On peut facilement modifier ce procédé pour travailler avec des nombres complexes. Dans ce cas on prend la forme quadratique:
Q est alors définie positive et définit un produit scalaire euclidien sur R2n ( n) si et seulement si z1/z2 Ï . Si jamais z1/z2 est réel, on cherche un couple zi/zj qui nest pas réel et on réordonne. Si il nen existe pas, on utilise le processus pour les réels 1, z2/z1, , zn/z1.
On utilise lalgorithme LLL pour trouver la relation de dépendance entre les zi la plus " petite " possible, cest-à-dire les coefficients ai les plus petits possibles.
Ceci donne lalgorithme suivant :
Procedure LinDep(z : TabComplex; BigN : Integer);
Var b_in, b_out, B : Vector;
k, kmax, i, j : Integer;
H, Mu : Matrix;
Begin
IdentityMatrix(b_in);
For i:=3 To n Do
For j:=3 To i-1 Do
Mu[i,j]:=0;
B[1]:=Re(z[1])*Re(z[1])+Im(z[1])*Im(z[1]);
B[2]:=Im(cprod(z[1],conj(z[2])));
For i:=3 To n Do
B[i]:=1;
For i:=2 To n Do
Mu[i,1]:=Re(cprod(z[1],conj(z[i])))/B[1];
If B[2]<>0 Then
Begin
For i:=3 To n Do
Mu[i,2]:=Im(cprod(z[1],conj(z[i])))/B[2];
B[2]:=BigN*B[2]*B[2]/B[1];
End
Else Begin
For i:=3 To n Do
Mu[i,2]:=0;
B[2]:=1;
End;
(* LLL *)
SetVectors(b_out[1], b_int[1]);
B[1]:=BigN*B[1];
k:=2;
kmax:=n;
IdentityMatrix(H, n);
Repeat
Repeat
Red(k, k-1);
Lovasz:=B[k]>=(0.75-Mu[k,k-1]^2)*B[k-1];
If Not Lovasz
Then Begin
Swap(k);
k:=max(2, k-1);
End;
Until Lovasz;
For l:=k-2 DownTo 1 Do Red (k,l)
k:=k+1;
Until k>n;
(* End of LLL *)
Output(b_out, z);
End;
Remarque :
ü
On na pas besoin ici de Gram, puisquon leffectue dun seul tenant au début de la procédure.
On veut trouver les petits vecteurs dun réseau, cest-à-dire les vecteurs x tels que Q(x) C, où C est une constante positive entière et Q est la forme quadratique du réseau. On va résoudre ce problème en trois temps : grâce à lalgorithme LLL, on va se placer dans une base plus " sympathique ", chercher dans celle-ci les petits vecteurs et redonner les solutions dans la base originale. On a donc besoin de deux outils : lun qui sache chercher les petits vecteurs de n et lautre qui sache transformer la matrice associée à la forme quadratique sous une forme adéquate : cest lalgorithme classique de Cholesky.
Le but est de trouver tous les vecteurs x non nuls de n vérifiant Q(x) C, où C est une constante positive entière et Q est une forme quadratique du type :
On va choisir (arbitrairement) une coordonnée du vecteur et lui affecter la plus grande valeur possible. On va ensuite la décrémenter et incrémenter successivement les coordonnées suivantes. Cest cette idée intuitive que lon va formaliser
On va choisir et ensuite , et ainsi de suite jusquà obtenir le vecteur. On décrémente ensuite xn et on recommence. Jusquà avoir le vecteur nul
Ceci donne lalgorithme pascal suivant (complet) :
Program ShortVectors;
Uses WinCrt;
Const n=5;
Type Vecteur = Array[1..n] of Integer;
Var
C,i,j : Integer;
q : Array[1..n,1..n] Of Integer;
Function IsNul(x : Vecteur) : boolean;
Var i : Integer;
IsN : Boolean;
Begin
IsN:=True;
For i:=1 To n Do
If x[i]<>0 Then IsN:=False;
IsNul:=IsN;
End;
Procedure SV(C : Integer);
Begin
Var i,j : Integer;
count : Integer;
Z : Real;
T,L,x,U : Vecteur;
NewBounds : Boolean;
Begin
Count:=0;
i:=n;
T[i]:=C;
U[i]:=0;
NewBounds:=True;
Repeat
If NewBounds Then
Begin
Z:=Sqrt(T[i]/q[i,i]);
L[i]:=Trunc(Z-U[i]);
x[i]:=Trunc(-Z-U[i])-1;
End;
Repeat
i:=i+1;
Until x[i-1]<=L[i-1];
i:=i-1;
If i>1 Then
Begin
T[i-1]:=T[i]-q[i,i]*(x[i]+U[i])*(x[i]+U[i]);
i:=i-1;
U[i]:=0;
For j:=i+1 To n Do U[i]:=U[i]+q[i,j]*x[j];
NewBounds:=True;
End
Else
If Not IsNul(x) Then
Begin
Count:=Count+2;
Write('x = (');
For j:=1 To n-1 Do Write(x[j],', ');
Writeln(x[n],')');
Write('-x = (');
For j:=1 To n-1 Do Write(-x[j],', ');
Writeln(-x[n],')');
Writeln('Q(x) = ',C-T[1]+q[1,1]*(x[1]+U[1])*(x[1]+U[1]));
Writeln;
NewBounds:=False;
End;
Until IsNul(x);
Writeln('Nb de vecteurs trouves : ',Count);
End;
For i:=1 To n Do
For j:=1 To n Do
If i=j Then q[i,j]:=1 Else q[i,j]:=0;
C:=7;
InitWinCrt;
SV(C);
Writeln('Appuyez sur Return...');
Readln;
DoneWinCrt;
End.
La preuve de cet algorithme est triviale : si celui-ci ce termine, par les calculs effectués, on est assuré que les vecteurs x sont solutions du problème. De plus, lalgorithme se termine car la norme (forme quadratique) des vecteurs x diminue dans la boucle principale en restant entière.
Le problème est le suivant : soit A une matrice réelle, symétrique définissant la forme quadratique Q. On va chercher une matrice R triangulaire supérieure telle que A= tR.R. En fait, on va mettre Q sous la forme
Lalgorithme est classique pour trouver R, on pourra se référer pour de plus amples détails (par exemple) au cours dAnalyse Numérique de Licence de M. Komornik (Strasbourg) p. 55 ou de DEUG de M. Akesby (Mulhouse) p. 34. La version qui calcule les coefficients de Q est moins usuelle : on pourra se référer à larticle de U. Fincke et M. Pohst paru dans Mathematics of Computation.
Procedure Cholesky(A : Matrix; Var Q, R : Matrix);
Var i,j,k,l : Integer;
Begin
For j:=1 To n Do
For i:=1 To j Do
Q[i,j]:=A[i,j];
i:=0;
Repeat
i:=i+1;
If i<n Then
Begin
For j:=i+1 To n Do
Begin
Q[j,i]:=Q[i,j];
Q[i,j]:=Q[i,j]/Q[i,i];
End;
For l:=i+1 To n Do
For k:=i+1 To l Do
Q[k,l]:=Q[k,l]-Q[k,i]*Q[i,l];
End;
Until i=n;
For i:=1 To n Do
Begin
R[i,i]:=Sqrt(Q[i,i]);
For j:=1 To i-1 Do R[i,j]:=0;
For j:=i+1 To n Do R[i,j]:=R[i,i]*Q[i,j];
End;
End;
On rappelle que Q(x) = txAx. En décomposant A = tRR par la méthode de Cholesky, on obtient Q(x) = txtRRx. Donc résoudre le problème Q(x) C revient à résoudre :
t
xtRRx COn introduit alors les notations : ri représente la i-ème colonne de R, ri représente la i-ème ligne de R-1.
On observant que R-1Rx=x, on a tri.Rx=xi. Donc par Cauchy-Schwarz :
.
Donc, en réduisant , on réduit lensemble des candidats pour les coordonnées de x. On va donc faire intervenir à cette étape lalgorithme LLL, qui va nous donner une matrice S-1=H-1R-1.
On résoud alors le problème tytSSy C par la méthode du A, et on retrouve les solutions originales par x = Hy !
Une amélioration substancielle de cet algorithme est de proceder à un ordonnement des colonnes de S, cest-à-dire lordre des coefficients de Cholesky. Mais il se peut alors quune solution (xk+1, , xn) de A ne puisse se prolonger en une solution (x1, , xn) convenable. La probabilité de cet événement décroit avec la croissance de lordre des xi.
Procedure FinckePohst(A : Matrix; C : Real);
Var A1,Q,Q1,R,R1,RInv,TRInv,S,TS,SInv,TSInv,H,HInv,THInv,X,Y : Matrix;
Sigma : Array[1..n,1..2] Of Integer;
Begin
Cholesky(A,Q,R);
InverseMatrix(R,RInv);
TransposeMatrix(RInv,TRInv);
BasisLLL(TRInv,TSInv,THInv);
TransposeMatrix(THInv,HInv);
InverseMatrix(HInv,H);
MultMatrix(HInv,RInv,SInv)
MultMatrix(R,H,S);
For i:=1 To n Do
Begin
Sigma[i,1]:=i;
Sigma[i,2]:=0;
For j:=1 To n Do
Sigma[i,2]:=Sigma[i,2]+SInv[i,j]*SInv[i,j];
End;
SortTab(Sigma);
PermuteColumns(S,Sigma);
TransposeMatrix(S,TS);
MultMatrix(TS,S,A1);
Cholesky(A1,Q1,R1);
SV2(C,Q1,Y);
ApplyInvSigma(Y,Sigma);
TransposeMatrix(Y,Y);
MultMatrix(H,Y,X);
OutputMatrix(X);
End;
Détails : Le tableau Sigma sert a calculer et stocker la permutation s qui réordonne la matrice S-1. On stocke donc dans la première ligne de Sigma les indices i et dans une deuxième ligne, les carrés des normes des lignes de S-1. On trie alors ce tableau par ordre décroissant de la deuxième ligne et ceci donne une représentation de la permutation dans la première ligne. Ce tri est effectué par la procédure SortTab.
La procédure PermuteColumns applique alors la permutation s -1 aux colonnes de S. On calcule alors la nouvelle matrice A1 et les nouveaux coefficients de Q1 par la méthode de Cholesky.
On cherche alors les petits vecteurs pour la forme Q1. Cette opération est prise en charge par la procédure SV2 qui est quasi-identique à SV, mais stocke les solutions dans une matrice Y.
Il ny a plus alors quà calculer X = H Y, et les colonnes de X sont alors des vecteurs solutions du problème général.
Remarques :
ü
Notre algorithme contient un nombre important de matrices qui pourrait être optimisé. Nous avons préféré fourni cet algorithme sous cette forme afin daccroître la lisibilité pour le lecteur.ü
Dans le deuxième appel à Cholesky, il nest pas utile de calculer R1.ü
Le gain de temps de cette méthode par rapport à celles préexistantes est consistant : on pourra se reporter à larticle cité plus haut pour une analyse de complexité.Limportance de ces algorithmes LLL est dautant plus grande quils sont très souvent à la base de nombreux problèmes mathématiques et informatiques. Les exemples dapplications que nous avons donnés ne reflètent quune partie des nombreux cas où il est nécessaire de faire appel à une " réduction de réseau ".
Ceci est dautant plus frappant que cet algorithme nexiste que depuis quelques années (1982) et a permis un essor ou une amélioration dune bonne part des algorithmes sur entiers. Ainsi, certaines de ses applications entre en jeux dans la recherche de racines de polynômes
Ce travail fut loccasion de nous replonger dans les mathématiques discrètes et nous a procuré - outre beaucoup dheures dintenses cogitations - un certain plaisir de retrouver un support concret et une réalisation logicielle.
Nous espérons avoir été aussi complets que possible sans égarer le lecteur dans dâpres détails
ü
Algorithme LLLü
Calculs sur Entiersü
Réseauxü
Formes Quadratiques
Ce mémoire aborde lexplication détaillée des algorithmes de Lenstra, Lenstra et Lovasz dorthogonalisation dune base dun réseau.
Le niveau requis nest pas très important puisque la plupart des notions utiles sont rappelées.