• Aucun résultat trouvé

Quelques perspectives

Dans le document Recherche de similarité dans du code source (Page 128-135)

Des premiers résultats expérimentaux montrent un certain intérêt à l’utilisation de la mé- thode de factorisation présentée afin de modéliser les similarités existantes à l’échelle de la

7.9. Quelques perspectives 128

fonction. L’utilisation de fonctions de chaînes de lexèmes permet de manipuler des projets par simple analyse lexicale suivie d’une analyse syntaxique basique pour délimiter les fonctions. Il reste toutefois possible de prendre en considération certaines informations sémantiques afin d’affiner les correspondances reportées. On pourra par exemple définir des lexèmes spéciaux délimitateurs afin de synchroniser le départ de correspondances rapportées et éviter le com- mencement par une fin d’instruction ou d’expression.

L’utilisation d’un alphabet de t-grams — dont il sera question au chapitre suivant — (pour un seuil de report de correspondances de t lexèmes) est une approche envisageable pour ap- porter une amélioration temporelle à l’exécution du processus de factorisation. Ceci permet de réduire de t − 1 éléments la longueur des chaînes manipulées ce qui est appréciable lorsque nous manipulons de nombreuses chaînes telles que des petites fonctions feuilles. Les structures d’arbre des intervalles et graphe de farmax générées sont alors plus légères.

Enfin, il est important de souligner l’importance de la phase de suppression des chevau- chements lors de la factorisation d’une fonction à partir de correspondances brutes issues de l’exploitation du graphe des farmax. Nous avons choisi une approche privilégiant les plus longues correspondances sur les plus courtes au détriment potentiel du taux de couverture des fonctions et de la minimisation du nombre de nouvelles fonctions externalisées. On no- tera que la factorisation d’une fonction est ainsi dépendante de son contexte : comparer des projets regroupés en une base disparate tel que réalisé en section précédente n’est donc pas nécessairement judicieux ; ceci pouvant entraîner la création de feuilles résiduelles de multi- plicité unitaire minimisant la quantification de la similarité. Il serait intéressant de quantifier réellement cet effet. D’autre part l’usage de nouvelles méthodes d’élimination de chevauche- ment et leur comparaison expérimentale pourrait apporter un certain éclairage. Cela pourrait aboutir sur la possibilité d’utiliser un processus de factorisation sur une base incrémentale de projets.

8

Méta-lexémisation

Sommaire

8.1 Génération d’empreintes . . . 130 8.1.1 Translation d’une chaîne en k-grams . . . 130 8.1.2 Hachage des k-grams . . . 131 Introduction . . . 131 Hachage incrémental de Karp-Rabin . . . 133 8.2 Sélection d’empreintes . . . 134 8.2.1 Quelques définitions . . . 134 8.2.2 Filtrage syntaxique préalable . . . 135 8.2.3 Sélection aléatoire . . . 135 8.2.4 Sélection par position . . . 136 8.2.5 Sélection sur fenêtre . . . 136 Fonction de sélection arbitraire . . . 136 Fonction de sélection objective . . . 137 8.3 Recherche de correspondances sur base d’empreintes . . . 137 8.3.1 Indexation des empreintes . . . 137 8.3.2 Recherche d’un projet requête dans une base de projets . . . 138 Détermination de métrique de similarité . . . 138 Recherche de correspondances exactes . . . 139 Utilisation d’une fonction de sélection non-locale . . . 142 8.4 Méta-lexémisation avec k-grams de taille variable . . . 142 8.4.1 Philosophie . . . 142 8.4.2 Algorithme classique de tuilage glouton de chaîne de lexèmes . . . . 143 Objectif . . . 143 Algorithme . . . 144 À propos de la maximalité de la couverture . . . 145 Complexité de l’algorithme original . . . 145 8.4.3 Pistes d’amélioration du tuilage glouton . . . 146 Utiliser une seule phase d’itérations sur k-grams décroissants . . . . 146

8.1. Génération d’empreintes 130

Accélérer l’extension . . . 146 Éviter des extensions redondantes sur des k-grams consécutifs . . . . 146 8.4.4 Algorithme amélioré de tuilage glouton . . . 146 Calcul des tables de hachage . . . 146 Itérations . . . 147 Complexité . . . 147 8.4.5 Adaptation à la recherche de similitudes sur une unique chaîne . . . 148 8.4.6 Adaptation à la recherche sur une base de projets indexés . . . 148 Réduction d’espace par sélection de méta-lexèmes . . . 148 Indexation paresseuse . . . 148 À propos de la condition de non-chevauchement des correspondances 149 La manipulation de longues chaînes de lexèmes peut être particulièrement contraignante pour les applications de recherches de similitudes sur des projets de taille importante. Une approche présentée dans le chapitre 6 consiste à utiliser des structures d’indexation de suffixes. Elle présente l’avantage de permettre la détection de similitudes avec un seuil minimal de lexèmes paramétrable mais au prix d’une utilisation importante de mémoire de masse, même pour les implantations les plus économes.

