10. Autour de l’algorithme d’Euclide

10.1. Algorithme d’Euclide étendu

L’algorithme d’Euclide étendu consiste à calculer la suite de relations

\[a u_k + b v_k = r_k\]

\[ \begin{align}\begin{aligned}r_0=a, r_1=b,\\\forall k\geq 1, r_{k-1} = q_k r_k + r_{k+1}, 0\leq r_{k+1}<r_k\end{aligned}\end{align} \]

dont on tire la relation de Bezout

\[a u_n + b v_n = r_n\]

en prenant \(n\) tel que \(r_n>0\) et \(r_{n+1}=0\).

  1. Implanter l’algorithme d’Euclide étendu pour deux entiers \(a,b\). On utilisera les fonctions iquo et irem.

Sur \(\k[x]\), les fonctions de quotient et reste deviennent quo et rem. En outre, le pgcd n’est défini qu’à un inversible près, et il est préférable de choisir à chaque étape \(r_k\) unitaire.

L’algorithme s’écrit alors

euclideetendu(a,b):={
  local la,lb,uk1,uk,vk1,vk,rk1,rk,qk,r,l;
  la:=lcoeff(a); lb:=lcoeff(b);
  uk1:=1/la; vk1:=0; rk1:=a/la;
  uk:=0; vk:=1/lb; rk:=b/lb;
  while(rk!=0) {
    qk := normal(quo(rk1,rk));
    r := normal(rk1 - qk * rk);
    l := lcoeff(r);
    if(r==0) {l:=1;}
    uk1, uk := uk, (uk1 - qk * uk)/l;
    vk1, vk := vk, (vk1 - qk * vk)/l;
    rk1, rk := rk, r/l;
    };
  return(normal([uk1,vk1,rk1]));
  }:;
  1. Exécuter cet algorithme sur des polynômes entiers à coefficients aléatoires. Que se passe-t-il ? Comparer les résultats avec la fonction xcas gcdex.

    solution ⇲ ⇱ solution

    On remarque que les coefficients rationnels explosent. De son côté xcas renvoie un pgcd dans \(\Z[X]\), mais les résultats sont bien associés

    a:=randPoly(x,5):; b:=randPoly(x,5):;
    A := euclideetendu(a,b);
    B := gcdex(a,b);
    normal(A*B[2])==B;
    
  2. Modifier l’algorithme en ajoutant un troisième argument \(t\) qui fasse retourner le triplet \((u_k,v_k,r_k)\) au dernier rang \(k\) tel que \(\deg(v_k)\leq t\) (avec un déroulement normal si \(t>=deg(a)\)).

    solution ⇲ ⇱ solution
    euclideetendu(a,b,t):={
      local la,lb,uk1,uk,vk1,vk,rk1,rk,qk,r,l;
      la:=lcoeff(a); lb:=lcoeff(b);
      uk1:=1/la; vk1:=0; rk1:=a/la;
      uk:=0; vk:=1/lb; rk:=b/lb;
      while(rk!=0 and degree(vk)<=t) {
        qk := normal(quo(rk1,rk));
        r := normal(rk1 - qk * rk);
        l := lcoeff(r);
        if(r==0) {l:=1;}
        uk1, uk := uk, (uk1 - qk * uk)/l;
        vk1, vk := vk, (vk1 - qk * vk)/l;
        rk1, rk := rk, r/l;
        //print( normal([uk,vk,rk]), normal(rk/vk) );
        };
      return(normal([uk1,vk1,rk1]));
      }:;
    

10.2. Approximants de Padé

Soit \(b(x)=\sum_{k\geq 0} b_k x^k\) une série entière. L’approximant de Padé d’ordre \((m,n)\) de \(b\) est la fraction rationnelle \(r/v\) vérifiant

\[\frac{r(x)}{v(x)} \equiv b(x)\mod x^{n+m+1}\]

avec \(r,v\) de degrés \(m\) et \(n\).

  1. Calculer le développement en série entière \(b(x)\) de \(\tan(x)\) au voisinage de \(0\) à l’ordre 9, et le convertir en polynôme (de degré 9).

    solution ⇲ ⇱ solution
    b := series(tan(x),x,0,10);
    b := convert(b,polynom);
    
  2. Représenter graphiquement \(b(x)\) et \(\tan(x)\) sur \(]-3/2,2[\).

    solution ⇲ ⇱ solution
    plot([b,tan(x)],x=-3/2..2);
    
  3. Écrire l’algorithme d’Euclide étendu entre \(x^{10}\) et \(b(x)\), et récupérer tous les couples \(v_k,r_k\) issus de l’algorithme.

    solution ⇲ ⇱ solution
    v := euclideetendu(x^10,b,1):; normal(v[2]/v[1]);
    v := euclideetendu(x^10,b,2):; normal(v[2]/v[1]);
    v := euclideetendu(x^10,b,3):; normal(v[2]/v[1]);
    v := euclideetendu(x^10,b,4):; normal(v[2]/v[1]);
    v := euclideetendu(x^10,b,5):; normal(v[2]/v[1]);
    v := euclideetendu(x^10,b,6):; normal(v[2]/v[1]);
    v := euclideetendu(x^10,b,7):; normal(v[2]/v[1]);
    v := euclideetendu(x^10,b,8):; normal(v[2]/v[1]);
    
  4. Pour chaque fraction \(r_k/v_k\), tracer la courbe représentative. Que dire de la qualité d’approximation de \(\tan(x)\), comparé à la formule de Taylor ?

  5. Écrire une fonction approx_pade(b,n,m) qui calcule le \((n,m)\) approximant de Padé de la série \(b\). Comparer avec la fonction correspondante xcas.

    solution ⇲ ⇱ solution
    pade(tan(x),x,9,3);
    pade(tan(x),x,9,5);
    pade(tan(x),x,9,6);
    

