Algorithmique et complexité

Algorithmique et complexité


Ces pages sont destinées à donner quelques principes simples permettant d'évaluer un programme.

I Notion de coût d'un programme

II Modèle

III En pratique

IV Simulation

I Notion de coût d'un programme

Algorithmique et complexité → I Notion de coût d'un programme

L'exécution d'un programme a toujours un coût. Il existe deux paramètres essentiels pour mesurer ce coût :
  • Le temps d'exécution : la complexité en temps.
  • L'espace mémoire requis : la complexité en espace.

Lorsqu'on fait un programme, il faut donc
  • évaluer les ressources nécessaires : place mémoire et temps d'exécution.
  • évaluer le nombre d'opérations élémentaires pour avoir une idée du coût en temps. Ce qui compte comme opérations dépend du type de problème [cela peut être des opérations du type comparaison, des opérations d'accès au disque ou des opérations arithmétiques]. Elles n'ont pas forcément le même poids. Certaines peuvent être négligeables devant d'autres mais si on les exécute très souvent, il faut quand même en tenir compte.
Il faut ensuite trouver un compromis entre espace et temps.
Algorithmique et complexité → I Notion de coût d'un programme

II Modèle


Pour pouvoir évaluer ces coûts de manière théorique, on définit un modèle abstrait d'ordinateur et on évalue les coûts de ce modèle. Par exemple, dans le cas d'une RAM (Random Acces Machine), on se donne une suite infinie de cases dans lesquelles on peut stocker un entier arbitrairement grand et un programme, c'est-à-dire une suite finie d'instructions permises :
  • arithmétique : αβγ, où est une des opérations addition, soustraction, multiplication, division d'entiers : ce type d'instruction calcule la valeur et la stocke dans alpha ;
  • branchement : Si βγ alors i. Ici, i est l'indice d'une instruction, et une opération de comparaison.
  • arrêt.

En pratique, il n'est pas vrai que la mémoire est illimitée. Les nombres stockés en mémoire sont limités. Et les opérations élémentaires n'ont pas toutes le même coût. On ne tient pas non plus compte des opérations qui, relativement aux autres, consomment peu de temps, telles que les tests, les affectations et les incrémentations.
Bien que très approximatif et ne tenant pas compte de la place mémoire, ce décompte du nombre d'opérations permet de comparer plusieurs algorithmes et correspond en général assez bien aux mesures que l'on peut faire dans une implémentation spécifique de l'algorithme.

III En pratique

Algorithmique et complexité → III En pratique

La plupart des algorithmes que nous verrons dans la suite sont de type arithmétique et les données sont des entiers, des listes d'entiers.

III-1 Taille

III-2 Coût

III-3 Complexité

III-4 Notations de Landau

III-5 Coûts d'opérations simples

III-6 Diviser pour régner

III-7 Pratiquement, que faire ?

III-8 Exercices d'application

Algorithmique et complexité → III En pratique

III-1 Taille

On mesure la taille des données de type entier comme leur nombre de chiffres en base 2 :
T(n)={lg(n)=[log 2(n)]+1 si n est non nul 1 si n est nul
Si les entiers qu'on considère sont de taille petite [par exemple si tous les entiers qu'on considère sont inférieurs à 10000], on pourra prendre T=1.

Exercice

Nombre de chiffres en base \( b \)
Nombre de chiffres en base \( b \)

III-2 Coût

On évalue le coût C(x) pour l'entrée x, le coût le pire 𝒞(n) pour n donné qui est le coût maximal de l'algorithme pour des entrées x de taille T(x) inférieure à n :
𝒞(n)=max T(x)=nC(x)
D'autres coûts peuvent être introduits comme le coût espéré
T(x)=nC(x)/ T(x)=n1.

Plus généralement, on peut se donner une distribution de probabilité Pr sur {x,T(x)=N} et évaluer
T(x)=nPr(t=x)C(x).

