Notion de Complexité 1 1 Problématique Les données numériques traitées par les odrinateurs sont de plus en plus nombreuses et volumineuses. Pour traiter efficacement ces données il faut surmonter 3 grandes difficultés : 1. Un problème de place : On considère un litre de gaz à dans les conditions normales de température et de pression (p = 1 bar et T = 25 ◦ C). On souhaite modéliser le mouvement des particules qui constituent ce système gazeux. Pour cela on doit disposer de la position de chaque particule à t=0 (repérées par xi , yi , zi ), de la vitesse de chaque particule à t=0 (notées par vxi , vyi , vzi ) et d’un modèle (par exemple le modèle des gaz parfaits). Chaque donnée numérique est entrée comme un flottant codé sur 64 bits ◮ Quelle est la mémoire nécessaire (exprimée en octets) pour stocker les valeurs numériques associées aux positions et aux vitesses des particules ? 2. Un problème de temps : Lancer le script harmonique complexite.py avec une durée d’observation de 10 s. Ce script réalise la résolution numérique de l’équation d’un oscillateur harmonique par la méthode d’Euler. ◮ Commenter le résultat obtenu. 3. Un problème de précision : ◮ Le script suivant a-t-il une fin ? 2 Estimation de la complexité temporelle d’un algorithme La durée d’execution d’un programme dépend du nombre d’opérations qu’il doit réaliser (et de l’ordinateur sur lequel on travail). Lorsque l’ordinateur effectue un grand nombre d’opérations, la durée des calculs peut rapidement devenir un paramètre qu’il faut prendre en compte dans le choix de l’algorithme. Afin de prévoir comment évolue la durée du calcul en fonction du nombre n que le programme doit traiter on peut réaliser une estimation (plus ou moins détaillée) de sa complexité. Pour estimer la complexité temporelle d’un algorithme, on identifie une opération fondamentale effectuée par l’ordinateur et on estime, en fonction de n, le nombre de fois que cette opération est réalisée. Dépendance en n Temps constant Linéaire Quadratique logarithmique complexité temporelle O(1) O(n) O(n2 ) O(log n) Exemples : 1. Pour chacune de ces fonctions indiquer le résultat si n = 3 2. Estimer la complexité temporelle de chacun de ces algorithmes Notion de Complexité 2 Complexité dans le meilleur et dans le pire des cas Pour deux séries de données de même taille n un algoritme n’effectue pas nécessairement le même nombre d’opérations. ◮ Définir la fonction recherche (vue en cours) qui permet savoir si un élément appartient à une liste. ◮ Quelle est sa compléxité. ◮ Modifier l’algorithme pour que celui-ci s’arrête dès que l’élément de la liste est trouvé. On voit sur cet exemple que, si on a de la chance, l’élément recherché sera trouvé dès le début et l’algorithme ainsi modifié s’arrêtera. Au contraire, si l’élément recherché n’appartient pas à la liste, la boucle for s’exécutera jusqu’au dernier élément de la liste. On peut alors nuancer l’estimation de la complexité temporelle d’un algorithme en parlant de compléxité dans le pire des cas (qui est un majorant de la complexité) et dans le meilleur des cas (qui est un minorant souvent moins intéressant). ◮ Reprendre l’algorithme précédent et déterminer la complexité dans le meilleur et pire des cas. 3 Exercices : Exercice 1 Recherche d’un mot dans une chaı̂ne de caractères 1. Définir une fonction recherche mot qui prend comme arguments un mot et un texte et renvoie la position de la première occurence du mot choisi dans le texte étudié s’il existe et False sinon. 2. Analyser la compléxité de l’algorithme proposé dans le meilleur et le pire des cas. Exercice 2 Recherche dans un tableau trié On cherche à déterminer si un tableau trié contient une certaine valeur. 1. Pour cela on peut utiliser la fonction recherche qui va réaliser une analyse séquentielle du tableau. Rappeler la complexité de la fonction recherche 2. Dans le cas spécifique d’un tableau trié, on peut utiliser aussi utiliser une méthode dichotomique. Définir une fonction recherche dichotomique qui renvoie les mêmes informations que la fonction précédente mais exploite par dichotomie la liste triée. 3. On note n la longueur du tableur et {gk , dk } les bornes gauche et droite de l’intervalle encadrant la valeur cherchée à la ke itération. Montrer que n dk − gk < k 2 4. En déduire la complexité de la recherche dichotomique. Exercice 3 Produit matriciel 1. Créer les matrices : 1 2 A = 2 4 2 1 3 6 0 −1 2 −3 B = −2 4 −6 −2 1 0 2. Définir une fonction matrice0 qui prend pour arguments un nombre de lignes et un nombre de colonnes et renvoie une matrice uniquement constituée de zéros. 3. Etudier la est la complexité de cette fonction ? 4. Définir une fonction prod matrice prend pour argument deux matrices et qui renvoie le produit de ces deux matrices. 5. Vérification de l’algorithme : – afficher le type de A et B, – importer le module numpy – changer le type de A et B en array à l’aide de la fonction array du module numpy, – effectuer le produit matriciel avec la fonction dot du module numpy Rq : Vous pouvez aussi tester l’effet de A×B en fonction du type de A et B (list ou array) 6. Analyser la compléxité de l’algorithme proposé.