4.8. Algorytm genetyczny
4.11.5. Operatory pokrycia
Operator pokrycia terminalnego
Operator pokrycia terminalnego uruchamiany jest w procedurze parsowania zdania (rys. 23) w sytuacji, gdy algorytm CYK nie może znaleźć produkcji wyprowadzającej symbol terminalny (słowo zdania). W takiej sytuacji operator tworzy produkcję termi-nalną wyprowadzającą dany symbol terminalny (rys. 25 – krok 2), a następnie dodaje do zbioru produkcji terminalnych gramatyki (krok 3). Liczność zbioru produkcji nP zostaje zwiększona o jeden. W kroku 4 zostaje wpisany do zbioru M symbol nietermi-nalny stojący po lewej stronie nowej produkcji. Operator pokrycia terminalnego uru-chamia operator pokrycia uniwersalnego, jeżeli pozwala na to zmienna fcu.
procedure Operator pokrycia terminalnego (a)
1. begin
2. utwórz X∈N → a
3. PT = PT ∪{X → a} 4. M = {X}
5. if fcu then zastosuj operator pokrycia uniwersalnego dla a 6. end
Rys. 25. Algorytm operatora pokrycia terminalnego dla terminala a Fig. 25. Terminal covering algorithm for terminal a
Operator pokrycia uniwersalnego
Zadaniem operatora pokrycia uniwersalnego jest dodanie do gramatyki produkcji terminalnej, wyprowadzającej zadany parametrem symbol terminalny (słowo zdania) z wyróżnionego symbolu uniwersalnego Su. Wraz z pojawieniem się nowej produkcji zwiększającej rozmiar populacji nP do zbioru M dodawany jest symbol uniwersalny Su (rys. 26 – krok 4).
procedure Operator pokrycia uniwersalnego (a)
1. begin
2. utwórz Su → a
3. PN = PN ∪{Su → a}
4. M = M ∪ {Su} 5. end
Rys. 26. Algorytm operatora pokrycia uniwersalnego dla terminala a Fig. 26. Don’t care covering algorithm for terminal a
Ponieważ operator pokrycia uniwersalnego wywoływany jest przez operator po-krycia terminalnego, każdej produkcji terminalnej typu A → a towarzyszyć będzie produkcja Su → a. Oznacza to, że z symbolu uniwersalnego można będzie
Operator pokrycia startowego
Działanie operatora pokrycia startowego uzależnione jest od ustawienia zmiennej
fcs. Dodatkowym warunkiem uruchomienia tego operatora jest rozbiór zdania pozy-tywnego (patrz rys. 23 – krok 12). Algorytm operatora rozpoczyna się od utworzenia produkcji terminalnej wyprowadzającej dany symbol terminalny z symbolu startowe-go S (rys. 27 – krok 2). W kroku następnym dodawana jest nowa produkcja do popu-lacji produkcji za pomocą ścisku (krok 3). W kroku ostatnim algorytmu do zbioru M dodawany jest symbol startowy gramatyki.
procedure Operator pokrycia startowego (a)
1. begin
2. utwórz S → a
3. dodaj ze ściskiem S → a do PT
4. M = M ∪ {S}
5. end
Rys. 27. Algorytm operatora pokrycia startowego dla terminala a Fig. 27. Starting covering algorithm for terminal a
Operator pokrycia agresywnego
Operator pokrycia agresywnego uruchamiany jest z prawdopodobieństwem pa w procedurze parsowania zdania (patrz rys. 23 – krok 26). W pierwszej kolejności tworzona jest nowa produkcja nieterminalna, której prawa strona należy do zbioru D (rys. 28 – krok 2). W kroku 3 procedury nowa produkcja dodawana jest ze ściskiem do zbioru produkcji nieterminalnych. W ostatnim kroku procedury zbiór M powięk-szany jest o lewą stronę nowej produkcji.
procedure Operator pokrycia agresywnego (D)
1. begin
2. utwórz X → BC | X∈N, BC ∈D
3. dodaj ze ściskiem X → BC do PN
4. M = M ∪ {X} 5. end
Rys. 28. Algorytm operatora pokrycia agresywnego dla zawartości Detektorów D Fig. 28. Aggressive covering algorithm for detectors D
Operator pokrycia pełnego
Zadaniem operatora pokrycia pełnego jest, podobnie jak i operatora agresywnego, umożliwienie dalszej procedury rozbioru zdania pozytywnego, która bez pojawienia się nowej produkcji w gramatyce nie będzie możliwa. W odróżnieniu od operatora agresyw-nego, operator pokrycia pełnego zostaje uruchamiany tylko wtedy, gdy analizowana jest ostatnia komórka tablicy CYK, czyli w gramatyce są wszystkie produkcje poza produkcją wiążącą symbol startowy gramatyki z pozostałymi symbolami nieterminalnymi gramaty-ki. Dodatkowym warunkiem zadziałania operatora jest zezwolenie zmiennej fcp.
Operator pokrycia pełnego tworzy nową produkcję nieterminalną, której prawa strona należy do zbioru D, a strona lewa jest symbolem startowym gramatyki (rys. 29 – krok 2). Następnie nowo utworzona produkcja dodawana jest ze ściskiem do populacji produkcji nieterminalnych (krok 3) oraz do zbioru M dodawany jest symbol startowy S.
procedure Operator pokrycia pełnego (D)
1. begin
2. utwórz S → BC | BC ∈D
3. dodaj ze ściskiem S → BC do PN
4. M = M ∪ {S}
5. end
Rys. 29. Algorytm operatora pokrycia pełnego dla zawartości Detektorów D Fig. 29. Full covering algorithm for detectors D
4.11.6. Algorytm genetyczny
Algorytm genetyczny jest uruchamiany na zakończenie każdego kroku ewolucyjnego pod warunkiem zezwolenia ze strony zmiennej fGA (patrz rys. 21 – krok 9). Celem działa-nia algorytmu genetycznego na populacji produkcji jest ewolucyjne poszukiwanie gra-matyki o lepszych własnościach niż wyindukowana w poprzednim kroku ewolucyjnym.
procedure Algorytm genetyczny (G)
1. begin
2. P1∈PN ← dokonaj selekcji produkcji z PN
3. P2∈PN ← dokonaj selekcji produkcji z PN
4. P1* ← P1 5. P2* ← P2
6. max∈
elit
n
P PN ← wskaż nelit najlepszych produkcji z PN
7. if liczba losowa z [0, 1) < pk then zastosuj krzyżowanie na P1*i P2* 8. zastosuj mutację na P1*
9. zastosuj mutację na P2*
10. if liczba losowa z [0, 1) < pi then zastosuj inwersję na P1* 11. if liczba losowa z [0, 1) < pi then zastosuj inwersję na P2*
12. PN ← PN \ max elit n P 13. dodaj ze ściskiem P1* do PN 14. dodaj ze ściskiem P2*do PN 15. PN ← PN ∪ max elit n P 16. end
Rys. 30. Algorytm genetyczny przetwarzający gramatykę G Fig. 30. Genetic algorithm for grammar G
Pierwszym etapem algorytmu jest selekcja dwóch produkcji z populacji. Selekcja może się odbyć metodą ruletki, turniejową lub losową w zależności od ustawień zmiennych decyzyjnych 1
GA
f oraz 2 GA
f (rys. 30 – kroki 2–3). Wybrane produkcje są następnie kopiowane (krok 4–5). W kolejnym kroku wskazywanych jest nelit
najlep-szych produkcji z populacji ze względu na wartość przystosowania. W kroku 7 algo-rytmu obie kopie wybranych produkcji są krzyżowane (procedure Krzyżowanie) z prawdopodobieństwem pk. Następnie na każdej produkcji uzyskanej w wyniku krzy-żowania działa operator mutacji (procedure Mutacja). Ostatnim operatorem przetwa-rzającym kopie wybranych produkcji jest inwersja (procedure Inwersja), która działa niezależnie na każdej produkcji z prawdopodobienstwem pi (kroki 10–11). W krokach 12–15 algorytmu następuje dodanie przetworzonych ewolucyjnie produkcji do popu-lacji z zachowaniem nelit najlepszych produkcji.
Inwersja
Operator inwersji (rys. 31) uruchamiany jest w algorytmie genetycznym z prawdo-podobieństwem pi na każdej produkcji oddzielnie (rys. 30 – krok 10 i krok 11). Efektem działania operatora jest zamiana kolejności symboli po prawej stronie produkcji.
procedure Inwersja ( p) 1. begin 2. utwórz p* := A → BC | A, B, C ∈N 3. p* ← p 4. p* ← (A → CB) 5. p← p* 6. end
Rys. 31. Algorytm operatora inwersji dla produkcji p Fig. 31. Inversion algorithm for production p
Mutacja
Podobnie jak inwersja, mutacja działa niezależnie dla każdej genetycznie modyfiko-wanej produkcji (rys. 30 – krok 8 i krok 9). Z prawdopodobieństwem pm może zostać zmieniona lewa strona produkcji (rys. 32 – krok 4), następnie pierwszy symbol prawej strony produkcji (krok 5) i wreszcie drugi symbol prawej strony produkcji (krok 6).
procedure Mutacja ( p)
1. begin
2. utwórz p* := A → BC | A, B, C ∈N 3. p* ← p
4. if liczba losowa z [0, 1) < pm then p* ← (X → BC) | X∈N 5. if liczba losowa z [0, 1) < pm then p* ← (A → XC) | X∈N 6. if liczba losowa z [0, 1) < pm then p* ← (A → BX) | X∈N 7. p← p*
8. end
Rys. 32. Algorytm operatora mutacji dla produkcji p Fig. 32. Mutation algorithm for production p
Krzyżowanie
Operator genetyczny krzyżowania dwóch produkcji uruchamiany jest przez proce-durę algorytmu genetycznego z prawdopodobieństwem pk (rys. 30 – krok 7).
Krzyżo-wanie produkcji polega na zamianie miejscami bądź to symbolu pierwszego prawej strony produkcji (rys. 33 – kroki 7–10), bądź symbolu drugiego (kroki 12–15).
procedure Krzyżowanie ( p1, p2) 1. begin 2. utwórz p1* := A → BC | A, B, C ∈N 3. utwórz p2* := D → EF | D, E, F ∈N 4. p1* ← p1 5. p2* ← p2
6. if liczba losowa z {1, 2} = 1 then
7. begin 8. p1* ← (A → EC) 9. p2* ← (D → BF) 10. end 11. else 12. begin 13. p1* ← (A → BF) 14. p2* ← (D → EC) 15. end 16. p1* ← (D → BC) 17. p2* ← (A → EF) 18. p1← p1* 19. p2← p2* 20. end
Rys. 33. Algorytm operatora krzyżowania dla produkcji p1 i p2
Fig. 33. Crossover algorithm for productions p1 and p2
Po zamianie któregoś z symboli prawej strony produkcji następuje zamiana miejscami symboli znajdujących się po lewej stronie krzyżowanych produkcji (kroki 16–17).
4.11.7. Korekcja
Algorytm korekcji gramatyki składa się z trzech kroków: usunięcia produkcji redun-dantnych z gramatyki (rys. 34 – krok 2), usunięcia produkcji nieproduktywnych (krok 3) oraz usunięcia produkcji nieosiągalnych (krok 4). Korekcja jest uwarunkowana warto-ścią zmiennej fkor i jest wywoływana przez procedurę indukcji gramatyki (rys. 22).
procedure Korekcja (G)
1. begin
2. usuń produkcje redundantne z G 3. usuń produkcje nieproduktywne z G 4. usuń produkcje nieosiągalne z G 5. end
Rys. 34. Algorytm korekcji gramatyki G Fig. 34. Correction algorithm for grammar G
Zadanie znalezienia i usunięcia produkcji redundantnych z gramatyki jest stosun-kowo proste i polega na pełnym przeglądzie listy produkcji i eliminacji wszystkich produkcji, które na tej liście występują więcej niż jeden raz.
procedure Usuń produkcje nieproduktywne (G)
1. begin
2. N* ← {X | X →a ∈PT, a∈T} 3. repeat
4. for each X → BC ∈PN do
5. if { CB, }⊆ N* then N* ← N* ∪{X} 6. until N* się nie zmienia
7. PN ← { X → BC ∈PN | B, C ∈ N*} 8. end
Rys. 35. Algorytm procedury usuwania produkcji nieproduktywnych z gramatyki G Fig. 35. Algorithm for removing non-productive productions from grammar G
Drugim krokiem korekcji jest usunięcie z populacji wszystkich produkcji niepro-duktywnych, czyli takich, z których nie można wyprowadzić symboli terminalnych. W pierwszym kroku procedury do tymczasowego zbioru symboli nieterminalnych N* przepisywane są wszystkie te symbole, z których wyprowadza się symbole końcowe gramatyki (rys. 35 – krok 2). Następnie w pętli (krok 3–6) wyszukuje się wszystkie symbole nieterminalne produktywne, poczynając od symboli wyprowadzających symbole terminalne (krok 5). Pętla wykonywana jest tak długo, aż tymczasowy zbiór symboli nieterminalnych N* nie ulega już zmianie (krok 6). W ostatnim kroku proce-dury tworzony jest na nowo zbiór produkcji nieterminalnych gramatyki PN. Do tego zbioru przepisywane są tylko te produkcje, których prawe strony należą do zbioru tymczasowgo N* (krok 7).
Ostatnim etapem korekcji gramatyki jest usunięcie produkcji nieosiągalnych, czyli takich, które można wywieść z istniejących w populacji produkcji (rys. 36). Algorytm zaczyna się od stworzenia tymczasowego zbioru symboli nieterminalnych N*, do któ-rego wstawiany jest symbol końcowy gramatyki S (krok 2). Tworzony jest również
tymczasowy zbiór produkcji P* (krok 3). Następnie wykonywana jest pętla tak dłu-go, aż operacje wykonywane w środku pętli nie będą już zmieniły zawartości zbioru
N* i P* (krok 4–10). W środku pętli iteracyjnie przeszukiwana jest lista produkcji nieterminalnych gramatyki pod kątem produkcji, których prawa strona należy do zbioru N* (krok 5). Dla każdej takiej produkcji do zbioru N* dodawane są symbole z prawej strony produkcji (krok 7), a zbiór P* powiększa się o znalezioną produkcję (krok 8). Po wyjściu z pętli zbiór N* nadpisuje zbiór symboli nieterminalnych gra-matyki N (krok 11), a zbiór P* nadpisuje zbiór produkcji nieterminalnych gramatyki
PN (krok 12).
procedure Usuń produkcje nieosiągalne (G)
1. begin 2. N* ← {S} 3. P* ← Ø 4. repeat 5. for each {X → BC ∈PN | X ∈N*} do 6. begin 7. N* ← N* ∪{B, C} 8. P* ← P* ∪{ X → BC} 9. end
10. until N* i P* się nie zmieniają 11. N ← N*
12. PN ← P*
13. end
Rys. 36. Algorytm procedury usuwania produkcji nieosiągalnych z gramatyki G Fig. 36. Algorithm for removing unreachable productions from grammar G