III-3 Complexité

On emploie souvent le mot complexité à la place de coût. La complexité évalue la difficulté intrinsèque des problèmes : par exemple
Tout algorithme capable de traiter toutes les instances de taille N a un coût minimal de T(N) dans le cas le pire.
L'algorithmique fournit des résultats positifs du type : L'algorithme Truc traite une instance de taille N en temps t(N).

III-4 Notations de Landau

Algorithmique et complexitéIII En pratique → III-4 Notations de Landau
Dans ce qui suit, f et g sont des fonctions d'une variable x qui est soit un entier positif, soit un réel, g est une fonction positive pour x assez grand,
  • f=O(g) signifie que f(x)cg(x) pour une constante c et pour x assez grand.
  • f=Ω(g) signifie que f(x)cg(x) pour une constante c et pour x assez grand.
  • f=Θ(g) signifie que cg(x)f(x)dg(x) pour des constantes c et d et pour x assez grand.
  • f=o(g) signifie que f(x)g(x) tend vers 0 lorsque x.
  • fg signifie que f(x)g(x) tend vers 1 lorsque x.

Exercice


Comparer des ordres de grandeur
Classer des ordres de grandeur
Un algorithme est dit polynomial si son coût est au plus polynomial en la taille des entrées. D'autres termes sont utilisés : sous-linéaire, linéaire, quadratique, exponentielle ...

Exercice

Vocabulaire

Attention de bien définir quelle taille est adaptée au problème.
Algorithmique et complexitéIII En pratique → III-4 Notations de Landau

III-5 Coûts d'opérations simples

