1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import logging, heapq, bisect, sys, random
20 import numpy.oldnumeric as Numeric
21 import utile
22
24 """ Classe gérant et résolvant les recouvrements """
25 - def __init__(self,texte,blocs_texte,lg_texte1, min_size=1):
26 self.texte = texte
27 self.blocs_texte = blocs_texte
28 self.lg_texte1 = lg_texte1
29 self.lg_texte2 = len(self.texte)-self.lg_texte1
30 self.min_size = min_size
31 self.tool = utile.Utile()
32
34 """ Renvoie sous forme d'une liste croissante d'intervalles tous les segments
35 couverts dans "blocs_texte"; cette fonction permet ensuite
36 determiner les recouvrements """
37
38 L = []
39 for chaine,liste_pos in self.blocs_texte.iteritems():
40 ln = len(chaine)
41 for occ in liste_pos:
42 L = self.tool.addition_intervalle(L, [occ, occ + ln])
43
44 return L
45
47 """ Cette fonction prends en entree la couverture, c'est-a-dire la
48 liste des intervalles couverts par les chaines de "blocs_texte"
49 Elle renvoie les zones de recouvrement sous forme quadruplets:
50 [occ_debut, occ_fin, chaine_anterieure, chaine_posterieure] """
51 logging.debug("debut recouvrements")
52 L = []
53 while len(couv)>1:
54 if couv[0][-1] > couv[1][0]:
55 L = self.tool.addition_intervalle(L, [couv[1][0], couv[0][-1], couv[0], couv[1]])
56 couv = couv[1:]
57 logging.debug("fin recouvrements")
58 return L
59
61 """ Cette fonction prend en entree la couverture, c'est-a-dire la
62 liste des intervalles couverts par les chaines de "blocs_texte"
63 Elle renvoie les zones de recouvrement sous forme quadruplets:
64 [occ_debut, occ_fin, chaine_anterieure, chaine_posterieure] """
65
66 L = []
67 i = 0
68 while i < len(couv)-1:
69 if couv[i][-1] > couv[i+1][0]:
70 L = self.tool.addition_intervalle(L, [couv[i+1][0], couv[i][-1], couv[i], couv[i+1]])
71 i += 1
72
73 return L
74
76 """ part d'un intervalle qui corresponds a un recouvrement
77 et trouve une cesure judicieuse (par exemple un blanc)
78 On coupera sur cette cesure
79 I: [occ_debut, occ_fin, chaine_anterieure, chaine_posterieure] """
80
81
82
83 if (I[0] == 0 or I[0] == self.lg_texte1 or
84 self.texte[I[0]-1] in [' ', '.', '-', ',', '!', '?', ':', ';']):
85 return I[0]
86 if (I[1] == (self.lg_texte1 - 1) or I[1] == (self.lg_texte1 + self.lg_texte2 - 1) or
87 self.texte[I[1]] in [' ', '.', '-', ',', '!', '?', ':', ';']):
88 return I[1]
89
90
91
92
93
94 L = range(I[0], I[1]+1)
95 for x in L:
96 if self.texte[x] == ' ':
97 return x
98 for x in L:
99 if self.texte[x] in ['.', '-', ',', '!', '?', ':', ';']:
100 return x
101 return L[0]
102
104 """ part d'un intervalle qui corresponds a un recouvrement
105 et trouve une cesure judicieuse (par exemple un blanc)
106 On coupera sur cette cesure
107 I: [occ_debut, occ_fin, chaine_anterieure, chaine_posterieure] """
108
109
110 res = I[0]
111 if (I[0] == 0 or I[0] == self.lg_texte1 or
112 self.texte[I[0]-1] in [' ', '.', '-', ',', '!', '?', ':', ';']):
113 res = I[0]
114 elif (I[1] == (self.lg_texte1 - 1) or I[1] == (self.lg_texte1 + self.lg_texte2 - 1) or
115 self.texte[I[1]] in [' ', '.', '-', ',', '!', '?', ':', ';']):
116 res = I[1]
117
118
119 else:
120
121 taillech1=I[2][1]-I[2][0]
122 taillech2=I[3][1]-I[3][0]
123 if taillech1<=taillech2: L = range(I[0], I[1] + 1)
124 else: L = range(I[1], I[0]-1, -1)
125 res = L[0]
126
127
128
129
130
131 for x in L:
132 if self.texte[x] in [' ', '.', '-', ',', '!', '?', ':', ';']:
133 res = x
134 break
135 logging.debug(self.texte[I[2][0]:I[2][1]]+' / ' +self.texte[I[3][0]:I[3][1]] +
136 ' / ' + self.texte[I[0]:I[1]] + ' / res='+self.texte[res-1:res+2] )
137 return res
138
140 """ part d'un intervalle qui correspond à un recouvrement
141 et trouve une cesure judicieuse (par exemple un blanc)
142 On coupera sur cette cesure
143 I: [occ_debut, occ_fin, chaine_anterieure, chaine_posterieure]
144
145 Attention !! pb dans BBL.extractDeplacements(), ne respecte plus l'assertion
146 d'ordre si on utilise cette fonction"""
147 sep = " .-,!?:;\r\n\t"
148 tailleChAnt=I[2][1]-I[2][0]
149 tailleChPost=I[3][1]-I[3][0]
150 res = I[0]
151 match = False
152
153
154 if tailleChAnt < tailleChPost:
155
156 if (I[0] == 0 or I[0] == self.lg_texte1 or self.texte[I[0]-1] in sep):
157 res = I[0]
158 match = True
159 elif (I[1] == (self.lg_texte1 - 1) or I[1] == (self.lg_texte1 + self.lg_texte2 - 1) or
160 self.texte[I[1]] in sep):
161 res = I[1]
162 match = True
163 else:
164 if (I[1] == (self.lg_texte1 - 1) or I[1] == (self.lg_texte1 + self.lg_texte2 - 1) or
165 self.texte[I[1]] in sep):
166 res = I[1]
167 match = True
168 elif (I[0] == 0 or I[0] == self.lg_texte1 or
169 self.texte[I[0]-1] in sep):
170 res = I[0]
171 match = True
172
173 if not match:
174 if tailleChAnt <= tailleChPost: L = range(I[0], I[1] + 1)
175 else: L = range(I[1], I[0]-1, -1)
176 res = L[0]
177
178
179
180
181
182 if not match:
183 for x in L:
184 if self.texte[x] in sep:
185 res = x
186 if tailleChAnt <= tailleChPost: pass
187 else: res = max(res+1,L[0])
188 break
189
190
191 if res < 0: res = 0
192 elif res > self.lg_texte1 + self.lg_texte2: res = self.lg_texte1 + self.lg_texte2
193 assert 0 <= res <= self.lg_texte1 + self.lg_texte2
194 return res
195
197 """ Une cesure etant donnee, cette fonction rogne les blocs de textes
198 qui recouvrent cette cesure, a savoir les segments anterieur
199 et posterieur qui sont donnes comme argument """
200 chaine_anterieure = self.texte[seg_anterieur[0]: seg_anterieur[1]]
201 chaine_posterieure = self.texte[seg_posterieur[0]: seg_posterieur[1]]
202
203
204
205 Nouv_chaine_anterieure = self.texte[seg_anterieur[0]: cesure]
206 Nouv_chaine_posterieure = self.texte[cesure:seg_posterieur[1]]
207 decalage_ant = seg_anterieur[1] - cesure
208 decalage_post = cesure - seg_posterieur[0]
209 min_size = self.min_size
210
211 if decalage_ant != 0:
212
213 if len(self.blocs_texte[chaine_anterieure]) <= 2:
214 if len(Nouv_chaine_anterieure) >= min_size:
215 self.blocs_texte[Nouv_chaine_anterieure] = self.blocs_texte[chaine_anterieure]
216 del self.blocs_texte[chaine_anterieure]
217 else:
218
219 assert len(self.blocs_texte[chaine_anterieure]) > 2
220 self.blocs_texte[chaine_anterieure].remove(seg_anterieur[0])
221
222
223 if len(Nouv_chaine_anterieure) >= min_size:
224 try:
225 bisect.insort_right(self.blocs_texte[Nouv_chaine_anterieure],seg_anterieur[0])
226 except KeyError:
227 self.blocs_texte[Nouv_chaine_anterieure] = [seg_anterieur[0]]
228 if __debug__:
229 if self.blocs_texte.has_key(chaine_anterieure):
230 assert len(self.blocs_texte[chaine_anterieure]) >= 2
231
232 if decalage_post != 0:
233
234 if len(self.blocs_texte[chaine_posterieure]) <= 2:
235 NL = [occ + decalage_post for occ in self.blocs_texte[chaine_posterieure]]
236 if len(Nouv_chaine_posterieure) >= min_size:
237 self.blocs_texte[Nouv_chaine_posterieure] = NL
238 del self.blocs_texte[chaine_posterieure]
239 else:
240 assert len(self.blocs_texte[chaine_posterieure]) > 2
241 self.blocs_texte[chaine_posterieure].remove(seg_posterieur[0])
242 if len(Nouv_chaine_posterieure) >= min_size:
243 try:
244 bisect.bisect_right(self.blocs_texte[Nouv_chaine_posterieure], cesure)
245 except KeyError:
246 self.blocs_texte[Nouv_chaine_posterieure] = [cesure]
247 if __debug__:
248 if self.blocs_texte.has_key(chaine_posterieure):
249 assert len(self.blocs_texte[chaine_posterieure]) >= 2
250
251
252
253
254
255
257 """ Une cesure etant donnee, cette fonction rogne les blocs de textes
258 qui recouvrent cette cesure, a savoir les segments anterieur
259 et posterieur qui sont donnes comme argument """
260 chaine_anterieure = self.texte[seg_anterieur[0]: seg_anterieur[1]]
261 chaine_posterieure = self.texte[seg_posterieur[0]: seg_posterieur[1]]
262
263
264
265 Nouv_chaine_anterieure = self.texte[seg_anterieur[0]: cesure]
266 Nouv_chaine_posterieure = self.texte[cesure:seg_posterieur[1]]
267 decalage_ant = seg_anterieur[1] - cesure
268 decalage_post = cesure - seg_posterieur[0]
269
270 if decalage_ant != 0:
271
272 if len(self.blocs_texte[chaine_anterieure])==2:
273 self.blocs_texte[Nouv_chaine_anterieure] = self.blocs_texte[chaine_anterieure]
274
275 del self.blocs_texte[chaine_anterieure]
276 else:
277 try:
278 self.blocs_texte[chaine_anterieure].remove(seg_anterieur[0])
279 if not self.blocs_texte.has_key(Nouv_chaine_anterieure):
280 self.blocs_texte[Nouv_chaine_anterieure]=[]
281 self.blocs_texte[Nouv_chaine_anterieure].append(seg_anterieur[0])
282 except Exception:
283
284 pass
285 self.blocs_texte[Nouv_chaine_anterieure] = self.blocs_texte[chaine_anterieure]
286 del self.blocs_texte[chaine_anterieure]
287
288 if decalage_post != 0:
289
290 if len(self.blocs_texte[chaine_posterieure])==2:
291 NL = []
292 for occ in self.blocs_texte[chaine_posterieure]:
293 NL.append(occ + decalage_post)
294 self.blocs_texte[Nouv_chaine_posterieure] = NL
295
296 del self.blocs_texte[chaine_posterieure]
297 else:
298 if not self.blocs_texte.has_key(Nouv_chaine_posterieure):
299 self.blocs_texte[Nouv_chaine_posterieure]=[]
300 self.blocs_texte[Nouv_chaine_posterieure].append(cesure)
301 try:
302 self.blocs_texte[chaine_posterieure].remove(seg_posterieur[0])
303 except Exception:
304
305 pass
306 NL = []
307 for occ in self.blocs_texte[chaine_posterieure]:
308 NL.append(occ + decalage_post)
309 self.blocs_texte[Nouv_chaine_posterieure] = NL
310 del self.blocs_texte[chaine_posterieure]
311
312
313
314
315
316
318 """ Une cesure etant donnee, cette fonction rogne les blocs de textes
319 qui recouvrent cette cesure, a savoir les segments anterieur
320 et posterieur qui sont donnes comme argument """
321 chaine_anterieure = self.texte[seg_anterieur[0]: seg_anterieur[1]]
322 chaine_posterieure = self.texte[seg_posterieur[0]: seg_posterieur[1]]
323
324
325
326 Nouv_chaine_anterieure = self.texte[seg_anterieur[0]: cesure]
327 Nouv_chaine_posterieure = self.texte[cesure:seg_posterieur[1]]
328 decalage_ant = seg_anterieur[1] - cesure
329 decalage_post = cesure - seg_posterieur[0]
330
331 if decalage_ant != 0:
332
333
334 try:
335 self.blocs_texte[Nouv_chaine_anterieure] = self.blocs_texte[chaine_anterieure]
336
337 del self.blocs_texte[chaine_anterieure]
338 except KeyError:
339 pass
340
341
342
343
344
345
346
347
348
349
350
351
352 if decalage_post != 0:
353
354
355 try:
356 NL = []
357 for occ in self.blocs_texte[chaine_posterieure]:
358 NL.append(occ + decalage_post)
359 self.blocs_texte[Nouv_chaine_posterieure] = NL
360
361 del self.blocs_texte[chaine_posterieure]
362 except KeyError:
363 pass
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
385 """ Une cesure etant donnee, cette fonction rogne les blocs de textes
386 qui recouvrent cette cesure, a savoir les segments anterieur
387 et posterieur qui sont donnes comme argument """
388 chaine_anterieure = self.texte[seg_anterieur[0]: seg_anterieur[1]]
389 chaine_posterieure = self.texte[seg_posterieur[0]: seg_posterieur[1]]
390
391
392
393 Nouv_chaine_anterieure = self.texte[seg_anterieur[0]: cesure]
394 Nouv_chaine_posterieure = self.texte[cesure:seg_posterieur[1]]
395 decalage_ant = seg_anterieur[1] - cesure
396 decalage_post = cesure - seg_posterieur[0]
397
398 if decalage_ant != 0:
399 if not self.blocs_texte.has_key(Nouv_chaine_anterieure):
400 self.blocs_texte[Nouv_chaine_anterieure] = []
401 self.blocs_texte[Nouv_chaine_anterieure].append(seg_anterieur[0])
402
403 try:
404 self.blocs_texte[chaine_anterieure].remove(seg_anterieur[0])
405 except ValueError: pass
406 if len(self.blocs_texte[chaine_anterieure]) == 0:
407 del self.blocs_texte[chaine_anterieure]
408
409 if decalage_post != 0:
410 if not self.blocs_texte.has_key(Nouv_chaine_posterieure):
411 self.blocs_texte[Nouv_chaine_posterieure] = []
412 self.blocs_texte[Nouv_chaine_posterieure].append(cesure)
413
414 try:
415 self.blocs_texte[chaine_posterieure].remove(seg_posterieur[0])
416 except ValueError: pass
417 if len(self.blocs_texte[chaine_posterieure]) == 0:
418 del self.blocs_texte[chaine_posterieure]
419
420
422 a = True
423 if a: print 'self.min_size=',self.min_size
424 tot = sum([len(chaine)*len(locc) for chaine,locc in self.blocs_texte.iteritems()])
425 logging.debug("debut eliminer_recouvrements len(chaines dic)=%d",tot)
426
427 Recouvre = self.recouvrements(self.couverture())
428 i=0
429 while Recouvre != []:
430
431
432 for Int in Recouvre:
433 if a: print '----------------------------------------------------------'
434 assert Int[2][1]-Int[2][0] >= self.min_size
435 assert Int[3][1]-Int[3][0] >= self.min_size
436
437
438 if ( self.blocs_texte.has_key(self.texte[Int[2][0]:Int[2][1]]) and
439 self.blocs_texte.has_key(self.texte[Int[3][0]:Int[3][1]])):
440 if self.tool.inclus_(Int[2], Int[3]):
441 ch = self.texte[Int[2][0]:Int[2][1]]
442 if a: print '*',ch,'* inclus dans *', self.texte[Int[3][0]:Int[3][1]],'*'
443 pos = bisect.bisect_right(self.blocs_texte[ch], Int[2][0])
444 if a: print pos, Int[2][0], self.blocs_texte[ch]
445 if Int[2][0] == self.blocs_texte[ch][pos-1]:
446
447 if a: print 'occ ',Int[2][0],' removed'
448 self.blocs_texte[ch].remove(Int[2][0])
449 if len(self.blocs_texte[ch]) == 0:
450 del self.blocs_texte[ch]
451 elif self.tool.inclus_(Int[3], Int[2]):
452 ch = self.texte[Int[3][0]:Int[3][1]]
453 if a: print '*',ch,'* inclus dans *',self.texte[Int[2][0]:Int[2][1]],'*'
454 pos = bisect.bisect_right(self.blocs_texte[ch], Int[3][0])
455 if a: print pos, Int[3][0], self.blocs_texte[ch]
456 if Int[3][0] == self.blocs_texte[ch][pos-1]:
457
458 if a: print 'occ ',Int[3][0],' removed'
459 self.blocs_texte[ch].remove(Int[3][0])
460 if len(self.blocs_texte[ch]) == 0:
461 del self.blocs_texte[ch]
462 else:
463 ch1 = self.texte[Int[2][0]:Int[2][1]]
464 ch2 = self.texte[Int[3][0]:Int[3][1]]
465 if a: print 'chevauchement entre *',ch1,'* et *',ch2,'*'
466
467 if self.blocs_texte.has_key(ch1) and self.blocs_texte.has_key(ch2):
468 pos1 = bisect.bisect_right(self.blocs_texte[ch1], Int[2][0])
469 pos2 = bisect.bisect_right(self.blocs_texte[ch2], Int[3][0])
470 if a: print pos1, Int[2][0], self.blocs_texte[ch1]
471 if a: print pos2, Int[3][0], self.blocs_texte[ch2]
472 if (Int[2][0] == self.blocs_texte[ch1][pos1-1] and
473 Int[3][0] == self.blocs_texte[ch2][pos2-1]):
474
475 self.adapter_cesure2(self.resoudre_recouvrement(Int), Int[2], Int[3])
476 if a: print 'cesure adapted'
477
478 Recouvre = self.recouvrements(self.couverture())
479
480 tot = sum([len(chaine)*len(locc) for chaine,locc in self.blocs_texte.iteritems()])
481 logging.debug("fin eliminer_recouvrements len(chaines dic)=%d",tot)
482
483 return self.blocs_texte
484
486 tot = sum([len(chaine)*len(locc) for chaine,locc in self.blocs_texte.iteritems()])
487
488
489 Recouvre = self.recouvrements(self.couverture())
490 i=0
491 while Recouvre != []:
492
493
494 for Int in Recouvre:
495
496
497 if ( self.blocs_texte.has_key(self.texte[Int[2][0]:Int[2][1]]) and
498 self.blocs_texte.has_key(self.texte[Int[3][0]:Int[3][1]])):
499 if self.tool.inclus_(Int[2], Int[3]):
500 ch = self.texte[Int[2][0]:Int[2][1]]
501 if Int[2][0] in self.blocs_texte[ch]:
502 self.blocs_texte[ch].remove(Int[2][0])
503 if len(self.blocs_texte[ch]) == 0:
504 del self.blocs_texte[ch]
505 elif self.tool.inclus_(Int[3], Int[2]):
506 ch = self.texte[Int[3][0]:Int[3][1]]
507 if Int[3][0] in self.blocs_texte[ch]:
508 self.blocs_texte[ch].remove(Int[3][0])
509 if len(self.blocs_texte[ch]) == 0:
510 del self.blocs_texte[ch]
511 else:
512 if cesureRandom:
513 self.adapter_cesure_nocoordo(random.randint(Int[0],Int[1]), Int[2], Int[3])
514 else:
515 self.adapter_cesure_nocoordo(self.resoudre_recouvrement(Int), Int[2], Int[3])
516
517
518 Recouvre = self.recouvrements(self.couverture())
519
520
521
522
523 return self.blocs_texte
524
527 """ part d'un intervalle qui correspond à un recouvrement
528 et trouve une cesure judicieuse (par exemple un blanc)
529 On coupera sur cette cesure
530 I: [occ_debut, occ_fin, chaine_anterieure, chaine_posterieure]
531
532 Attention !! pb dans BBL.extractDeplacements(), ne respecte plus l'assertion
533 d'ordre si on utilise cette fonction"""
534 sep = " .-,!?:;"
535 tailleChAnt=I[2][1]-I[2][0]
536 tailleChPost=I[3][1]-I[3][0]
537
538
539 if tailleChAnt < tailleChPost:
540
541 if (I[0] == 0 or I[0] == self.lg_texte1 or
542 self.texte[I[0]-1] in sep):
543 return I[0]
544 if (I[1] == (self.lg_texte1 - 1) or I[1] == (self.lg_texte1 + self.lg_texte2 - 1) or
545 self.texte[I[1]] in sep):
546 return I[1]
547 else:
548 if (I[1] == (self.lg_texte1 - 1) or I[1] == (self.lg_texte1 + self.lg_texte2 - 1) or
549 self.texte[I[1]] in sep):
550 return I[1]
551 if (I[0] == 0 or I[0] == self.lg_texte1 or
552 self.texte[I[0]-1] in sep):
553 return I[0]
554
555 if tailleChAnt <= tailleChPost: L = range(I[0], I[1] + 1)
556 else: L = range(I[1], I[0]-1, -1)
557
558 for x in L:
559 if self.texte[x] == ' ':
560 return x
561 for x in L:
562 if self.texte[x] in sep:
563 return x
564 return L[0]
565
567 chaine = self.texte[debut:fin]
568 try:
569 self.res[chaine].append(debut)
570 except KeyError:
571 self.res[chaine] = [debut]
572
574
575 seq_repeat = self.blocs_texte
576
577 self.res = {}
578 nbFusion = 1 ; n=0 ; cut = False
579 while nbFusion > 0 :
580 nbFusion = 0 ; n += 1
581
582 pos = old_debut = len(seq_repeat)-1
583 while pos >= 0:
584 (debut,fin) = seq_repeat[pos]
585 if debut == fin: pos -= 1 ; continue
586 pos = debut
587 pos -= 1
588 (debut_prec,fin_prec) = seq_repeat[pos]
589 if pos == -1: (debut_prec,fin_prec) = (-1,-1)
590 if fin_prec >= fin:
591 assert debut_prec <= debut, str(debut_prec)+' '+str(debut)
592 for i in xrange(debut,fin): seq_repeat[i] = (debut_prec,fin_prec)
593 nbFusion += 1
594 continue
595 if fin_prec <= debut:
596 continue
597 assert debut_prec <= debut < fin_prec <= fin
598
599 coupure = self.resoudre_recouvrement((debut,fin_prec,(debut_prec,fin_prec),(debut,fin)))
600
601 for i in xrange(coupure,fin):
602 seq_repeat[i] = (coupure, fin)
603
604
605 for i in xrange(debut_prec, coupure):
606 seq_repeat[i] = (debut_prec, coupure)
607
608
609 nbFusion += 1
610
611
612 pos = len(seq_repeat)-1
613 while pos >= 0:
614 (debut,fin) = seq_repeat[pos]
615 if fin-debut > 0: self.add_bloc(debut,fin)
616 pos = debut - 1
617
618 return self.res
619
621
622 seq_repeat = self.blocs_texte
623 longueur_sequence = len(seq_repeat)
624
625 self.res = {}
626 nbFusion = 1 ; n=0
627 while nbFusion > 0:
628 nbFusion = 0 ; n += 1
629 print n
630 pos = old_debut = 0
631 while pos < longueur_sequence:
632 (debut,fin) = seq_repeat[pos]
633 pos = fin + 1
634 if debut == fin: continue
635 if pos >= longueur_sequence: (debut_prec,fin_prec) = (longueur_sequence+1,longueur_sequence+1)
636 else: (debut_prec,fin_prec) = seq_repeat[pos]
637
638 if fin >= fin_prec:
639 assert debut <= debut_prec
640 for i in xrange(debut_prec,fin_prec): seq_repeat[i] = (debut,fin)
641 nbFusion += 1
642 continue
643 if fin <= debut_prec:
644 continue
645 if debut >= debut_prec:
646 for i in xrange(debut,fin): seq_repeat[i] = (debut_prec,fin_prec)
647 nbFusion += 1
648 continue
649 assert debut <= debut_prec < fin <= fin_prec, str(pos)+str((debut,fin))+str((debut_prec,fin_prec))
650 coupure = self.resoudre_recouvrement((debut_prec,fin,(debut,fin),(debut_prec,fin_prec)))
651 for i in xrange(debut,coupure):
652 seq_repeat[i] = (debut, coupure)
653
654
655 for i in xrange(coupure, fin_prec):
656 seq_repeat[i] = (coupure, fin_prec)
657 nbFusion += 1
658 print nbFusion
659 pos = 0
660 while pos < len(seq_repeat):
661 (debut,fin) = seq_repeat[pos]
662 self.add_bloc(debut,fin)
663 pos = fin + 1
664
665 return self.res
666
668 logging.debug("debut eliminer_recouvrements")
669 seq_repeat = self.blocs_texte
670 self.res = {}
671 pos = old_debut = len(seq_repeat)-1
672
673 (debut_av,fin_av) = (len(seq_repeat),len(seq_repeat))
674 while pos >= 0:
675
676 (debut,fin) = seq_repeat[pos]
677 pos = debut
678 pos -= 1
679 if debut == fin: continue
680 (debut_prec,fin_prec) = seq_repeat[pos]
681 if pos == -1: (debut_prec,fin_prec) = (-1,-1)
682 if fin_prec >= fin:
683
684 assert debut_prec <= debut
685 continue
686 if fin_prec <= debut:
687 self.add_bloc(debut,fin); continue
688 assert debut_prec <= debut < fin_prec <= fin
689 coupure = self.resoudre_recouvrement((debut,fin_prec,(debut_prec,fin_prec),(debut,fin)))
690 self.add_bloc(coupure,fin)
691 seq_repeat[pos] = (debut_prec, coupure)
692 return self.res
693
695 logging.debug("debut eliminer_recouvrements")
696 seq_repeat = self.blocs_texte
697 longueur_sequence = len(seq_repeat)
698 self.res = {}
699 pos = old_debut = 0
700
701
702 while pos < longueur_sequence:
703
704 (debut,fin) = seq_repeat[pos]
705 pos = fin
706 pos += 1
707 if debut == fin: continue
708 if pos >= longueur_sequence: (debut_prec,fin_prec) = (longueur_sequence+1,longueur_sequence+1)
709 else: (debut_prec,fin_prec) = seq_repeat[pos]
710
711 if fin >= fin_prec:
712
713 assert debut <= debut_prec
714 self.add_bloc(debut,fin)
715 continue
716 if fin <= debut_prec:
717 self.add_bloc(debut,fin); continue
718 if debut >= debut_prec:
719 continue
720 assert debut <= debut_prec < fin <= fin_prec, str(pos)+str((debut,fin))+str((debut_prec,fin_prec))
721 coupure = self.resoudre_recouvrement((debut_prec,fin,(debut,fin),(debut_prec,fin_prec)))
722 self.add_bloc(debut,coupure)
723 seq_repeat[pos] = (coupure,fin_prec)
724 return self.res
725
727 logging.debug("debut eliminer_recouvrements")
728 seq_repeat = self.blocs_texte
729 res = {}
730 pos = len(seq_repeat)-1
731 old_debut = len(seq_repeat)+1
732 (debut_av,fin_av) = (len(seq_repeat),len(seq_repeat))
733 while pos >= 0:
734
735 pos_BU = pos
736 (debut,fin) = seq_repeat[pos]
737
738 assert debut <= fin
739 if debut == fin:
740 pos = debut-1
741
742 else:
743 pos = debut
744 (debut_prec,fin_prec) = seq_repeat[pos-1]
745
746 while pos-2 >= 0:
747 (debut_prec2,fin_prec2) = seq_repeat[pos-2]
748 if fin_prec2 >= fin_prec:
749 assert debut_prec2 <= debut_prec,str(debut_prec2)+'/'+str(debut_prec)
750 (debut_prec,fin_prec) = seq_repeat[pos-2]
751 pos -= 1
752 else: break
753
754 pos -= 1
755 if fin_prec >= fin:
756 continue
757
758 if fin_prec > debut:
759 coupure = self.resoudre_recouvrement((debut,fin_prec,(debut_prec,fin_prec),(debut,fin)))
760 debut = coupure
761 seq_repeat[pos] = (debut_prec,coupure)
762
763
764 if fin > debut_av:
765 coupure2 = debut_av
766 fin = coupure2
767
768 assert fin <= old_debut,str(fin)+'/'+str(old_debut)
769 assert fin <= debut_av
770 chaine = self.texte[debut:fin]
771 try:
772 res[chaine].append(debut)
773 except KeyError:
774 res[chaine] = [debut]
775 (debut_av,fin_av) = (debut,fin)
776 old_debut = debut
777
778
779
780 logging.debug("fin eliminer_recouvrements")
781 return res
782
784 logging.debug("debut eliminer_recouvrements")
785 seq_repeat = self.blocs_texte
786 res = {}
787 pos = 0
788 old_fin = -1
789 (debut_av,fin_av) = (-1,-1)
790 while pos < len(seq_repeat)-1:
791
792 pos_BU = pos
793 (debut,fin) = seq_repeat[pos]
794
795 assert debut <= fin
796 if debut == fin:
797 pos = fin+1
798
799 else:
800 pos = fin
801 if pos >= len(seq_repeat)-1:
802 try:
803 chaine = self.texte[debut:fin]
804 res[chaine].append(debut)
805 except KeyError:
806 res[chaine] = [debut]
807 break
808
809 (debut_prec,fin_prec) = seq_repeat[pos+1]
810
811 while pos+2 <len(seq_repeat):
812 (debut_prec2,fin_prec2) = seq_repeat[pos+2]
813 if (debut_prec2 == debut_prec and fin_prec2 >= fin_prec):
814 assert debut_prec2 >= debut_prec,str(debut_prec2)+'/'+str(debut_prec)
815 (debut_prec,fin_prec) = seq_repeat[pos+2]
816 pos += 1
817 else: break
818 pos += 1
819
820
821
822
823 if debut_prec < fin:
824 coupure = self.resoudre_recouvrement((debut_prec,fin,(debut,fin),(debut_prec,fin_prec)))
825 fin = coupure
826 seq_repeat[pos] = (coupure,fin_prec)
827
828
829 if debut > fin_av:
830 coupure2 = fin_av
831 debut = coupure2
832
833 assert fin >= old_fin,str(fin)+'/'+str(old_fin)
834
835 chaine = self.texte[debut:fin]
836 try:
837 res[chaine].append(debut)
838 except KeyError:
839 res[chaine] = [debut]
840 (debut_av,fin_av) = (debut,fin)
841 old_fin = fin
842
843
844
845 logging.debug("fin eliminer_recouvrements")
846 return res
847
849 """ Renvoie un dico indexé par un tuplet (cle,longueur)
850 plutot que par chaine[debut:fin], ce qui évite de stocker les chaines
851 dans le dico """
853 cle = hash(self.texte[debut:fin])
854 longueur = fin-debut
855 try:
856 self.res[(cle,longueur)].append(debut)
857 except KeyError:
858 self.res[(cle,longueur)] = [debut]
859 self.NOSMEM_nb_bloc += 1
860
862 - def __init__(self,texte,blocs_texte,lg_texte1,min_size):
865
892
894 listet = self.transformListe()
895
896 longueur_totale = self.lg_texte1+self.lg_texte2+1
897 self.seq_repeat_deb = Numeric.zeros(longueur_totale,Numeric.Int)
898 self.seq_repeat_fin = Numeric.zeros(longueur_totale,Numeric.Int)
899 for i in xrange(longueur_totale):
900
901 self.seq_repeat_deb[i] = i
902 self.seq_repeat_fin[i] = i
903
904 self.totalAjout = self.totalRogneG = self.totalRogneD = self.nb_reinclusion = 0
905 bb= False
906 i = 0
907 while i < len(listet)-1:
908 [deb, longueur, cle_hash , lOcc] = listet[i]
909 k = 0
910 while k < len(lOcc)-1:
911 occ1 = lOcc[k] ; occ2 = lOcc[k+1]
912 if occ1+longueur > occ2:
913 pos = lOcc.index(occ2)
914 lOcc.pop(pos)
915 else: k+= 1
916
917 j = i + 1
918 while j < len(listet):
919 (deb2, longueur2, cle_hash2 , lOcc2) = listet[j]
920 dd1 = dd2 = dg1 = dg2 = 0
921 for occ in lOcc:
922 for occ2 in lOcc2:
923
924 if '&&é&éé.nous.' == self.texte[occ:occ+longueur] :
925 print listet[i],listet[j]
926 bb = True
927
928
929 if occ <= occ2 < occ2+longueur2 <= occ+longueur:
930 pos = lOcc2.index(occ2)
931 lOcc2.pop(pos)
932 if occ2 <= occ < occ+longueur <= occ2+longueur2:
933 pos = lOcc.index(occ)
934 lOcc.pop(pos)
935 if occ < occ2 < occ+longueur and occ+longueur < longueur_totale-1:
936 if bb: print dd1,dg1
937 cd = self.resoudre_recouvrement([occ2, occ+longueur,[occ,occ+longueur], [occ2,occ2+longueur2]])
938 dd1 = max(dd1,occ+longueur-cd)
939 dg1 = max(dg1, cd-occ2)
940 if bb: print cd,dd1,dg1
941 if occ2 < occ < occ2+longueur2 and occ2+longueur2 < longueur_totale-1:
942 if bb: print dd2,dg2
943 cg = self.resoudre_recouvrement([occ, occ2+longueur2,[occ2,occ2+longueur2], [occ,occ+longueur]])
944 dg2 = max(dg2, cg-occ)
945 dd2 = max(dd2, occ2+longueur2-cg)
946 if bb: print cg,dd2,dg2
947 if dd1 > 0 or dg1 > 0:
948 longueur -= dd1
949 lOcc2 = [occ+dg1 for occ in lOcc2]
950 longueur2 -= dg1
951
952 if dd2 > 0 or dg2 > 0:
953 longueur2 -= dd2
954 lOcc = [occ+dg2 for occ in lOcc]
955 longueur -= dg2
956
957 if len(lOcc2) == 0:
958 listet[j] = [sys.maxint, longueur2, cle_hash2 , lOcc2]
959 else: listet[j] = [lOcc2[0], longueur2, cle_hash2 , lOcc2]
960
961 if bb: print listet[i],listet[j]
962 j += 1
963 if bb: bb= False
964 if len(lOcc) == 0:
965 listet[i] = [sys.maxint, longueur, cle_hash , lOcc]
966 else: listet[i] = [lOcc[0], longueur, cle_hash , lOcc]
967 (deb, longueur, cle_hash , lOcc) = listet[i]
968 i += 1
969
970
971
972
973
974 self.NOSMEM_nb_bloc = 0
975 self.NOSMEM_nb_occ = 0
976 self.NOSMEM_tot_size = 0
977 self.res = {}
978 pos = 0
979
980
981 for nosmem in listet:
982 (deb, longueur, cle_hash , lOcc) = nosmem
983 if longueur == 0:
984
985 continue
986 if len(lOcc) == 1:
987
988 continue
989 prev = -1
990 for occ in lOcc:
991 if occ > prev:
992 self.add_bloc(occ,occ+longueur)
993 self.NOSMEM_nb_occ += 1
994 self.NOSMEM_tot_size += longueur
995 prev = occ + longueur
996
997
998
999
1000
1001
1002
1003 for cle,lOcc in self.res.iteritems():
1004 lOcc.reverse()
1005
1006 return self.res
1007
1009 """ part d'un intervalle qui correspond à un recouvrement
1010 et trouve une cesure judicieuse (par exemple un blanc)
1011 On coupera sur cette cesure
1012 I: [occ_debut, occ_fin, chaine_anterieure, chaine_posterieure]
1013
1014 Attention !! pb dans BBL.extractDeplacements(), ne respecte plus l'assertion
1015 d'ordre si on utilise cette fonction"""
1016 sep = " .-,!?:;\r\n\t"
1017 tailleChAnt=I[2][1]-I[2][0]
1018 tailleChPost=I[3][1]-I[3][0]
1019 res = random.randint(I[0],I[1])
1020 if res < 0: res = 0
1021 elif res > self.lg_texte1 + self.lg_texte2: res = self.lg_texte1 + self.lg_texte2
1022 assert 0 <= res <= self.lg_texte1 + self.lg_texte2
1023 return res
1024
1026 - def __init__(self,texte,blocs_texte,lg_texte1,min_size):
1029
1031
1032 self.dicoOccLiee = {}
1033 longueur_totale = self.lg_texte1+self.lg_texte2+1
1034 self.seq_repeat_deb = Numeric.zeros(longueur_totale,Numeric.Int)
1035 self.seq_repeat_fin = Numeric.zeros(longueur_totale,Numeric.Int)
1036 for i in xrange(longueur_totale):
1037
1038 self.seq_repeat_deb[i] = i
1039 self.seq_repeat_fin[i] = i
1040 self.hqOccBloc = self.transformHeapQueue()
1041 self.old_len_add = 10000000
1042 self.totalAjout = self.totalRogneG = self.totalRogneD = self.nb_reinclusion = 0
1043
1044 while len(self.hqOccBloc) > 0:
1045
1046 (index,longueur,cle_hash,lOcc) = heapq.heappop(self.hqOccBloc)
1047
1048
1049
1050 if len(lOcc) > 1:
1051
1052 self.ajoutOccurences(longueur,lOcc)
1053
1054
1055
1056
1057
1058 self.NOSMEM_nb_bloc = 0
1059 self.NOSMEM_nb_occ = 0
1060 self.NOSMEM_tot_size = 0
1061 self.res = {}
1062 pos = 0
1063
1064 while pos < len(self.seq_repeat_deb):
1065 debut = self.seq_repeat_deb[pos]
1066 fin = self.seq_repeat_fin[pos]
1067 if fin-debut > 0:
1068 self.add_bloc(debut,fin)
1069 pos = fin
1070 self.NOSMEM_nb_occ += 1
1071 self.NOSMEM_tot_size += fin-debut
1072 else: pos += 1
1073
1074
1075
1076
1077
1078
1079 for cle,lOcc in self.res.iteritems():
1080 lOcc.reverse()
1081
1082 return self.res
1083
1085 """ Ajoute la liste des occurrences lOcc à self.seq_repeat """
1086 lNonOverlap, lOverlap = self.checkOverlap(longueur,lOcc)
1087 if len(lNonOverlap) == 1:
1088
1089
1090 bisect.insort_right(lOverlap,lNonOverlap[0])
1091 elif len(lNonOverlap) > 1:
1092
1093 cle = hash(self.texte[lNonOverlap[0][1]:lNonOverlap[0][2]])
1094 longueur2 = lNonOverlap[0][2] - lNonOverlap[0][1]
1095 locc = [item[1] for item in lNonOverlap]
1096 try:
1097
1098 self.dicoOccLiee[(cle,longueur2)].extend(locc)
1099 except KeyError:
1100 self.dicoOccLiee[(cle,longueur2)] = locc
1101 self.addOccSeq(lNonOverlap)
1102
1103 if len(lOverlap) > 1:
1104 item_min = lOverlap[0] ; lOcc = []
1105 for item in lOverlap: assert item_min[0] <= item[0]
1106 max_decalageG = max_decalageD = 0
1107 for item in lOverlap:
1108
1109
1110 max_decalageG = max(max_decalageG, item[3])
1111 max_decalageD = max(max_decalageD, item[4])
1112 for item in lOverlap:
1113
1114
1115 lOcc.append(item[1]-item[3]+max_decalageG)
1116
1117 nouveau_debut_item_min = item_min[1]-item_min[3]+max_decalageG
1118 nouveau_fin_item_min = item_min[2]-item_min[4]+max_decalageD
1119 longueur2 = nouveau_fin_item_min - nouveau_debut_item_min
1120 if longueur2 > 0:
1121
1122 cle_hash = hash(self.texte[nouveau_debut_item_min:nouveau_fin_item_min])
1123 item = (1.0/longueur2,longueur2,cle_hash,lOcc)
1124
1125 self.nb_reinclusion += 1
1126 heapq.heappush(self.hqOccBloc, item)
1127
1129 """Ajout effectif des occurrences d'un bloc à self.seq_repeat """
1130
1131 cle_dic = hash(self.texte[lNonOverlap[0][1]:lNonOverlap[0][2]])
1132 longeur_dic = lNonOverlap[0][0]
1133 for longueur,debut,fin,decalageG,decalageD in lNonOverlap:
1134
1135 self.totalAjout += longueur
1136
1137
1138 debut_prec = self.seq_repeat_deb[debut]
1139 fin_prec = self.seq_repeat_fin[debut]
1140 if debut < fin_prec:
1141
1142 pos_cesure = debut - debut_prec
1143 longueur_prec = fin_prec - debut_prec
1144 cle_prec = hash(self.texte[debut_prec:fin_prec])
1145 if self.dicoOccLiee.has_key((cle_prec,longueur_prec)):
1146 locc_prec = list(self.dicoOccLiee[(cle_prec,longueur_prec)])
1147 else: locc_prec = [debut_prec]
1148 for debut_occ_prec in locc_prec:
1149 for i in xrange(debut_occ_prec,debut_occ_prec+longueur_prec):
1150 if i < debut_occ_prec+pos_cesure:
1151
1152 self.seq_repeat_deb[i] = debut_occ_prec
1153 self.seq_repeat_fin[i] = debut_occ_prec+pos_cesure
1154 else:
1155
1156 self.seq_repeat_deb[i] = i
1157 self.seq_repeat_fin[i] = i
1158 self.totalRogneG += 1
1159
1160 if self.dicoOccLiee.has_key((cle_prec,longueur_prec)): del self.dicoOccLiee[(cle_prec,longueur_prec)]
1161 try: self.dicoOccLiee[hash(self.texte[locc_prec[0]:locc_prec[0]+pos_cesure]),pos_cesure].extend(locc_prec)
1162 except KeyError: self.dicoOccLiee[hash(self.texte[locc_prec[0]:locc_prec[0]+pos_cesure]),pos_cesure]=locc_prec
1163
1164
1165 debut_suiv = self.seq_repeat_deb[fin]
1166 fin_suiv = self.seq_repeat_fin[fin]
1167 if debut_suiv < fin:
1168
1169 pos_cesure = fin - debut_suiv
1170 longueur_suiv = fin_suiv - debut_suiv
1171 cle_suiv = hash(self.texte[debut_suiv:fin_suiv])
1172 if self.dicoOccLiee.has_key((cle_suiv,longueur_suiv)):
1173 locc_suiv = list(self.dicoOccLiee[(cle_suiv,longueur_suiv)])
1174 else: locc_suiv = [debut_suiv]
1175 nouv_longueur_suiv = longueur_suiv - pos_cesure
1176 nouv_locc_suiv = []
1177 for debut_occ_suiv in locc_suiv:
1178 for i in xrange(debut_occ_suiv,debut_occ_suiv+longueur_suiv):
1179 if i < debut_occ_suiv+pos_cesure:
1180
1181 self.seq_repeat_deb[i] = i ; self.seq_repeat_fin[i] = i
1182 else:
1183
1184 self.seq_repeat_deb[i] = debut_occ_suiv+pos_cesure
1185 self.seq_repeat_fin[i] = debut_occ_suiv+longueur_suiv
1186 nouv_locc_suiv.append(debut_occ_suiv+pos_cesure)
1187 self.totalRogneD += 1
1188
1189 if self.dicoOccLiee.has_key((cle_suiv,longueur_suiv)): del self.dicoOccLiee[(cle_suiv,longueur_suiv)]
1190 try: self.dicoOccLiee[hash(self.texte[nouv_locc_suiv[0]:nouv_locc_suiv[0]+nouv_longueur_suiv]),nouv_longueur_suiv].extend(nouv_locc_suiv)
1191 except KeyError: self.dicoOccLiee[hash(self.texte[nouv_locc_suiv[0]:nouv_locc_suiv[0]+nouv_longueur_suiv]),nouv_longueur_suiv]=nouv_locc_suiv
1192
1193
1194
1195 for i in xrange(debut,fin):
1196
1197 self.seq_repeat_deb[i] = debut
1198 self.seq_repeat_fin[i] = fin
1199
1201 '''Recherche des chevauchements gauche et droits d'une liste d'occurrences d'un bloc.
1202 Les césures potentielles sont recherchées et stockées avec les blocs associés.
1203 lNonOverlap est une liste d'occurrences sans chevauchement et lOverlap avec.
1204 lOverlap est ordonée de façon croissante sur la longueur des blocs césurés.
1205 les overlap G et D sont résolus ensemble'''
1206
1207 lNonOverlap = [] ; lOverlap = [] ; discarded = 0
1208 for occ in lOcc:
1209 debut = occ ; fin = occ+longueur
1210 try:
1211
1212 d1 = self.seq_repeat_deb[debut] ; f1 = self.seq_repeat_fin[debut]
1213
1214 d2 = self.seq_repeat_deb[fin] ; f2 = self.seq_repeat_fin[fin]
1215 except IndexError:
1216 return lNonOverlap, lOverlap
1217
1218 if d1 <= debut < fin <= f1:
1219
1220 discarded += 1
1221
1222 else:
1223 overlapG = d1 <= debut < f1 <= fin
1224 overlapD = debut <= d2 < fin <= f2
1225
1226 if overlapG: cesureG = self.resoudre_recouvrement([debut,f1,[d1,f1],[debut,fin]])
1227 else: cesureG = debut
1228 if overlapD: cesureD = self.resoudre_recouvrement([d2,fin,[debut,fin],[d2,f2]])
1229 else: cesureD = fin
1230
1231
1232 decalageG = cesureG - debut ; decalageD = fin - cesureD
1233
1234 if (not overlapG and not overlapD) or (decalageG == decalageD == 0):
1235 assert cesureG == debut and cesureD == fin
1236 lNonOverlap.append((longueur,debut,debut+longueur,0,0))
1237 else: bisect.insort_right(lOverlap,(cesureD-cesureG,cesureG,cesureD,decalageG,decalageD))
1238 assert len(lOcc) == discarded + len(lNonOverlap) + len(lOverlap)
1239
1240 return lNonOverlap, lOverlap
1241
1263
1265 """ part d'un intervalle qui corresponds a un recouvrement
1266 et trouve une cesure judicieuse (par exemple un blanc)
1267 On coupera sur cette cesure
1268 I: [occ_debut, occ_fin, chaine_anterieure, chaine_posterieure]
1269 la chaine la + longue est favorisée"""
1270
1271 taillech1=I[2][1]-I[2][0]
1272 taillech2=I[3][1]-I[3][0]
1273 sep = " .-,!?:;\r\n\t"
1274 if taillech1<=taillech2:
1275 if (I[0] == 0 or I[0] == self.lg_texte1 or
1276 self.texte[I[0]-1] in sep):
1277 return I[0]
1278 if (I[1] == (self.lg_texte1 - 1) or I[1] == (self.lg_texte1 + self.lg_texte2 - 1) or
1279 self.texte[I[1]] in sep):
1280 return I[1]
1281 else:
1282 if (I[1] == (self.lg_texte1 - 1) or I[1] == (self.lg_texte1 + self.lg_texte2 - 1) or
1283 self.texte[I[1]] in sep):
1284 return I[1]
1285 if (I[0] == 0 or I[0] == self.lg_texte1 or
1286 self.texte[I[0]-1] in sep):
1287 return I[0]
1288
1289 if taillech1<=taillech2: L = range(I[0], I[1] + 1)
1290 else: L = range(I[1], I[0]-1, -1)
1291
1292 for x in L:
1293 if self.texte[x] == ' ':
1294 return x
1295 for x in L:
1296 if self.texte[x] in sep:
1297 return x
1298 return L[0]
1299