Afin de permettre un passage à l’échelle, l’usage d’empreintes afin de représenter des échan- tillons des séquences de lexèmes à indexer en base s’avère intéressant. Nous étudions tout d’abord la génération d’empreintes à partir de k-grams pour ensuite nous interroger sur les méthodes de sélection d’empreintes. Celles-ci permettent de choisir uniquement certaines em- preintes de méta-lexèmes à référencer afin de diviser la taille de la base d’indexation par un facteur fixe. Ces empreintes sont ensuite utilisées pour la recherche de zones de similarité entre projets indexés et un projet requête.

Dans un dernier temps, nous nous intéressons à la recherche de correspondances exactement similaires et non chevauchantes entre séquences de lexèmes : à cet effet, nous utilisons une méthode de méta-lexémisation avec longueur de k-gram variable. Ceci est l’occasion de pré- senter la méthode de tuilage Greedy String Tiling [82] avec quelques améliorations que nous proposons afin d’améliorer la complexité temporelle dans certaines situations. Cette technique est alors adaptée à la recherche de correspondances sur une base de projets indexés.

8.1 Génération d’empreintes

8.1.1 Translation d’une chaîne en k-grams

Définition 8.1. Soit t = t1t2· · · tnune chaîne de lexèmes de Σ. Nous définissons la chaîne de

k-grams dérivée de t comme la chaîne Gk(t) = u = u1u2· · · un−k+1 avec :

u1 = t1 t2 · · · tk u2 = t2 t3 · · · tk+1 · · · ui = ti ti+1 · · · ti+k−1 · · · un−k+1 = tn−k+1 tn−k+2 · · · tn

La représentation d’une chaîne en k-grams permet l’introduction d’un nouvel alphabet de méta-lexèmes de Σk pour représenter la chaîne originale. Les similitudes sont ensuite recher-

chées en utilisant le nouveau méta-alphabet de cardinalité plus importante mais dont la fré- quence d’apparition de chaque méta-lexème est diminuée. Nous notons qu’aucune similitude portant sur des séquences identiques de lexèmes de taille inférieure à k ne peut plus alors être détectée.

Un mot sur la cardinalité de l’alphabet des k-grams La cardinalité de l’alphabet des k-grams est bornée par |Σ|k; cependant parmi tous les k-uplets de lexèmes, seule une faible proportion représentent des successions de lexèmes grammaticalement et sémantiquement ad- missibles. Ainsi, par exemple en langage C, le 2-gram "({" est interdit alors que le 2-gram "){" peut être rencontré. Les k-grams grammaticalement valides peuvent ainsi être énumérés par analyse de la grammaire pour des valeurs faibles de k. Nous présentons en figure 8.1 le nombre de k-grams différents pour un projet Java de volume important (OpenJDK 1.6 avec environ 1 million de lignes de code) ainsi que la répartition de leur fréquence. Ayant consi- déré les lexèmes obtenus après parcours en profondeur de l’arbre de syntaxe concret, nous constatons qu’il existe |Σ| = 154 1-grams, 1670 2-grams, 7480 3-grams et 20666 4-grams1 dont

le nombre n’augmente que peu avec le volume de code analysé. En revanche le nombre de k-grams distincts pour des valeurs plus élevées de k est approximativement linéaire avec le volume de code traité : il s’établit à N − k + 1 − d, d étant le nombre de k-grams dupliqué (avec typiquement d −→ 0 lorsque k −→ N).

8.1.2 Hachage des k-grams Introduction

Étant donné l’espace des k-grams Σk issu de l’alphabet de lexèmes Σ, nous souhaitons

représenter chaque k-gram par un entier. À cet effet, nous introduisons une fonction de hachage réalisant cette correspondance. Si l’alphabet Σ est de cardinalité finie, il est possible d’utiliser la fonction de hachage bijective fpb suivante :

f pb : (g1, g2, · · · , gk) −→ bk−1g1+ bk−2g2+ · · · + b0gk

où b = |Σ| et les lexèmes g1, g2, · · · , gkde Σ sont confondus avec une valeur entière les représen-

tant en utilisant un ordre total arbitraire sur Σ. Il peut cependant être avantageux de limiter l’étendue de l’intervalle des entiers représentatifs en sacrifiant l’injectivité de la fonction de hachage afin de limiter l’espace mémoire occupé par chaque valeur de hachage. Afin de tester si deux valeurs de hachage désignent le même k-gram, il est alors nécessaire d’accompagner chacune de ces valeurs d’un lien vers l’occurrence de k-gram qu’elle désigne afin de pouvoir vérifier si deux valeurs de hachage sont des faux-positifs ou non.