Algorithmique et complexitéIII En pratique → III-5 Coûts d'opérations simples
Soient a et b deux entiers, inférieurs ou égaux à n. Le nombre de bits dans la représentation binaire de n est
lg(n)=([logn/log2]+1).
Si les entiers sont représentés en base B, le nombre de chiffres est
lg B(n)=[logn/logB]+1.
Tous deux sont en Θ(logn).
Une opération sur des entiers de taille "petite" [par exemple, ayant un chiffre en base B, on parle d'entiers simple précision] est appelée opération élémentaire.
La taille d'un entier est donc mesurée en général par lg(n).

III-5-1 Opérations élémentaires

III-5-2 Coût de l'algorithme d'Euclide

III-5-3 Calcul modulaire modulo n

Algorithmique et complexitéIII En pratique → III-5 Coûts d'opérations simples

III-5-1 Opérations élémentaires

Le nombre d'opérations élémentaires pour des entiers grands (multi-précision) pour les quatre opérations de base nécessaires avec des algorithmes classiques (ceux que vous utilisez pour faire une opération à la main) est résumé dans le tableau suivant :
Opération   Complexité en bits  pour a et b inférieurs à n
addition a+b    O(lg(a)+lg(b))   O(lg(n))
soustraction ab    O(lg(a)+lg(b))   O(lg(n))
multiplication ab    O(lg(a)lg(b))   O(lg(n) 2)
division a=bq+r    O(lg(q)lg(b))   O(lg(n) 2)

III-5-2 Coût de l'algorithme d'Euclide

Algorithmique et complexitéIII En pratiqueIII-5 Coûts d'opérations simples → III-5-2 Coût de l'algorithme d'Euclide
Algorithme   Complexité en bits
Algorithme d'Euclide    O((lg(n)) 2)
Algorithme étendu    O((lg(n)) 2)
Algorithmique et complexitéIII En pratiqueIII-5 Coûts d'opérations simples → III-5-2 Coût de l'algorithme d'Euclide

III-5-3 Calcul modulaire modulo n

Opération   Complexité en bits
addition modulaire a+bmodn    O(lg(n))
soustraction modulaire abmodn    O(lg(n))
multiplication modulaire abmodn    O((lg(n)) 2)
inversion modulaire a 1modn    O((lg(n)) 2)
exponentiation modulaire    O((lg(n)) 3)

III-6 Diviser pour régner

Algorithmique et complexitéIII En pratique → III-6 Diviser pour régner
On a un problème avec une solution "simple" algosimple(x) pour des entrées x de taille petite. Pour x de taille grande, on le décompose en plus petites entrées x 1, ..., x r, de taille plus petite. Par exemple, on décompose le problème en deux avec des tailles moitié. On fait alors tourner le programme algo(x) sur ces entrées. Éventuellement, pour pouvoir décomposer le problème et le recomposer, on a d'autres petites choses à faire dont le coût est en f(x).

Diviser pour régner



Input: x
Output: algo(x)
si x est petit ou simple alors
       retourner alogsimple(x)

Décomposer x en sous-entrées x 1, ..., x t
pour i=1 à t faire
       y ialgo(x i)

recombiner les y i en une solution y pour x
retourner y

Si le coût du programme est C(x), on a donc
C(x)C(x 1)+...+C(x r)+f(x)
pour x>T 1 ; C(x) pour x<T 1 est le coût de l'algorithme simple. Par exemple, si l'on a décomposé le problème en deux problèmes de taille moitié, pour x>T 1, C(x)2C(x/2)+f(x). Il reste à évaluer à partir de cette inégalité de récurrence quel est le coût. Pour cela on s'inspire du lemme suivant.

Lemme

Soit C: + + une fonction vérifiant C(x)=0 pour x<1 et C(x)aC(xb)+cx k pour certains a>0, b>1 et c réels et pour x +. Une borne supérieure pour C(x) lorsque x est
{O(x log ba) si a>b k O(x klogx) si a=b k O(x k) si a<b k.

Démonstration
On écrit x=b nx 0 avec x 0 inférieur à une constante T 0, d'où nlog b(x)+N 0.
Par récurrence,
C(x) a(aC(xb 2)+A(xb) k)+Ax k a nC(xb n)+A i=0 n1a i(xb i) k a nC 0+Ax k(a/b k) n1a/b k1
La dernière inégalité n'est valable que si a est différent de b k. On a alors a n=x log b(a)×D(x) avec D(x) fonction bornée et
b kn=x kc 1.
Donc C(x) est la forme C 2C 3x log b(a)x k avec C 2 et C 3 bornés.
  1. Si a<b k, c'est un O(x k).
  2. Si a>b k, c'est un O(x log b(a)).
  3. Si a=b k,
    C(x) a nC 0+Anx k O(x k)+O(x klog b(x))=O(x klog b(x)).


Il existe des versions avec des relations du type
C(x)aC(xb)+f(x)
où le comportement asymptotique de f est connu.
Dans les cas réels, la fonction C n'est pas définie sur +, on ne la connait souvent bien que sur une classe d'entiers (par exemple dans le cas de dichotomie, sur les entiers de la forme 2 k). On fait alors des hypothèses raisonnables sur la fonction de coût pour pouvoir appliquer ce lemme ou une variante (croissance, C(x)+C(y)C(x+y) ...)

Exercice

Application
Algorithmique et complexitéIII En pratique → III-6 Diviser pour régner

III-7 Pratiquement, que faire ?

Algorithmique et complexitéIII En pratique → III-7 Pratiquement, que faire ?
  • Choisir la fonction taille pour les entrées.
  • Compter le nombre de boucles.
  • Évaluer le coût des opérations à l'intérieur : est-ce une opération élémentaire, donc à coût en O(1) ?
  • Dans le cas d'un branchement, évaluer le coût de la branche la plus coûteuse.

Voici deux exemples :

Racine carrée entière d'un entier n



Input: n un entier positif
Output: la racine carrée par défaut d'un entier n
d1 ; racine0 ;
tant que racine×racine<=n faire
       racineracine+1;

retourner racine
Il y a ici au plus n passages dans la boucle et à chaque fois une addition élémentaire est faite. La taille T d'un entier n étant Θ(logn), le coût de l'algorithme est en exp(O(T)).

Recherche du plus petit élément d'une liste en O(n)



Input: une liste x de longueur n
Output: la position du plus petit élément de la liste x
k1
pour i=1 à n faire
      si x[i]<x[k] alors
             ki


retourner k
On compte le nombre de passages dans la boucle, la comparaison étant considérée comme une opération élémentaire. Il y en a n1=O(T) si la liste est de taille inférieure à T. Le coût est donc au plus linéaire en T.
Algorithmique et complexitéIII En pratique → III-7 Pratiquement, que faire ?

III-8 Exercices d'application

Algorithmique et complexitéIII En pratique → III-8 Exercices d'application

Exercice

Dans cet exercice , vous sont présentés des algorithmes. Vous devez donner leur ordre de complexité. Prenez le temps de les comprendre en même temps. Faites attention à ce qu'est la taille dans chacun des problèmes donnés.

Algorithmique et complexitéIII En pratique → III-8 Exercices d'application

IV Simulation

Algorithmique et complexité → IV Simulation
Algorithmique et complexité → IV Simulation

IV-1 Addition dans Pari/GP

Algorithmique et complexitéIV Simulation → IV-1 Addition dans Pari/GP

On fait 5000 additions de nombres dont la taille (longueur en base 2) est 3000+5000ipouri=1,30. Le calcul est fait avec le logiciel GP/Pari.
Des droites de pentes diverses ont été tracées en vert ainsi que des paraboles en bleu pour donner des points de repère.
Algorithmique et complexitéIV Simulation → IV-1 Addition dans Pari/GP

IV-2 Addition dans Octave

Algorithmique et complexitéIV Simulation → IV-2 Addition dans Octave
elapsed_time = toc ;
On fait 10000 additions de nombres dont la taille (longueur en base 2) est 30000+50000ipouri=1,30. Le calcul est fait avec le logiciel Octave
Des droites de pentes diverses ont été tracées en vert ainsi que des paraboles en bleu pour donner des points de repère.
Algorithmique et complexitéIV Simulation → IV-2 Addition dans Octave

IV-3 Multiplication dans Pari/GP

Algorithmique et complexitéIV Simulation → IV-3 Multiplication dans Pari/GP
On fait 5000 multiplications de nombres dont la taille (logarithme en base 2) est 0+1000ipouri=1,30. Le calcul est fait avec le logiciel GP/Pari.

Les graphes tracés sont les courbes d'équation
  • y=x log(3)log(2) en vert,
  • y=x en bleu,
  • y=x 1.25 en noir,
  • y=x 2 en violet.
Les échelles ne sont pas précisées intentionnellement car elles n'ont pas de signification ici.
Algorithmique et complexitéIV Simulation → IV-3 Multiplication dans Pari/GP

IV-4 Multiplication dans Octave

Algorithmique et complexitéIV Simulation → IV-4 Multiplication dans Octave

On fait 3000 multiplications de nombres dont la taille (longueur en base 2) est 10000+5000ipouri=1,30. Le calcul est fait avec le logiciel Octave

Algorithmique et complexitéIV Simulation → IV-4 Multiplication dans Octave

document donnant quelques notions d'algorithmique en vue d'une utilisation dans un cours d'algèbre effective.
: complexity, CFAI,interactive math, server side interactivity

The most recent version

Cette page n'est pas dans son apparence habituelle parce que WIMS n'a pas pu reconnaître votre navigateur web.
Afin de tester le navigateur que vous utilisez, veuillez taper le mot wims ici : puis appuyez sur ``Entrer''.

Veuillez noter que les pages WIMS sont générées interactivement; elles ne sont pas des fichiers HTML ordinaires. Elles doivent être utilisées interactivement EN LIGNE. Il est inutile pour vous de les ramasser par un programme robot.