Devoir 4 d informatique Introduction et objectifs Dans une usine de fabrication d imprimantes, différents tests sont mis en place en fin de chaîne de montage pour valider l assemblage des machines Lors de l un de ces tests, un capteur récupère des données et les envoie à un ordinateur qui les analyse et vérifie la conformité du produit Les résultats des tests sont conservés dans une base de données qui est utilisée à des fins statistiques pour améliorer la qualité de la production Nous nous proposons, dans ce sujet, d aborder différentes étapes de ce processus Le problème comporte ainsi quatre grandes parties indépendantes (sauf par le thème traité) - Dans la partie 1, on s intéresse au processus de réception par l ordinateur des données transmises par le capteur - Dans la partie 2, nous parlerons du traitement des données numériques récupérées (à fin de validation de l imprimante assemblée) - La partie 3 nous permettra de parler de l utilisation de la banque de données évoquée plus haut - Afin de limiter la place prise par les données stockées dans la base, on choisit de compresser celles-ci La partie 4 présente une méthode de compression Le sujet comporte des questions de programmation Vous trouverez en fin de sujet une annexe Python détaillant certaines commandes qui pourront être utiles Vous ne devez pas utiliser de fonctions spécifiques qui ne seraient pas rappelées en annexe Au cas où vous jugeriez utile ou pertinent d utiliser une telle fonction, vous devrez le préciser en expliquant sommairement l action des fonctions utilisées 1 Réception des données par l ordinateur 11 Le capteur Le capteur utilisé est analogique et comporte un convertisseur qui traduit les mesures effectuées sous forme numérique Chaque donnée est ainsi convertie en un entier 1 Expliquer comment on peut stocker les entiers relatifs (et donc avec un signe) sur p bits en machine Comment sont codés 94 ou 87 sur 8 bits selon cette convention? 2 On suppose qu un entier codé sur 10 bits représente une valeur de tension comprise entre 5V et 5V Quelle est alors la résolution de la mesure en volt? Dans la suite de la partie, on ne se préoccupe plus des problèmes de codage des entiers 12 Liaison avec l ordinateur Pour simplifier le problème, on suppose que le capteur transmet à l ordinateur les données sous la forme d une suite de caractères, formant donc une chaîne de caractères On suppose que cette chaîne possède la forme suivante : - un en-tête d un caractère qui permet d identifier le type de renseignement transmis (par exemple, U pour une tension, I pour une intensité électrique ou encore P pour une position) ; - trois caractères parmi 0,, 9 indiquant le nombre n de mesures envoyées ; - une suite de n blocs de quatre caractères formés d un des symboles + ou - et de trois caractères parmi 0,, 9 ; un tel bloc correspond à la représentation de l une des mesures numériques ; - un bloc de caractères parmi 0,, 9 appelé checksum et qui doit correspondre à la valeur modulo 10000 de la somme des valeurs absolues des n mesures transmises 1
Exemple : on suppose que l ordinateur a reçu la chaîne suivante "U005+012+004-023-002+0420083" On peut dire qu il s agit de mesures de tension (caractère U ), qu il y a 5 mesures représentées respectivement par les entiers 12, 4, 23, 2 et 42 La somme des valeurs absolues des mesures vaut 83 (modulo 10000) 3 Quel peut être le rôle du dernier bloc de quatre caractères? 4 Ecrire une fonction transforme qui prend en argument une chaîne de caractères dont on suppose qu elle a la forme voulue et qui renvoie une liste de trois éléments : un caractère (type de mesure), une liste d entiers (les mesures) et un entier (le checksum) Par exemple, appelée avec la chaîne caractère ci-dessus, la fonction renverra la liste [ U,[12,4,-23,-2,42],83] 5 Ecrire une fonction valide qui prend en argument une liste comme celle renvoyée par transforme et qui indique si la valeur du checksum est la bonne (la fonction renvoie donc True si le checksum est correct et False sinon) 2 Analyse des mesures 21 Traitement numérique La suite des valeurs de mesure du courant en Ampère fournies par le capteur est supposée contenue dans une liste Les mesures ont été effectuées toutes les 2ms à partir du temps 0 Pour valider le fonctionnement de l imprimante, on doit avoir accès aux deux quantités suivantes : - la valeur moyenne du signal I sur la durée d acquisition, c est à dire I moy = 1 t final tfinal 0 I(t) dt - la valeur de l écart type du signal I sur la durée d acquisition, c est à dire ( 1 I ec = t final tfinal 0 ) 1/2 (I(t) I moy ) 2 dt On ne connaît les valeurs de I(t) que pour t = 0, 2, 4, On peut obtenir une valeur approchée des intégrales ci-dessus en utilisant la méthode des rectangles ou des trapèzes (qui ne nécessitent de connaître la valeur de la fonction qu en un nombre fini de points bien répartis, ce dont nous disposons ici) 6 Rappeler la formule des trapèzes pour le calcul approché de l intégrale d une fonction continue sur un segment [a, b] en utilisant n points équirépartis, c est à dire les points x k = a + k b a n 1 (0 k n 1) 7 Ecrire une fonction moyenne prenant en argument une liste de mesures d intensité (comme décrite plus haut) et renvoyant une valeur approchée de I moy en utilisant la méthode des trapèzes 8 Ecrire de même une fonction ecart type prenant en argument une liste de mesures d intensité et renvoyant une valeur approchée de I ec en utilisant la méthode des trapèzes 22 Validation des mesures Quand on soumet un composant de l imprimante à un signal d entrée e, il doit réagir en fournissant un signal de sortie s vérifiant les relations s(0) = 0 et s (t) = e(t) s(t) 2
9 Ecrire une fonction sortie prenant en argument une fonction e correspondant à un signal d entrée ainsi qu un entier n et renvoyant une liste contenant les valeurs approchées attendues aux temps 0, 2,, 2(n 1) (exprimés en ms) pour la sortie s Pour calculer les valeurs approchées s i des s(2i), on pourra utiliser l approximation s (2i) s(2i+2) s(2i) 2 ce qui permet d exprimer s i+1 à l aide de s i 10 Ecrire une fonction verifier prenant en argument une fonction e, une liste valeur correspondant aux valeurs de sorties renvoyées par le capteur à l ordinateur (une mesure toutes les 2ms) quand le composant est soumis à l entrée associée à e, et un flottant eps supposé > 0 Cette fonction doit renvoyer un booléen indiquant si la liste obtenue et la liste théorique diffèrent, pour chaque coordonnée, de moins de eps en valeur absolue 3 Exploitation de la base de données On suppose que les résultats des tests ont permis d obtenir deux tables dont une représentation simplifiée est donnée ci-dessous : testfin nserie datetest Imoy Iec fichiermes 230-588ZX2547 2012-04-22 14-25-45 045 011 mesure31025csv 230-588ZX2548 2012-04-22 14-26-57 043 012 mesure41026csv production Num nserie dateprod type 20 230-588ZX2547 2012-04-22 15-52-12 JETDESK-1050 21 230-588ZX2548 2012-04-22 15-53-24 JETDESK-3050 Après son assemblage et avant les différents tests de validation, un numéro de série unique est attribué à chaque imprimante A la fin des tests de chaque imprimante, les résultats d analyse ainsi que le fichier contenant l ensemble des mesures réalisées sur l imprimante sont rangés dans la table testfin Lorsqu une imprimante satisfait les critères de validation, elle est enregistrée dans la table production avec son numéro de série, la date et l heure de sortie de production ainsi que son type 11 Rédiger une requête SQL donnant la table des numéros de série imprimantes dont le type est "JETDESK-1050" ayant été produites 12 Rédiger une requête SQL donnant le minimum et le maximum des valeurs de Imoy pour toutes les imprimantes testées 13 Rédiger une requête SQL donnant la moyenne des valeurs de Iec par type d imprimante pour les imprimantes produites 14 Rédiger une requête SQL permettant d obtenir les numéros de série, la valeur de l écart type et le fichier de mesures des imprimantes ayant une valeur de Iec strictement inférieure à la valeur moyenne de la colonne Iec 4 Compression d un fichier texte Présentation Le fichier de résultat des tests est supposé être un fichier texte composé de caractères Il est représenté informatiquement par un fichier binaire, suite de 0 et de 1 Le codage classique des caractères (par exemple le codage ASCII) attribue un nombre fixé de bits à chaque caractère (on parle de codage de 3
longueur fixe) En supposant que l on alloue (pour simplifier) 5 bits à chaque caractère, on peut choisir de représenter A par 00000, B par 11111, C par 10100, D par 11000, E par 00100 et F par 00111, le texte AABCDCCEF sera représenté par 00000 00000 11111 10100 11000 10100 10100 00100 00111 où les espaces ne sont là que pour mieux voir ce qui se passe Réciproquement, la suite de bits 00111 11111 00000 00000 correspond à la chaîne EFAA L objet de la compression est d attribuer à chaque caractère un code de longueur variable, longueur d autant plus petite que le caractère est fréquent On utilisera alors moins de bits pour coder la même chaîne L inconvénient (que nous ne prendrons pas en compte) est que le code ayant servi doit aussi être transmis pour permettre le décodage L attribution des codes ne peut cependant pas se faire n importe comment Supposons que l on code A par 001, B par 00, C par 101 et D par 01 La suite de bits 00101 peut alors s interpréter de deux façons : 001 01 pour AD ou 00 101 pour BC L objet de cette partie est de présenter certains aspects d une méthode de choix efficace de codage Première étape La première étape consiste à créer une structure contenant la liste des caractères présents dans le texte associés à leur fréquence dans ce texte, ordonnée par fréquence (synonyme ici de nombre d apparitions) croissante Par exemple, pour la chaîne AABCDCCEF, on veut obtenir la liste [ [ B,1], [ D,1], [ E,1], [ F,1], [ A,2], [ C,3] ] A cet effet, on considère les fonctions suivantes : def ajouter(car,liste): i=0 while i<len(liste) and liste[i][0]!= car: i=i+1 if i==len(liste): listeappend([car,1]) else: liste[i][1]=liste[i][1]+1 def freq_liste(chaine): liste=[] for i in range(len(chaine)): ajouter(chaine[i],liste) return(liste) 15 Donner le contenu de la variable l suite à l exécution de la commande l=freq_liste("aabbcb") 16 Préciser la nature des arguments de la fonction ajouter et expliquer ce que réalise cette fonction Donner, sans justification, un invariant de boucle permettant de justifier votre affirmation 17 Si on l appelle avec une chaîne de n caractères, donner un ordre de grandeur du nombre d opérations qui seront effectuées par freq liste en fonction de n On justifiera rapidement le résultat avancé On admet dans la suite que la fonction freq liste a été modifiée de façon à renvoyer un résultat ordonné par fréquence croissante comme indiqué plus haut 4
L arbre de Huffman La deuxième étape consiste à faire évoluer la liste qui vient d être créée Pour expliquer cette évolution, on introduit la structure d arbre binaire On la visualise graphiquement comme suit : 8 4 4 3 [ E,1][ B,1][ C,3] [ D,1][ A,2] Les cercles s appellent des noeuds et de chaque noeud part un chemin vers la droite et un autre vers la gauche Les chemins forment les branches de l arbre et ils aboutissent sur des objets qu on appelle les feuilles Contrairement aux arbres de la nature, il faut donc voir ces structures du haut vers le bas Un arbre est ainsi soit une feuille soit un noeud avec un arbre à gauche et un arbre à droite Ici, les feuilles de l arbre sont des listes à deux éléments : un caractère et un entier De plus, les noeuds sont marqués par un entier correspondant à la somme des entiers des feuilles situées en dessous Par exemple, le noeud en haut de l arbre exemple contient l entier 8 car à partir de ce noeud on peut atteindre cinq feuilles dont la somme des entiers vaut 1 + 2 + 1 + 1 + 3 = 8 Enfin, on appelera poids d un arbre l entier de la liste si l arbre est une feuille et l entier associé au noeud d origine sinon Ainsi, dans la première étape, on a obtenu une liste de feuilles (et donc d arbres) ordonnée par poids croissant Attention : la façon dont les arbres autres que les feuilles seront représentés en Python n a aucune importance pour la suite du sujet On propose alors l algorithme suivant, qui prend en argument cette liste ordonnée Tant que la liste a au moins deux éléments, enlever les deux premiers éléments a et b de la liste créer l arbre égal au noeud avec a à gauche et b à droite inserer cet arbre dans la liste Renvoyer l unique élément de la liste Attention : la liste est composée d arbres et il faut la garder triée par ordre croissant des poids L insertion doit conserver cette propriété 18 On applique cet algorithme avec la liste (triée) de feuilles associée à AABBCB Donner les valeurs successives de la liste lors des itérations (on dessinera donc les arbres qui la compose) 19 On suppose que l on dispose d une fonction poids donnant le poids d un arbre (dont la représentation effective en Pyhton ne nous intéresse pas) On considère alors la fonction récursive suivante def inserer(arbre,liste,pos): if pos == len(liste): listeappend(arbre) elif poids(arbre) <= poids(liste[pos]): 5
listeinsert(pos,arbre) else: inserer(arbre,liste,pos+1) Justifier proprement l affirmation suivante : cette fonction, quand on l appelle avec pos égal à 0, permet d insérer un arbre dans une liste d arbres triée par poids croissant, en conservant l ordre de tri On précise que si l est une liste, l appel linsert(i,x) ajoute l élément x à la liste l en position i (en décalant donc les éléments suivants) Le codage effectif Dans l arbre de Huffman, chaque caractère présent dans le texte de départ se trouve sur une feuille et, par construction, la feuille est d autant plus basse dans l arbre que le caractère est peu courant L idée du codage est d associer à un caractère une suite de 0 ou de 1 correspondant au chemin du haut de l arbre vers la feuille associée Dans ce chemin, on code un passage vers la gauche par un 0 et un passage vers la droite par un 1 20 Dans le cas du texte AABCDCCEF, donner le code que l on associera à chaque caractère On supposera que dans la liste triée initiale, à poids égal pour deux feuilles on place d abord celle correspondant à un caractère alphabétiquement plus petit 5 Annexe : aide-mémoire 51 Listes Les listes sont des structures dont les éléments sont numérotés à partir de 0 L élément numéro i de la liste l se note l[i] La taille d une liste l est son nombre d éléments et s obtient par la commande len(l) Les listes sont des structures mutables On peut modifier la valeur de l élément i de la liste l (écrire l[i]=) On peut ajouter un élément x à droite d une liste l (écrire lappend(x)) On peut ajouter un élément x en position i d une liste l en écrivant linsert(i,x) (on suppose que 0 i len(l)) Si initialement l = [a 0,, a n 1 ], après cet appel, la liste est l = [a 0,, a i 1, x, a i,, a n 1 ] On pourra utiliser l opérateur + sur les listes : [0,1]+[1,3]=[0,1,1,3] Si l est une liste alors l[i:j] est la sous liste [l[i],,l[j-1]] 52 Chaînes de caractère Les chaînes de caractères sont des suites ordonnées de caractères encadrées par des " ou des Comme pour les listes, la numérotation commence à 0 L élément numéro i d une chaîne c se note c[i] La taille d une chaîne c est son nombre de caractères et s obtient par la commande len(c) Les chaînes de caractères ne sont PAS des structures mutables Si c est une chaîne de caractères alors c[i:j] est la sous-chaîne c[i]c[j-1] Si c est une chaîne composée de caractères tous entiers, la commande int(c) permet d obtenir le nombre associé 6