Nous pouvons toutefois noter que seule une certaine portion de l’espace Σk des k-grams

est intersectée par des k-grams en pratique. Cela peut rendre intéressant l’ajout d’un niveau d’indirection pour la représentation des k-grams. Ceux-ci sont indexés dans une base par une valeur de hachage non obligatoirement bijective ou un arbre lexicographique et associés à une valeur entière bijective pour k petit.

1

Les valeurs de cet exemple sont à comparer avec les puissances de |Σ| : |Σ|2 = 23716, |Σ|3 3, 65 · 106 et

8.1. Génération d’empreintes 132 10 100 1000 10000 100000 1e+06 1e+07 100 1000 10000 100000 1e+06 1e+07

Nombre de k-grams distincts

Nombre d’occurrences de k-gram

1-gram 2-gram 3-gram 4-gram 10-gram 15-gram 20-gram 30-gram 40-gram 50-gram 100-gram

Hachage incrémental de Karp-Rabin

Calculer indépendamment les valeurs de hachage des N − k + 1 k-grams d’une séquence de N lexèmes est de complexité temporelle dépendante de k (typiquement Θ(k) pour chaque k-gram). Nous souhaitons par une méthode incrémentale de hachage calculer l’ensemble des valeurs de hachages en temps Θ(N).

Choix de la base En utilisant la fonction de hachage bijective fp|Σ| polynomiale présentée précédemment, nous pouvons calculer chaque valeur de hachage de k-grams en temps O(k) (seules k additions et k − 1 multiplications sont nécessaires). Nous limitons la cardinalité de l’espace de hachage à N (en pratique une puissance de 2) en considérant la fonction non injective fp|Σ| mod N . Dans cette situation, l’utilisation de la base b = |Σ| peut s’avérer peu

judicieuse en particulier si N et b présentent des facteurs communs : la surjectivité de fb est

alors altérée. Les possibilités de collisions pour des k-grams différents sont ainsi augmentées. Ainsi, par exemple, si b et N sont pairs, fb mod N est à valeurs paires. b et N doivent être

premiers entre eux ce qui est assuré par le choix d’un entier b premier. Les bases les plus couramment utilisées sont 33 et 65599 [54].

Incrémentalités

Définition 8.2. (Incrémentalité simple) Une fonction de hachage f sur des k-grams est dite incrémentale si le k-gram d’indice i (i > 1) est calculable à partir de la donnée du k-gram précédent d’indice i − 1 en un temps constant (indépendant de la valeur de k).

La fonction de hachage polynomiale fpb est effectivement incrémentale. Connaissant la

valeur de hachage de ui = titi+1· · · ti+k−2ti+k−1, la valeur de hachage du k-gram ui+1 =

ti+1ti+2· · · ti+k−1ti+k peut être calculée ainsi en temps constant :

f pb(ui+1) = ui−1× b − ti× bk+ ti+k

La séquence des valeurs de hachage de la séquence de k-grams Gk(t) est ainsi calculable en

temps O(n). Il est alors possible de rechercher un facteur de k lexèmes sur une chaîne en temps linéaire indépendant de k en calculant les valeurs de hachage de tous ses k-grams comme l’ont proposé Karp et Rabin [53]. Nous présentons en figure 8.2 un exemple de hachage incrémental d’une chaîne de lexèmes après attribution d’une valeur numérique à chaque lexème.

Définition 8.3. (Incrémentalité forte) Une classe de fonctions de hachage F = {f1, f2, · · · }

sur des 1, 2, · · · -grams est dite fortement incrémentale si pour k = k′+ k′′ (1 ≤ k≤ k′′) il

existe une fonction g permettant le calcul du k-gram uiui+1· · · ui+k−2ui+k−1 à partir des k′-

gram et k′′-gram u

iui+1· · · ui+k′−1ui+k−2et ui+k′ui+k+1· · · ui+k−2ui+k−1avec une complexité

temporelle de o(k) (par exemple Θ(log k)).

Pour un facteur u = vw (|v| = k′, |w| = k′′), il est possible de calculer la valeur de hachage

de u en connaissant celles de v et w avec la classe de fonctions de hachage polynomiales fpb

avec une complexité temporelle meilleure que O(|u|). En effet, nous pouvons constater l’égalité suivante :

f pb(u) = f pb(vw) = f pb(v) ∗ bk ′′

Dans le document Recherche de similarité dans du code source (Page 128-135)