• Nie Znaleziono Wyników

Zależność (10.3) z warunkami brzegowymi (10.2) poprawnie wyznacza podciąg MerLCS dla ciągów Z, A, B

niezmienniczy względem transpozycji

Lemat 10.1. Zależność (10.3) z warunkami brzegowymi (10.2) poprawnie wyznacza podciąg MerLCS dla ciągów Z, A, B

Dowód. Dowód jest identyczny jak dowód twierdzenia 1 z [116] z jednym wyjątkiem. Dla do-pasowania (sytuacji, w której zi= aj lub zi= bk) nie można zapomnieć o możliwości, że skró-cenie jednego z ciągów o jeden symbol może doprowadzić do lepszego wyniku niż podążenie

za dopasowaniem i skrócenie dwu ciągów. 

Podstawową ideą algorytmu Penga i in. [173] jest ograniczenie obliczeń tylko do komó-rek macierzy M reprezentujących dopasowania, których zwykle jest znacznie mniej niż nmr.

10.2. Algorytm równoległości bitowej 195 Zwłaszcza w przypadku dużych alfabetów macierz programowania dynamicznego jest rzadka.

Czas potrzebny na obliczenie pojedynczej komórki macierzy może być wprawdzie większy niż O(1), ale sumarycznie dla całego algorytmu złożoność czasowa jest O(`mr), gdzie ` jest dłu-gością ciągu wynikowego. Zwykle, dla dużych alfabetów ` jest znacznie mniejsze niż n, dzięki czemu algorytm ten może być istotnie szybszy.

10.2. Algorytm równoległości bitowej

10.2.1. Podstawowe idee

Niniejszy podrozdział zawiera opis algorytmu równoległości bitowej, który został zapro-ponowany przez autora w [70]. Zanim jednak zostanie przedstawiony ten algorytm, konieczne jest dowiedzenie kilku lematów.

Lemat 10.2. Wartość komórki M(i, j, k) jest równa bądź większa o 1 niż wartość dowolnego z następujących jej sąsiadów: M(i − 1, j,k), M(i, j − 1,k), M(i, j,k − 1).

Dowód. M(i, j, k) jest długością podciągu MerLCS dla Zi, Aj, Bk. Wymienione komórki są-siednie zawierają długości podciągu MerLCS dla tych samych ciągów, przy czym jeden z nich jest okrojony o ostatni symbol. Niemożliwe jest, aby okrojenie jednego ciągu o ostatni sym-bol spowodowało zmniejszenie długości podciągu MerLCS o więcej niż 1, ponieważ usunięcie ostatniego symbolu z jednego ciągu może co najwyżej spowodować, że ten symbol nie znaj-dzie się w ciągu wynikowym. Podobnie, nie jest możliwe, żeby okrojenie jednego z ciągów wejściowych spowodowało, że długość podciągu MerLCS wzrośnie. 

Na podstawie lematu 10.2 możliwa jest reprezentacja trójwymiarowej macierzy M przez dwuwymiarową macierz G, zawierającą wektory zmian będące wektorami liczb całkowitych z zakresu [1, r]. Wektory te zdefiniowane są następująco:

i∈ G( j,k) ⇐⇒ M(i, j,k) − M(i − 1, j,k) = 1 dla 1 ≤ i ≤ r. (10.4) Równoważność pomiędzy macierzami M i G wynika z faktu, że:

M(i, j, k) = |{x : x ∈ G( j,k) ∧ x ≤ i}|. (10.5)

Łatwo można zauważyć, że definicja wektorów zmian jest analogiczna do sposobu reprezentacji zmian w macierzy programowania dynamicznego dla problemu LCS przedstawionej w [120].

Zanim zostanie sformułowany bezpośredni algorytm wyznaczania G( j, k), dogodne jest za-pisanie zależności (10.3) w następujący sposób:

M0(i, j − 1,k) = max







M0(i − 1, j − 1,k),

M(i − 1, j − 1,k) + 1, jeśli zi= aj, M(i, j − 1,k),

(10.6)

M00(i, j, k − 1) = max







M00(i − 1, j,k − 1),

M(i − 1, j,k − 1) + 1, jeśli zi= bk, M(i, j, k − 1),

(10.7)

M(i, j, k) = max

(M0(i, j − 1,k),

M00(i, j, k − 1). (10.8)

Można zauważyć, że pierwsze składniki funkcji maksimum w (10.6)–(10.7) oznaczają tylko tyle, że wartości M0, M00, M nie maleją przy wzroście i (por. trzeci składnik funkcji maksimum w (10.3)). Wymaganie to jest inherentne dla definicji G.

Wektor zmian G0( j −1,k) dla M0(i, j −1,k) może być wyznaczony na podstawie G( j −1,k) następująco:

1. G0( j − 1,k) ← G( j − 1,k).

2. Dla każdego i od r do 1 takiego, że zi= ajwykonaj:

a) jeśli i ∈ G0( j − 1,k) nie rób nic,

b) w przeciwnym przypadku wstaw i do G0( j − 1,k) i usuń z G0( j − 1,k) najmniejszą war-tość całkowitą (jeśli taka istnieje) większą niż i.

W podobny sposób obliczany jest wektor G00( j, k − 1).

Lemat 10.3. Powyższy algorytm poprawnie oblicza wektory zmian G0( j − 1,k) i G00( j, k − 1) odpowiadające M0(i, j − 1,k) i M00(i, j, k − 1) dla wszystkich poprawnych wartości i.

Dowód. Rangą h(x) elementu x w wektorze zmian będzie nazywany indeks tego elementu w posortowanym zbiorze wartości znajdujących się w wektorze zmian. Można zauważyć, że dla każdego i w G0( j − 1,k) o randze h(i) zachodzi:

• M(i, j − 1,k) = h(i), a więc i ∈ G( j − 1,k) lub

• M(i − 1, j − 1,k) = h(i) − 1 i zi= aj.

Wobec tego i należy do G0( j − 1,k) wtedy i tylko wtedy, gdy:

• i ∈ G( j − 1,k) i nie istnieje i0< i takie, że M(i0− 1, j − 1,k) = h(i0) − 1 i zi0 = aj lub

• i jest najmniejszym indeksem takim, że M(i − 1, j − 1,k) = h(i) − 1 i zi= aj.

Dowód dla G00( j, k − 1) jest analogiczny. 

10.2. Algorytm równoległości bitowej 197 Łatwo można zauważyć, że powyższy sposób wyznaczania wektorów zmian jest dokładnie taki sam jak pokazany w [120, Observation 4] dla algorytmu LCS-BP-Length rozwiązującego problem LCS.

Dysponując wektorami G0( j − 1,k), G00( j, k − 1), można wyznaczyć G( j,k). Na podstawie (10.5) oraz (10.8) wiadomo, że:

M(i, j, k) = max

(|{x : x ∈ G0( j − 1,k) ∧ x ≤ i}|

|{x : x ∈ G00( j, k − 1) ∧ x ≤ i}| . (10.9) W związku z tym, aby obliczyć G( j, k), należy postępować jak poniżej:

1. Dla każdej pary liczb całkowitych z G0( j − 1,k) i G00( j, k − 1) jednakowej rangi weź mniej-szą z nich i wstaw do G( j, k).

2. Jeśli wśród elementów w G0( j − 1,k) i G00( j, k − 1) występuje element o unikalnej randze, to wstaw go do G( j, k).

10.2.2. Algorytm

Do efektywnej reprezentacji wektorów zmian mogą być zastosowane wektory bitowe. Po-nieważ wszystkie wektory zmian w proponowanym algorytmie zawierają liczby całkowite z za-kresu [1, r], to długość każdego z używanych wektorów bitowych wynosi r. (Jedynie dla wy-gody prezentacji bity w wektorach bitowych będą numerowane od 1). Dla każdego wektora zmian G( j, k), G0( j −1,k), G00( j, k−1) istnieje odpowiedni wektor bitowyW ( j,k),W0( j −1,k), W00( j, k − 1) zdefiniowany następująco: wszystkie bity mają wartość 1, z wyjątkiem tych, któ-rych indeksy występują w odpowiednim wektorze zmian.

Używana będzie także tablica wektorów bitowych Yx, dla każdego x ∈Σ. Każdy wektor Yx

zdefiniowany jest następująco: wszystkie bity mają wartość0, z wyjątkiem tych, które odzwier-ciedlają pozycję symbolu x w T . Te wektory bitowe reprezentują pozycje, na których występują dopasowania przy porównywaniu ciągu T z konkretnym symbolem z A lub B. Jest to dokładnie ta sama reprezentacja jak stosowana w algorytmie LCS-BP-Length (por. podrozdz. 7.3.4).

W celu obliczenia W0( j − 1,k) na podstawie W ( j − 1,k) używa się wektora Yaj, jako że reprezentuje on pozycje, na których w Z występuje aj. Ponieważ operacje wymagane w tym miejscu są identyczne do wykonywanych w algorytmie LCS-BP-Length, więc zostanie użyta następująca sekwencja operacji bitowych z [120]:

W0( j − 1,k) ← W ( j − 1,k) & Yaj,

W0( j − 1,k) ← (W ( j − 1,k) +W0( j − 1,k)) | (W ( j − 1,k) −W0( j − 1,k)).

Analogiczną sekwencję operacji stosuje się do wyznaczenia W00( j, k − 1).

Obliczenie W ( j, k) na podstawie W0( j − 1,k) i W00( j, k − 1) jest nieco bardziej skompliko-wane. Przydatne okażą się tu poniższe lematy.

Lemat 10.4. Dla dowolnego x ∈ G0( j − 1,k) o randze h(x) i y ∈ G00( j, k − 1) o randze h(y) zachodzi:

a) jeśli x> y, to h(x) ≥ h(y), b) jeśli x< y, to h(x) ≤ h(y), c) jeśli x= y, to |h(x) − h(y)| ≤ 1.

Dowód. Dowód zostanie przeprowadzony przez zaprzeczenie.

Przypadek a: Niech x> y i h(x) < h(y). Z (10.6) i (10.7) wiadomo, że

h(x) = M0(x, j − 1,k) = M(x − 1, j − 1,k) + 1, (10.10) h(y) = M00(y, j, k − 1) = M(y − 1, j,k − 1) + 1. (10.11) Z założenia h(x) < h(y) wynika, że

M0(x, j − 1,k) < M00(y, j, k − 1). (10.12)

Na podstawie (10.8) wiadomo

M(y, j, k) ≥ M00(y, j, k − 1), (10.13)

a z x > y wynika, że

M(x − 1, j − 1,k) ≥ M(y, j − 1,k). (10.14)

Łącząc wyniki z (10.10)–(10.14), otrzymuje się:

M(y, j, k) ≥ M00(y, j, k − 1) > M0(x, j − 1,k) > M(x − 1, j − 1,k) ≥ M(y, j − 1,k), (10.15) a więc

M(y, j, k) − M(y, j − 1,k) > 1, (10.16)

co jest niemożliwe z uwagi na lemat 10.2.

Przypadek b: Dowód jest analogiczny jak dla przypadku a.

Przypadek c: Niech|h(x) − h(y)| > 1. Z (10.10) i (10.11) wynika, że

|M(x − 1, j − 1,k) − M(x − 1, j,k − 1)| > 1. (10.17) Ponieważ zarówno M(x − 1, j − 1,k), jak i M(x − 1, j − 1,k) są sąsiadami M(x − 1, j,k), więc na podstawie lematu 10.2 wartość powyższej różnicy nie może być większa niż 1. 

10.2. Algorytm równoległości bitowej 199 Lemat 10.5. W celu obliczenia G( j, k) na podstawie G0( j − 1,k) i G00( j, k − 1) wystarczy:

1. Znaleźć sumę zbiorów G0( j − 1,k) i G00( j, k − 1) otrzymując wielozbiór G( j, k), w którym niektóre liczby całkowite mogą występować dwukrotnie.

2. Usunąć z G( j, k) liczby całkowite o parzystych rangach otrzymując zbiór G( j, k).

Dowód. Dowód indukcyjny względem rangi x z G( j, k). Dla x = 1 najmniejsza liczba całkowita w wielozbiorze G( j, k) zostaje przepisana do G( j, k) (jest to element o randze 1 w G0( j − 1,k) lub G00( j, k − 1)). Kolejny najmniejszy element z G( j, k) (rangi 2) musi być elementem o ran-dze 1 odpowiednio w G00( j, k − 1) lub G0( j − 1,k) (lemat 10.4), a więc w G( j,k) znajdzie się mniejszy z elementów o randze 1 spośród wejściowych zbiorów.

Niech teraz x > 1 i dla elementów o rangach 2x − 3 i 2x − 2 z G( j, k) jeden z nich jest elementem o randze x − 1 w G0( j − 1,k), a drugi elementem o randze x − 1 w G00( j, k − 1).

Dla elementów o rangach 2x − 1 i 2x w G( j, k), jeden z nich musi być elementem o randze x w G0( j − 1,k), a drugi elementem o randze x w G00( j, k − 1) (lemat 10.4). Mniejszy z tych ele-mentów jest wstawiany do G( j, k). Oczywiście, jeśli w G( j, k) znajdują się dwa identyczne ele-menty, ich rangi różnią się parzystością, więc dokładnie jeden z nich jest wstawiany do G( j, k),

dzięki czemu G( j, k) jest zbiorem. 

Ponieważ liczby całkowite występujące w obu wektorach, G0( j − 1,k) i G00( j, k − 1), muszą należeć do G( j, k), więc można usunąć je z G( j, k) po pierwszym kroku i dodać na samym końcu (tylko po jednej kopii), po usunięciu elementów o parzystych rangach, do G( j, k). Można to wykonać za pomocą operacji różnicy symetrycznej:

W( j, k) ← W0( j − 1,k) ⊕ W00( j, k − 1).

Kluczowym etapem algorytmu wyznaczania W ( j, k) na podstawie W0( j − 1,k) i W00( j, k − 1) jest wpisanie wartości 0 do wszystkich bitów wartości 1 o parzystych rangach. W [215, stro-ny 74–77] przedstawiostro-ny jest następujący algorytm wyznaczający „parzystość” w 32-bitowym słowie komputerowym x (jego adaptacja dla innych wartości w jest natychmiastowa):

y← x ⊕ (x  1), y← y ⊕ (y  2), y← y ⊕ (y  4), y← y ⊕ (y  8), y← y ⊕ (y  16).

Bit o indeksie i w y ma wartość1 wtedy i tylko wtedy, gdy liczba bitów o wartościach 1 na pozycjach od 0 do i w x jest parzysta. Dzięki temu, aby usunąć bity 1 o parzystych rangach z wektora bitowego W ( j, k), należy wyznaczyć parzystość tego wektora i wykonać maskowanie bitów1 o parzystych rangach.

Kompletny pseudokod algorytmu rozwiązującego problem MerLCS przedstawiony jest na rys. 10.2. W pierwszej części tego algorytmu (wiersze1–7) rozwiązywany jest problem LCS dla

MerLCS-BP(Z, A, B)

Wejście: Z, A, B – podciągi, dla których wyznaczany jest podciąg MerLCS Wyjście: długość podciągu MerLCS

{Wyznaczanie warunków brzegowych}

1 W(0, 0) ← 0r 2 for k ← 1 to m do

3 U← W (0,k − 1) & Ybk

4 W(0, k) ← (W (0,k − 1) +U) | (W (0,k − 1) −U) 5 for j ← 1 to n do

6 U← W ( j − 1,0) & Yaj

7 W( j, 0) ← (W ( j − 1,0) +U) | (W ( j − 1,0) −U) {Obliczenia właściwe}

8 for j ← 1 to n do 9 for k ← 1 to m do

10 U0← W ( j − 1,k) & Yaj

11 W0← (W ( j − 1,k) +U0) | (W ( j − 1,k) −U0) 12 U00← W ( j,k − 1) & Ybj

13 W00← (W ( j,k − 1) +U00) | (W ( j, k − 1) −U00) 14 U← W0& W00

15 W ← W0 ⊕ W00

16 V ← W

17 for i ← 0 to dlog2re − 1 do

18 V ← V ⊕ (V  (1 i))

19 W( j, k) ← (W & V ) | U {Wyznaczanie wyniku}

20 ` ← 0; V ← ∼W (n,m) 21 while V 6= 0rdo

22 V ← V & (V − 1); ` ← ` + 1 23 return `

Rys. 10.2. Algorytm równoległości bitowej wyznaczający długość podciągu MerLCS Fig. 10.2. Bit-parallel algorithm computing MerLCS length

par ciągów Z i A oraz Z i B, w celu wyznaczenia warunków brzegowych (10.2). W wierszach 8–19 wykonywane są obliczenia właściwe, tj. dla każdej pary ( j, k) wyznaczany jest wektor bitowy W ( j, k). Końcowa część algorytmu (wiersze 20–23) to zliczenie bitów o wartości 0 w wektorze W (n, m), dzięki czemu otrzymuje się długość podciągu MerLCS.

10.2.3. Szczegóły implementacyjne

W algorytmie zaprezentowanym powyżej zakłada się, że r ≤ w, tzn. każdy wektor bitowy mieści się w pojedynczym słowie komputerowym, co rzadko jest spełnione. Emulacja wektorów bitowych jako tablic rozmiaru dr/we słów komputerowych nie jest trudna. Uważnej implemen-tacji wymagają jednak niektóre operacje bitowe i arytmetyczne. Wszystkie operacje odejmo-wania (−), bitowe (| , & , ⊕) w wierszach 3–4, 6–7, 10–15 mogą być łatwo zaimplementowane na tablicach słów komputerowych, ponieważ nie występują tu żadne przeniesienia pomiędzy