1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 from HMM import *
21
22 import string
23 from blocTexte import *
24 import logging
25
26 from MediteAppli import transDiacritic
27
28
29
31 """Classe effectuant la comparaison des textes en utilisant la methode définie par S. Feng et R. Manmatha
32 """
33 - def __init__(self, txt1, txt2, ignorerSeparateurs=False, ignorerCase=True, ignorerDiacritiques=False, p2=2, calculDep=True , lenMinBlocDep=4, debugLevel = 4):
34 """Constructeur de l'objet
35
36 @param txt1: la premiere version du texte a comparer
37 @type txt1: String
38 @param txt1: la premiere version du texte a comparer
39 @type txt1: String
40 @param ignorerSeparateurs: Optionnel,Définit si l'on souhaite ou non ignorer les separateurs (ponctuations etc..), Faux par defaut
41 @type ignorerSeparateurs: Bool
42 @param ignorerCase: ignore la casse
43 @type ignorerCase: bool
44 @param ignorerDiacritiques: sensibilité aux accents
45 @type ignorerDiacritiques: bool
46 @param p2: paramètre ratio des remplacements pour insertions/suppressions
47 @type p2: integer
48 @param calculDep: Optionnel, defininit si l'on souhaite ou non calculer les deplacements
49 @type calculDep: Bool
50 @param lenMinBlocDep: longueue minimale bloc déplacé
51 @type lenMinBlocDep: integer
52 @param debugLevel: Optionnel,definit le niveau de log, les valeurs suivantes sont utilisées :
53 logging.INFO = tres peu verbeux (affichage du debut et fin de l'algo seulement)
54 logging.DEBUG = peu verbeux
55 4 verbeux (affichage de certaines variables, affichage des textes, affichage de la progression générale du hmm)
56 3 tres verbeux (affichage dans les boucles / methodes)
57 2 tres tres verbeux (affichage des tableaux etc...), tres peu lisible
58 1 maxi debug (affichage de tous les contenus des appels du fichier HMM.py) /!\ les dictionaires de 150 termes c'est pas joli a voir, ne pas utiliser !!
59 @type debugLevel: Integer
60 """
61 self.texte1 = txt1
62 self.texte2 = txt2
63 self.ignorerSeparateurs = ignorerSeparateurs
64 self.ignorerCase = ignorerCase
65 self.ignorerDiacritiques = ignorerDiacritiques
66 self.calculDep = calculDep
67 self.lenMinBlocDep = lenMinBlocDep
68 self.p2 = p2
69
70
71
72
73
74
75
76 logging.basicConfig(level=debugLevel,datefmt='%a, %d %b %Y %H:%M:%S',format='%(asctime)s %(levelname)s %(message)s')
77 logging.info("algoFeng initialisé, separateurs ignorés : %s, loglevel : %s", ignorerSeparateurs,debugLevel)
78 if __debug__ :
79 logging.log(4,"texte1 :\n%s",self.texte1)
80 logging.log(4,"texte2 :\n%s",self.texte2)
81
82 if self.ignorerDiacritiques:
83
84
85
86
87
88
89 self.texte1 = transDiacritic(self.texte1)
90 self.texte2 = transDiacritic(self.texte2)
91
92 if self.ignorerCase:
93
94 self.texte1 = self.texte1.lower()
95 self.texte2 = self.texte2.lower()
96
97
98
99
100
101
103 """
104 Effectue la comparaison des textes, fonction principale
105
106 Renvoie un tuplet ((blocsAlignes1,blocsAlignes2),(blocsSupprimés Texte1,blocs Ajouté Texte 2),
107 (dep1,dep2),(corespondances entre Dep),(remp1,remp2))
108
109 @return: blocs sur lesquels on aligne pour le texte1 et texte2, blocs supprimés, blocs ajoutés, blocs deplacés du texte1, blocs deplacés du texte2
110 @type: ([(posAligneTxt1Debut,posAligneTxt1Fin),...],[(posAligneTxt2Debut,posAligneTxt2Fin),...]),([(posSupprTxt1Debut,posSupprTxt1Fin),...],[(posAjoutTxt2Debut,posAjoutTxt2Fin),...]),([(posDepTxt1Debut,posDepTxt1Fin),...],[(posDepTxt2Debut,posDepTxt2Fin),...]),([(paires de blocs déplacés)]), ([(posRempTxt1Debut,posRempTxt1Fin),...],[(posRempTxt2Debut,posRempTxt2Fin),...]) avec pos des Integers
111 """
112
113 logging.info("debut algoFeng.aligne")
114
115
116 listeMots1 = self.__creerListeMots(self.texte1)
117 listeMots2 = self.__creerListeMots(self.texte2)
118 logging.debug("listeMots crées")
119 logging.log(2,"listeMots1 : %s",listeMots1)
120 logging.log(2,"listeMots2 : %s", listeMots2)
121
122 dicoTexte1 = self.__creerDico(listeMots1)
123 dicoTexte2 = self.__creerDico(listeMots2)
124 logging.debug("dicoTexte crées")
125 logging.log(2,"dicoTexte1 : %s",dicoTexte1)
126 logging.log(2,"dicoTexte2 : %s", dicoTexte2)
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 A,B = self.__creerListes(dicoTexte1,dicoTexte2)
142 logging.debug("listes A et B crées")
143 logging.debug("(nbBlocsListe / nbBlocsTexte) : texte1 -> %d / %d , texte2 -> %d / %d",len(A),len(listeMots1),len(B),len(listeMots2))
144 logging.log(2,"liste A : %s",A)
145 logging.log(2,"liste B : %s",B)
146 if __debug__ :
147 setA = set(x.val for x in A)
148 setB = set(x.val for x in B)
149 assert setA.symmetric_difference(setB) == set([])
150
151
152
153
154
155
156
157 hmmPhase1 = algoHMM(A, B)
158
159 logging.debug("Debut calcul hmm phase1 (mot ancres)")
160
161
162 motAncres = hmmPhase1.calculeAlignement()
163
164 logging.debug("Fin calcul hmm phase1")
165
166 blocsAjoutes1 = []
167 blocsAjoutes2 = []
168 blocsAlignes1 = []
169 blocsAlignes2 = []
170 logging.debug("Debut postprocessing Phase1")
171
172 (blocsAlignes1,blocsAlignes2) = self.__filtrageApareillementsIdentiques(motAncres,listeMots1,listeMots2)
173 logging.log(2,"motAncres : %s",motAncres)
174
175 if __debug__ :
176 logging.log(3,"Liste des mots ancrés (mot texte1 | mot texte2):")
177 for blocs in motAncres :
178
179 assert listeMots1[blocs[0]].val == listeMots2[blocs[1]].val
180 logging.log(3,"(%s | %s)",self.texte1[listeMots1[blocs[0]].debut:listeMots1[blocs[0]].fin], self.texte2[listeMots2[blocs[1]].debut:listeMots2[blocs[1]].fin])
181
182 assert len(blocsAlignes1) == len(blocsAlignes2)
183 for i in xrange(len(blocsAlignes1)):
184
185 assert hash(self.texte1[blocsAlignes1[i][0]:blocsAlignes1[i][1]]) == hash(self.texte2[blocsAlignes2[i][0]:blocsAlignes2[i][1]])
186 logging.debug("Fin postrpoc Phase1")
187 logging.log(2,"blocsAlignes1 : %s",blocsAlignes1)
188 logging.log(2,"blocsAlignes2 : %s",blocsAlignes2)
189
190
191
192
193
194
195
196
197 logging.debug("Debut Phase2")
198 ancreGauche1 = -1
199 ancreGauche2 = -1
200 if __debug__ :
201 lAncre = len(listeMots2)
202 for i in xrange(len(motAncres)):
203 ancreDroit1 = motAncres[i][0]
204 ancreDroit2 = motAncres[i][1]
205
206 (retAlignes1,retAlignes2),(retAjoutes1,retAjoutes2) = self.__lanceHMMPhase2([(ancreGauche1,ancreGauche2),(ancreDroit1,ancreDroit2)],listeMots1,listeMots2)
207
208 blocsAlignes1.extend(retAlignes1)
209 blocsAlignes2.extend(retAlignes2)
210 blocsAjoutes1.extend(retAjoutes1)
211 blocsAjoutes2.extend(retAjoutes2)
212
213
214 ancreGauche1 = ancreDroit1
215 ancreGauche2 = ancreDroit2
216 if __debug__:
217 logging.log(4,"Phase2 : %0.0f %% Done",float((ancreGauche2*lAncre**-1)*100))
218
219
220 logging.log(4,"Phase2 : traitement partie droite finale : longueur liste1 : %s, longueur liste2 : %s", len(listeMots1)-1-ancreGauche1,len(listeMots2)-1-ancreGauche2)
221 if ancreGauche1 < len(listeMots1)-1 and ancreGauche2 < len(listeMots2)-1:
222 (retAlignes1,retAlignes2),(retAjoutes1,retAjoutes2) = self.__lanceHMMPhase2([(ancreGauche1,ancreGauche2),(len(listeMots1),len(listeMots2))],listeMots1,listeMots2)
223
224
225 blocsAlignes1.extend(retAlignes1)
226 blocsAlignes2.extend(retAlignes2)
227 blocsAjoutes1.extend(retAjoutes1)
228 blocsAjoutes2.extend(retAjoutes2)
229
230
231
232
233 blocsAlignes1.sort()
234 blocsAlignes2.sort()
235
236
237
238 logging.debug("Fin phase2 et 3")
239
240
241 if __debug__ :
242
243 bAj1 = blocsAjoutes1[:]
244 bAj1.sort()
245 bAj2 = blocsAjoutes2[:]
246 bAj2.sort()
247 assert blocsAjoutes1 == bAj1
248 assert blocsAjoutes2 == bAj2
249
250
251 dep1=[]
252 dep2=[]
253 coresDep=[]
254 if self.calculDep:
255
256 self.__regrouperBlocs(blocsAjoutes1, self.texte1,True)
257 self.__regrouperBlocs(blocsAjoutes2, self.texte2,True)
258
259
260 logging.debug("Debut du calcul des blocs déplacés")
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285 dicoDep={}
286
287 for posDebut,posFin in blocsAjoutes1 :
288
289 if posFin-posDebut >= self.lenMinBlocDep:
290
291 val = hash(self.texte1[posDebut:posFin])
292 if not dicoDep.has_key(val):
293 dicoDep[val]=(1,[(posDebut,posFin)],0,[])
294 else :
295 nbOcc1,lPos1,nbOcc2,lPos2 = dicoDep[val]
296 lPos1.append((posDebut,posFin))
297 lPos1.sort()
298 dicoDep[val] = (nbOcc1+1,lPos1,nbOcc2,lPos2)
299 for posDebut,posFin in blocsAjoutes2 :
300 if posFin-posDebut >= self.lenMinBlocDep:
301 val = hash(self.texte2[posDebut:posFin])
302 if not dicoDep.has_key(val):
303 dicoDep[val]=(0,[],1,[(posDebut,posFin)])
304 else :
305 nbOcc1,lPos1,nbOcc2,lPos2 = dicoDep[val]
306 lPos2.append((posDebut,posFin))
307 lPos2.sort()
308 dicoDep[val] = (nbOcc1,lPos1,nbOcc2+1,lPos2)
309
310 for val,(nbOcc1,lPos1,nbOcc2,lPos2) in dicoDep.iteritems():
311
312 for i in xrange(min(nbOcc1,nbOcc2)):
313 dep1.append(lPos1[i])
314 dep2.append(lPos2[i])
315 coresDep.append((lPos1[i],lPos2[i]))
316
317 coresDep.sort()
318
319 dep1.sort()
320 dep2.sort()
321
322 for ind in dep1 :
323 blocsAjoutes1.pop(blocsAjoutes1.index(ind))
324 for ind in dep2 :
325 blocsAjoutes2.pop(blocsAjoutes2.index(ind))
326
327 logging.log(2,"Blocs déplacés1 : %s",dep1)
328 logging.log(2,"Blocs déplacés2 : %s",dep2)
329
330 assert len(blocsAlignes1)==len(blocsAlignes2)
331 remp1=[]
332 remp2=[]
333 aSupr1=[]
334 aSupr2=[]
335 logging.debug("Debut du regroupage des liste de blocs")
336
337
338 self.__regrouperBlocs(blocsAjoutes1, self.texte1)
339 self.__regrouperBlocs(blocsAjoutes2, self.texte2)
340 logging.debug("Fin du regroupage des listes de blocs")
341
342
343
344 for i in xrange(len(blocsAlignes1)-1):
345
346 if (blocsAlignes2[i+1][0]-blocsAlignes2[i][1]) != 0:
347 ratio = float(blocsAlignes1[i+1][0]-blocsAlignes1[i][1])/float(blocsAlignes2[i+1][0]-blocsAlignes2[i][1])
348 if ratio>=float(self.p2**-1) and ratio<=self.p2 and self.texte1[blocsAlignes1[i][1]:blocsAlignes1[i+1][0]]!=" ":
349 remp1.append((blocsAlignes1[i][1],blocsAlignes1[i+1][0]))
350 remp2.append((blocsAlignes2[i][1],blocsAlignes2[i+1][0]))
351
352
353
354
355
356 for bloc in remp1:
357 try:
358 blocsAjoutes1.pop(blocsAjoutes1.index(bloc))
359 except:
360
361
362
363 pass
364
365 for bloc in remp2:
366 try:
367 blocsAjoutes2.pop(blocsAjoutes2.index(bloc))
368 except:
369
370 pass
371
372 remp1.sort()
373 remp2.sort()
374
375
376
377 self.__regrouperBlocs(remp1, self.texte1,False)
378 self.__regrouperBlocs(remp2, self.texte2,False)
379
380
381
382 if __debug__ :
383
384
385 res = ""
386 for deb,fin in blocsAlignes1 :
387 res += self.texte1[deb:fin] +" "
388 res+="\n============\n"
389 for deb,fin in blocsAlignes2 :
390 res += self.texte2[deb:fin] + " "
391 logging.log(4,"Texte aligné :\n%s",res)
392
393 logging.info("fin algoFeng.aligne")
394
395
396
397
398
399 return (blocsAlignes1,blocsAlignes2),(blocsAjoutes1,blocsAjoutes2),(dep1,dep2),(coresDep),(remp1,remp2)
400
401
402
403
404
405
406
407
409 """Lance la phase 2 de l'algo.
410
411 Ici on lance la comparaison HMM au niveau des MOTS
412
413 @param listeMots1: la liste de blocs pour le texte1
414 @param listeMots2: la liste de blocs pour le texte2
415 @param bornesAncres: les bornes pour l'alignement, sur lequel on va couper les listeMots
416 @type liste1,liste2,listeMots1,listeMots2 : liste de blocs ou les champs val, posDebut, posFin et index sont renseignés
417 @type bornesAncres: [(borneGaucheListeMots1,borneGaucheListeMots2),(borneDroiteListeMots1,borneDroiteListeMots2)]
418 @return: liste des blocs alignes, liste des blocs ajoutes
419 @type: ([(DebutBlocTxt1,FinBlocTxt1)...],[(DebutBlocTxt2,FinBlocTxt2)...]),([(DebutBlocTxt1,FinBlocTxt1)...],[(DebutBlocTxt2,FinBlocTxt2)...])
420 """
421
422 liste1 = listeMots1[bornesAncres[0][0]+1:bornesAncres[1][0]]
423 liste2 = listeMots2[bornesAncres[0][1]+1:bornesAncres[1][1]]
424
425 logging.log(3,"Fonction __lanceHMMPhase2 invoquée bornes listeMots1 :[%s;%s] bornes listeMots2 :[%s;%s]",bornesAncres[0][0],bornesAncres[1][0],bornesAncres[0][1],bornesAncres[1][1])
426 hmmPhase2 = algoHMM(liste1,liste2)
427
428 motAlignes = hmmPhase2.calculeAlignement()
429
430
431 blocsAjoutes1 = []
432 blocsAjoutes2 = []
433 blocAlignes1 = []
434 blocAlignes2 = []
435 (blocAlignes1,blocAlignes2) = self.__filtrageApareillementsIdentiques(motAlignes,listeMots1,listeMots2)
436
437
438 if __debug__ :
439 logging.log(3,"Mots Alignés phase2 : (texte1 | texte2)")
440
441
442 for blocs in motAlignes :
443 assert listeMots1[blocs[0]].val == listeMots2[blocs[1]].val
444 logging.log(3,"(%s | %s)",self.texte1[listeMots1[blocs[0]].debut:listeMots1[blocs[0]].fin], self.texte2[listeMots2[blocs[1]].debut:listeMots2[blocs[1]].fin])
445
446
447 assert len(blocAlignes1) == len(blocAlignes2)
448 for i in xrange(len(blocAlignes1)):
449
450 assert hash(self.texte1[blocAlignes1[i][0]:blocAlignes1[i][1]]) == hash(self.texte2[blocAlignes2[i][0]:blocAlignes2[i][1]])
451
452
453 logging.log(2,"blocsAlignés1 : %s",blocAlignes1)
454 logging.log(2,"blocsAlignés2 : %s",blocAlignes2)
455
456
457
458
459
460 logging.log(3,"Debut phase 3")
461 (retAlignes1,retAlignes2),(retAjoutes1,retAjoutes2) = self.__alignePhase3(motAlignes, bornesAncres,listeMots1,listeMots2)
462
463
464 blocAlignes1.extend(retAlignes1)
465 blocAlignes2.extend(retAlignes2)
466 blocsAjoutes1.extend(retAjoutes1)
467 blocsAjoutes2.extend(retAjoutes2)
468
469 blocAlignes1.sort()
470 blocAlignes2.sort()
471 blocsAjoutes1.sort()
472 blocsAjoutes2.sort()
473 logging.log(3,"Fin phase3")
474 logging.log(3,"Fin __lanceHMMPhase2")
475
476 return (blocAlignes1,blocAlignes2),(blocsAjoutes1,blocsAjoutes2)
477
478
479 - def __alignePhase3(self,motsAlignes, bornesAncres,listeMots1, listeMots2):
480 """Lance la Phase 3 de l'algo
481
482 Alignement au niveau des caracteres
483 @param motsAlignes: la liste des mots alignés en phase 2
484 @param bornesAncres: les bornes entre lesquelles on travaille
485 @param listeMots1: la liste des blocs du texte 1
486 @param listeMots2: la liste des blocs du texte 2
487 @type motsAlignes: [(posListeMots1,posListeMots2)...]
488 @type bornesAncres: [(borneGaucheListeMots1,borneGaucheListeMots2),(borneDroiteListeMots1,borneDroiteListeMots2)]
489 @type liste1,liste2,listeMots1,listeMots2 : liste de blocs ou les champs val, posDebut, posFin et index sont renseignés
490 @return: liste de blocs alignés, liste des blocs ajoutes
491 @rtype: ([(DebutBlocTxt1,FinBlocTxt1)...],[(DebutBlocTxt2,FinBlocTxt2)...]),([(DebutBlocTxt1,FinBlocTxt1)...],[(DebutBlocTxt2,FinBlocTxt2)...])
492 """
493
494
495
496
497 logging.log(3,"Fonction __alignePhase3 invoquée, bornes liste1 :[%s %s] liste2:[%s %s]",bornesAncres[0][0],bornesAncres[1][0],bornesAncres[0][1],bornesAncres[1][1])
498 borneGauche1 = bornesAncres[0][0]
499 borneGauche2 = bornesAncres[0][1]
500 blocAlignes1 = []
501 blocAlignes2 = []
502 blocAjoutes1 = []
503 blocAjoutes2 = []
504
505 for i in xrange(len(motsAlignes)):
506 borneDroite1 = motsAlignes[i][0]
507 borneDroite2 = motsAlignes[i][1]
508 (retAlignes1,retAlignes2),(retAjoutes1,retAjoutes2) = self.__lanceHMMPhase3(listeMots1[borneGauche1+1:borneDroite1],listeMots2[borneGauche2+1:borneDroite2])
509
510 if __debug__ :
511
512 for pos in retAlignes1+retAjoutes1:
513 for subPos in pos :
514 assert listeMots1[borneGauche1+1].debut <= subPos
515 assert listeMots1[borneDroite1].fin >= subPos
516 for pos in retAlignes2+retAjoutes2:
517 for subPos in pos :
518 assert listeMots2[borneGauche2+1].debut <= subPos
519 assert listeMots2[borneDroite2].fin >= subPos
520
521 blocAlignes1.extend(retAlignes1)
522 blocAlignes2.extend(retAlignes2)
523 blocAjoutes1.extend(retAjoutes1)
524 blocAjoutes2.extend(retAjoutes2)
525 if __debug__ :
526
527 bAl1 = blocAlignes1[:]
528 bAl1.sort()
529 bAl2 = blocAlignes2[:]
530 bAl2.sort()
531 bAj1 = blocAjoutes1[:]
532 bAj1.sort()
533 bAj2 = blocAjoutes2[:]
534 bAj2.sort()
535 assert blocAlignes1 == bAl1
536 assert blocAlignes2 == bAl2
537 assert blocAjoutes1 == bAj1
538 assert blocAjoutes2 == bAj2
539
540 borneGauche1 = borneDroite1
541 borneGauche2 = borneDroite2
542
543
544 if borneGauche1 < len(listeMots1)-1 and borneGauche2 < len(listeMots2)-1:
545 (retAlignes1,retAlignes2),(retAjoutes1,retAjoutes2) = self.__lanceHMMPhase3(listeMots1[borneGauche1+1:bornesAncres[1][0]], listeMots2[borneGauche2+1:bornesAncres[1][1]])
546
547 if __debug__ :
548
549 for pos in retAlignes1+retAjoutes1:
550 for subPos in pos :
551 assert listeMots1[borneGauche1+1].debut <= subPos
552 assert listeMots1[bornesAncres[1][0]-1].fin >= subPos
553 for pos in retAlignes2+retAjoutes2:
554 for subPos in pos :
555 assert listeMots2[borneGauche2+1].debut <= subPos
556 assert listeMots2[bornesAncres[1][1]-1].fin >= subPos
557 blocAlignes1.extend(retAlignes1)
558 blocAlignes2.extend(retAlignes2)
559 blocAjoutes1.extend(retAjoutes1)
560 blocAjoutes2.extend(retAjoutes2)
561 if __debug__ :
562
563 bAl1 = blocAlignes1[:]
564 bAl1.sort()
565 bAl2 = blocAlignes2[:]
566 bAl2.sort()
567 bAj1 = blocAjoutes1[:]
568 bAj1.sort()
569 bAj2 = blocAjoutes2[:]
570 bAj2.sort()
571 assert blocAlignes1 == bAl1
572 assert blocAlignes2 == bAl2
573 assert blocAjoutes1 == bAj1
574 assert blocAjoutes2 == bAj2
575
576 logging.log(3,"Fin __alignePhase3")
577
578 return (blocAlignes1,blocAlignes2),(blocAjoutes1,blocAjoutes2)
579
580
581
583 """Crée les listes de caracteres et effectue la comparaison HMM sur ces 2 listes
584
585 recherche les blocs ajoutes / supprimes
586 @param liste1: les elements du texte1 que l'on souhaite aligner
587 @param liste2: les elements du texte2 que l'on souhaite aligner
588 @type liste1,liste2: liste de blocs ou les champs val, posDebut, posFin et index sont renseignés
589 @return: liste de blocs alignés, liste des blocs ajoutes
590 @rtype: ([(DebutBlocTxt1,FinBlocTxt1)...],[(DebutBlocTxt2,FinBlocTxt2)...]),([(DebutBlocTxt1,FinBlocTxt1)...],[(DebutBlocTxt2,FinBlocTxt2)...])
591 """
592
593
594 logging.log(3,"Fonction __lanceHMMPhase3 invoquée")
595 listeCar1 = []
596 listeCar2 = []
597
598
599 logging.log(3,"Création des listes de caracteres")
600 index = 0
601 for bloc in liste1 :
602 for i in xrange(bloc.fin-bloc.debut) :
603 listeCar1.append(bloc(self.texte1[i+bloc.debut],bloc.debut+i,bloc.debut+i+1,index))
604 index += 1
605
606
607 index = 0
608 for bloc in liste2:
609 for i in xrange(bloc.fin-bloc.debut) :
610 listeCar2.append(bloc(self.texte2[i+bloc.debut],bloc.debut+i,bloc.debut+i+1,index))
611 index += 1
612 logging.log(2,"listeCar1 : %s",listeCar1)
613 logging.log(2,"listeCar2 : %s",listeCar2)
614
615 hmmPhase3 = algoHMM(listeCar1,listeCar2)
616
617 carAlignes = hmmPhase3.calculeAlignement()
618 (blocAlignes1,blocAlignes2) = self.__filtrageApareillementsIdentiques(carAlignes, listeCar1, listeCar2)
619 if __debug__ :
620 logging.log(2,"Resultat HMM (apres postprocessing): %s",carAlignes)
621 logging.log(2,"Caracteres alignés : (texte1 | texte2)")
622 for bloc in carAlignes :
623 assert listeCar1[bloc[0]].val == listeCar2[bloc[1]].val
624 logging.log(2,"(%s | %s)",listeCar1[bloc[0]].val, listeCar2[bloc[1]].val)
625 assert len(blocAlignes1) == len(blocAlignes2)
626 for i in xrange(len(blocAlignes1)):
627
628 assert hash(self.texte1[blocAlignes1[i][0]:blocAlignes1[i][1]]) == hash(self.texte2[blocAlignes2[i][0]:blocAlignes2[i][1]])
629
630 i = 0
631
632
633 logging.log(3,"Debut du calcul des blocs supprimés / ajoutés")
634
635 for bloc1,bloc2 in carAlignes:
636
637 listeCar1.pop(bloc1-i)
638 listeCar2.pop(bloc2-i)
639 i+=1
640 blocAjoutes1 = []
641 blocAjoutes2 =[]
642 for bloc in listeCar1:
643 blocAjoutes1.append((bloc.debut,bloc.fin))
644 for bloc in listeCar2:
645 blocAjoutes2.append((bloc.debut,bloc.fin))
646 logging.log(2,"BlocAjoutes1 : %s",blocAjoutes1)
647 logging.log(2,"BlocAjoutes2 : %s", blocAjoutes2)
648 logging.log(3,"fin __lanceHMMPhase3")
649 return (blocAlignes1,blocAlignes2),(blocAjoutes1,blocAjoutes2)
650
651
653 """effectue la séparation des mots du texte
654
655 @param texte: le texte que l'on souhaite separer
656 @type texte: String
657 @return: liste de bloc(hash,posdebut,posfin+1,posListeMots)
658 """
659 if self.ignorerSeparateurs :
660
661
662
663 separateurs = """!\r,\n:\t;-?"'`()"""
664
665 sepTable = string.maketrans(separateurs," "*len(separateurs))
666 texte = texte.translate(sepTable)
667
668 texteSplit = texte.split(" ")
669 pos = -1
670 posListe = 0
671 listeMots = []
672 for mot in texteSplit:
673 if len(mot) == 0 :
674
675 pos+=1
676 else:
677 pos+=1
678 listeMots.append( bloc(hash(mot), pos, pos+len(mot), posListe) )
679 pos+=len(mot)
680 posListe+=1
681
682 return listeMots
683
685 """Crée pour chaque mot un dictionnaire comportant son nombre d'occurences
686 et ses positions
687
688 @param liste: la liste a traiter
689 @type liste: liste de bloc(hash,posdebut,posfin+1,posListeMots)
690 @return: le dictionnaire des mots présentds dans la liste
691 @type dico de (hash : (nbOccurences,len,[posOccListe,...],[posOccTxt...])
692 """
693
694 dico = {}
695 for mot in liste :
696
697 hashMot=mot.val
698 if not(dico.has_key(hashMot)):
699
700 dico[hashMot] = (1,mot.fin-mot.debut,[mot.index],[mot.debut])
701 else:
702
703 (nbOcc,lenMot,posListe,posTexte) = dico[hashMot]
704 posListe.append(mot.index)
705 posTexte.append(mot.debut)
706
707 dico[hashMot] = (nbOcc+1,lenMot,posListe,posTexte)
708
709
710 return dico
711
712
714 """Cree les listes de la phase 1.(a) et 1.(b) de l'algo
715
716 liste des apax : termes uniques dans chaque texte et communs aux 2 textes
717
718 @param dicoTexte1,dicoTexte2 : les dictionnaires pour les deux textes
719 @type dicoTexte1,dicoTexte2: dico de (hash : (nbOccurences,len,[posOccListe,...],[posOccTxt...])
720 @return les listes A,B des apax dans les textes 1 et 2
721 @type: listes de bloc(val,index)
722 """
723
724
725
726 A = []
727 for key,v in dicoTexte1.iteritems():
728 if v[0]==1 :
729 A.append(bloc(key , index=v[2][0]))
730
731
732 A.sort(cmp=lambda x,y: cmp(x.index,y.index))
733
734
735
736
737
738
739 B=[]
740 aSupprimer=[]
741
742 for mot in A:
743 if not dicoTexte2.has_key(mot.val):
744 aSupprimer.append(mot)
745 elif dicoTexte2[mot.val][0]>1 :
746 aSupprimer.append(mot)
747 else :
748 listeIndex = dicoTexte2[mot.val][2]
749 for index in listeIndex:
750 B.append(bloc(mot.val,index=index))
751 for mot in aSupprimer :
752 A.pop(A.index(mot))
753
754
755 B.sort(cmp=lambda x,y: cmp(x.index,y.index))
756
757
758 return A,B
759
760
761
762
764 """determine l'alignement une fois que le HMM a renvoyé les blocs considérés comme alignés
765
766 /!\ EFFECTUE DES EFFETS DE BORD SUR aligneHMM /!\
767 renvoie la liste des blocs alignés, et le cas échéant la liste des blocs insérés sous forme de liste de (posDeb,posFin)
768
769 @param aligneHMM: le resultat de l'alignement HMM */!\_MODIFIE EN RETOUR PAR CETTE METHODE_/!\*
770 @type aligneHMM: [(posBlocAligné1,posBlocAligné2)...]
771 @param listeMots1,listeMots2: les listes de mots pour les textes
772 @type listeMots1,listeMots2: liste de blocs ou les champs val, posDebut, posFin et index sont renseignés
773 """
774 aSupprimer = []
775 blocsAlignes1 = []
776 blocsAlignes2 = []
777 aligneHMM.sort()
778 for pos1,pos2 in aligneHMM :
779
780 if listeMots1[pos1].val != listeMots2[pos2].val :
781
782 aSupprimer.append((pos1,pos2))
783 for pos in aSupprimer :
784 aligneHMM.pop(aligneHMM.index(pos))
785
786
787
788
789 aSupprimer = []
790 posActuelle=-1
791 for pos1,pos2 in aligneHMM :
792 if pos1 != posActuelle :
793 posActuelle = pos1
794 blocsAlignes1.append((listeMots1[pos1].debut,listeMots1[pos1].fin))
795 blocsAlignes2.append((listeMots2[pos2].debut,listeMots2[pos2].fin))
796 else :
797 aSupprimer.append((pos1,pos2))
798
799 for pos in aSupprimer :
800 aligneHMM.pop(aligneHMM.index(pos))
801 return (blocsAlignes1,blocsAlignes2)
802
803
804
806 """regroupe les blocs adjacents d'une liste de blocs
807
808 /!\ EFFECTUE UN EFFET DE BORD SUR listeBlocs /!\
809
810
811 @param listeBlocs: la liste des blocs
812 @type listeBlocs: [(posDebut,posFin+1)]
813 @param txt: le texte correspondant
814 @type txt: String
815 """
816
817 separateurs = " "
818 if self.ignorerSeparateurs :
819
820
821 separateurs = """!\r,\n:\t;-?"'`()"""
822 i=0
823 while i != len(listeBlocs)-1:
824 if listeBlocs[i][1] == listeBlocs[i+1][0] :
825 listeBlocs[i] = (listeBlocs[i][0],listeBlocs[i+1][1])
826 del listeBlocs[i+1]
827
828
829 elif (not ignorerPonctuation) and txt[listeBlocs[i][1]] in separateurs:
830 listeBlocs[i] = (listeBlocs[i][0],listeBlocs[i][1]+1)
831 else :
832 i += 1
833
834
835
836
837
839 """
840
841 @deprecated: nous n'utilisons pas les methodes definies dans le papier de Feng & Manmatha, qui s'averent tres contraignantes sur les HMM
842 @see: __creerListes
843 """
844
845
846
847 A = []
848 for key,v in dicoTexte1.iteritems():
849 if v[0]==1 :
850 A.append(bloc(key , index=v[2][0]))
851
852
853 A.sort(cmp=lambda x,y: cmp(x.index,y.index))
854
855
856
857
858
859 self.__filtrerListe(A,dicoTexte1,dicoTexte2,listeMots1,listeMots2)
860
861
862
863
864 B=[]
865
866 for mot in A:
867 for index in dicoTexte2[mot.val][2]:
868 B.append(bloc(mot.val,index=index))
869
870
871 B.sort(cmp=lambda x,y: cmp(x.index,y.index))
872
873
874 return A,B
875
876 - def __filtrerListe(self,liste,dicoTexte1,dicoTexte2,listeMots1,listeMots2):
877 """
878 """
879 aSupprimmer = []
880 for element in liste:
881
882 mot = element.val
883 if not dicoTexte2.has_key(mot) :
884 aSupprimmer.append(element)
885 else:
886
887 pos1 = dicoTexte1[mot][2][0]
888 suivant1 = None
889 precedant1 = None
890 if pos1 > 0 :
891 precedant1 = listeMots1[pos1-1].val
892 if pos1 < len(listeMots1)-1:
893 suivant1 = listeMots1[pos1+1].val
894
895 motTrouveDansTexte2 = False
896 for pos2 in dicoTexte2[mot][2]:
897
898 identique = True
899 if pos2 > 0 and precedant1 != None :
900 precedant2 = listeMots2[pos2-1].val
901 if precedant1 != precedant2 :
902 identique = False
903 if pos2 < len(listeMots1)-1 and suivant1 != None:
904 suivant2 = listeMots2[pos2+1].val
905 if suivant1 != suivant2:
906 identique = False
907 if identique :
908 motTrouveDansTexte2 = True
909 if not motTrouveDansTexte2:
910
911 aSupprimmer.append(element)
912 for elem in aSupprimmer :
913 liste.pop(liste.index(elem))
914
916 """determine l'alignement une fois que le HMM a renvoyé les blocs considérés comme alignés
917 /!\ EFFECTUE DES EFFETS DE BORD SUR aligneHMM /!\
918 renvoie la liste des blocs alignés, et le cas échéant la liste des blocs insérés sous forme de liste de (posDeb,posFin)
919 @deprecated: cette fonction est moche (mais vraiment tres moche en fait) :(
920 @see: __filtrageApareillementsIdentiques
921 """
922
923 aligne = {}
924 blocsAlignes1 = []
925 blocsAlignes2 = []
926 blocsAjoutes1 = []
927 blocsAjoutes2 = []
928
929 aSupprimer = []
930
931 for pos in aligneHMM :
932 pos1 = pos[0]
933 pos2 = pos[1]
934
935 hashMot = listeMots1[pos1].val
936 if hashMot == listeMots2[pos2].val :
937
938 if not aligne.has_key(hashMot):
939
940 aligne[hashMot] = (1,[(pos1,pos2)])
941 else :
942
943 (cpt,listePos) = aligne[hashMot]
944 cpt += 1
945 listePos.append((pos1,pos2))
946 aligne[hashMot] = (cpt,listePos)
947 else :
948
949 aSupprimer.append(pos)
950
951
952
953
954
955
956 for mot, (cpt,listePos) in aligne.iteritems():
957 if cpt == 1 :
958
959 blocsAlignes1.append((listeMots1[listePos[0][0]].debut,listeMots1[listePos[0][0]].fin))
960 blocsAlignes2.append((listeMots2[listePos[0][1]].debut,listeMots2[listePos[0][1]].fin))
961
962 blocsAlignes1.sort()
963 blocsAlignes2.sort()
964
965
966 else :
967
968
969
970
971
972
973
974 dicoPos1={}
975 dicoPos2={}
976
977 for pos in listePos :
978 pos1=pos[0]
979 pos2=pos[1]
980 if not dicoPos1.has_key(pos1):
981 dicoPos1[pos1] = (1,[pos2])
982 else :
983
984 nbOcc,listeAlignement = dicoPos1[pos1]
985 nbOcc += 1
986 listeAlignement.append(pos2)
987 dicoPos1[pos1] = (nbOcc,listeAlignement)
988
989 if not dicoPos2.has_key(pos2):
990 dicoPos2[pos2] = (1,[pos1])
991 else :
992
993 nbOcc,listeAlignement = dicoPos2[pos2]
994 nbOcc += 1
995 listeAlignement.append(pos1)
996 dicoPos2[pos2] = (nbOcc,listeAlignement)
997
998
999
1000 for pos1,(nbOcc1,listeLies1) in dicoPos1.iteritems():
1001 if nbOcc1 == 1 and len(listeLies1) == 1:
1002
1003
1004 blocsAlignes1.append((listeMots1[pos1].debut,listeMots1[pos1].fin))
1005 blocsAlignes2.append((listeMots2[listeLies1[0]].debut,listeMots2[listeLies1[0]].fin))
1006 else :
1007
1008 listeLies1.sort()
1009
1010 bons=[]
1011 autres=[]
1012 for pos2 in listeLies1:
1013 if dicoPos2[pos2][0]==1 :
1014 bons.append(pos2)
1015 else :
1016 autres.append(pos2)
1017
1018
1019
1020 if len(bons)>0:
1021
1022
1023
1024
1025 blocsAlignes1.append((listeMots1[pos1].debut,listeMots1[pos1].fin))
1026 blocsAlignes2.append((listeMots2[bons[0]].debut,listeMots2[bons[0]].fin))
1027 bons.pop(0)
1028 for pos2 in bons :
1029 aSupprimer.append((pos1,pos2))
1030
1031
1032
1033 for pos in aSupprimer :
1034
1035
1036 del aligneHMM[aligneHMM.index(pos)]
1037
1038
1039 blocsAlignes1.sort()
1040 blocsAlignes2.sort()
1041 return (blocsAlignes1,blocsAlignes2),(blocsAjoutes1,blocsAjoutes2)
1042