10.3. Algorithme de Berlekamp-Massey

Soit \((b_k)_{k\in\N}\) une suite récurrente linéaire d’ordre \(n\), c’est-à-dire qu’il existe un polynôme \(c(x)=x^n-\sum_{i=0}^{n-1}c_ix^i\) tel que

\[\forall k\geq 0, b_{k+n} = \sum_i{c_ib_{k+i}}\]
  1. Écrire une fonction linrec(b,c,k) qui à partir des \(n\) premiers coefficients de la suite et des coefficients \(c_0,\dots c_{n-1}\) du polynôme annulateur calcule la liste des \(k\) premiers termes.

    solution ⇲ ⇱ solution
    linrec(b,c,k):= {
      local n,l,j;
      l := length(c);
      for(n:=length(b);n<k;n++) {
        b := append(b,sum(c[j]*b[n-l+j],j,0,l-1));
        }
      return b;
    }:;
    
  2. Les suites récurrentes à coefficients dans des corps finis sont périodiques, pourquoi ? Trouver la période des suites récurrentes sur \(\F_2\) données par les valeurs initiales \(1,1,\dots 1\) et les polynômes

    \[\begin{split}R_1(x) &= x^5+x^4+x \\ R_2(x) &= x^5+x^3+1\end{split}\]
    solution ⇲ ⇱ solution
    linrec([seq(1%2,5)],[0,1,0,0,1],40)%0
    
    linrec([seq(1%2,5)],[1,0,0,1,0],40)%0
    
  3. On considère la suite de valeurs initiales \(1,2,3,4,5\) et de polynôme générateur \(x^5-x^4+x^3-2x^2+2x-1\). Former la série \(b(x)=\sum_k b_kx^x\) tronquée à l’ordre \(10\).

    solution ⇲ ⇱ solution
    b := linrec([1,2,3,4,5],[1,-2,2,-1,1],10)
    P := sum(b[k]*x^k,k,0,10)
    
  4. À l’aide de la fonction pade, retrouver le polynôme générateur à partir des premiers termes de la suite.

10.4. Algorithme de Wiedemann

Cet algorithme de résolution des systèmes linéaires \(Ax=b\) est particulièrement intéressant dans le cas de matrices sur les corps finis, de grandes dimension et «creuses», c’est-à-dire avec peu de coefficients non-nuls.

C’est le cas par exemple pour l’algorithme page-rank de google, ou pour les algorithmes de factorisation par crible (matrices de dimension plusieurs millions, mais avec moins d’une centaine de coefficients non-nuls par ligne).

Dans ce genre de cas, on ne stocke pas toute la matrice mais seulement l’emplacement de ses coefficients non-nuls. Inverser \(A\) par une technique de pivot de Gauss est hors de question, puisque le pivot a tendance à remplir la matrice.

La technique de Wiedemann consiste à calculer le polynôme minimal de l’endomorphisme \(A\) restreint au sous-espace de Krylov engendré par les itérés de \(b\) par \(A\). Ce polynôme permet alors d’exprimer \(A^{-1}b\) comme un polynôme en les \(A^kb\).

  1. Construire une matrice \(A\) aléatoire sur \(\F_2\).
  2. Pour deux vecteurs \(u,v\) également aléatoires, on construit la suite \(u^TA^kv\). Montrer que c’est une suite récurrente, et que le polynôme minimal de \(A\) en est un polynôme générateur.
  3. Retrouver le polynôme minimal de \(A\) par la méthode de Berlekamp et Massey.

En réalité, on ne trouve pas le polynôme minimal de \(A\) mais un annulateur de la trace (relativement à la forme linéaire \(u^T\)) du minimal de \(A\) sur le sous-espace engendré par les itérés de \(v\) (appelé sous-espace de Krylov).

Une approche probabiliste consiste à prendre le ppcm des annulateurs trouvés via divers couples \((u,v)\) jusqu’à vérifier que l’on annule \(A\). Pour montrer que c’est efficace, on peut montrer des résultats de densité sur les vecteurs \(u\) et \(v\) qui fournissent le résultat.

L’algorithme de Wiedemann ne s’intéresse en réalité pas au polynôme minimal de \(A\), mais bien au minimal sur l’espace de Krylov des \(A^ku\), le but étant d’inverser \(A\)