1. ÚVOD TEORIE O GRAMATIKÁCH ZÁKLADNÍ POJMY TEORIE JAZYKŮ A GRAMATIK REGULÁRNÍ JAZYKY BEZKONTEXTOVÉ JAZYKY...

Podobné dokumenty
Automaty a gramatiky(bi-aag) Motivace. 1. Základní pojmy. 2 domácí úkoly po 6 bodech 3 testy za bodů celkem 40 bodů

doplněk, zřetězení, Kleeneho operaci a reverzi. Ukážeme ještě další operace s jazyky, na které je

Formální jazyky a gramatiky Teorie programovacích jazyků

Naproti tomu gramatika je vlastně soupis pravidel, jak

Vztah jazyků Chomskeho hierarchie a jazyků TS

Turingovy stroje. Teoretická informatika Tomáš Foltýnek

Množinu všech slov nad abecedou Σ značíme Σ * Množinu všech neprázdných slov Σ + Jazyk nad abecedou Σ je libovolná množina slov nad Σ

Vzorce. StatSoft. Vzorce. Kde všude se dá zadat vzorec

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

OSTRAVSKÁ UNIVERZITA V OSTRAVĚ PŘÍRODOVĚDECKÁ FAKULTA

Nový způsob práce s průběžnou klasifikací lze nastavit pouze tehdy, je-li průběžná klasifikace v evidenčním pololetí a školním roce prázdná.

Reliance 3 design OBSAH

FORTANNS. 22. února 2010

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

VZORCE A VÝPOČTY. Autor: Mgr. Dana Kaprálová. Datum (období) tvorby: září, říjen Ročník: sedmý

Jednoznačné a nejednoznačné gramatiky

Čtvrtek 8. prosince. Pascal - opakování základů. Struktura programu:

Programovací jazyk Pascal

Čtvrtek 3. listopadu. Makra v Excelu. Obecná definice makra: Spouštění makra: Druhy maker, způsoby tvorby a jejich ukládání

DUM 06 téma: Tvorba makra pomocí VBA

StatSoft Jak vyzrát na datum

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Překladač a jeho struktura

PHP tutoriál (základy PHP snadno a rychle)

Základní popis Toolboxu MPSV nástroje

Regulární výrazy. Definice Množina regulárních výrazů nad abecedou Σ, označovaná RE(Σ), je definována induktivně takto:

Složitost Filip Hlásek

Úvod...1 Instalace...1 Popis funkcí...2 Hlavní obrazovka...2 Menu...3 Práce s aplikací - příklad...5

ALGORITMIZACE A PROGRAMOVÁNÍ

Algoritmizace a programování

2. úkol MI-PAA. Jan Jůna (junajan)

Bezkontextové jazyky. Bezkontextové jazyky 1 p.1/39

PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1

AUTOMATY A GRAMATIKY. Pavel Surynek. Kontextové uzávěrové vlastnosti Turingův stroj Rekurzivně spočetné jazyky Kódování, enumerace

Úvod do informatiky. Miroslav Kolařík

0. ÚVOD - matematické symboly, značení,

Automaty a gramatiky(bi-aag) Formální překlady. 5. Překladové konečné automaty. h(ε) = ε, h(xa) = h(x)h(a), x, x T, a T.

Bezkontextové jazyky 2/3. Bezkontextové jazyky 2 p.1/27

Základní popis Toolboxu MPSV nástroje

6 Příkazy řízení toku

Tabulkový procesor. Základní rysy

Přehledy pro Tabulky Hlavním smyslem této nové agendy je jednoduché řazení, filtrování a seskupování dle libovolných sloupců.

Výpočetní modely pro rozpoznávání bezkontextových jazyků zásobníkové automaty LL(k) a LR(k) analyzátory

Algoritmizace. 1. Úvod. Algoritmus

6 Algebra blokových schémat

Konečný automat. Jan Kybic.

Lekce 01 Úvod do algoritmizace

Dynamicky vázané metody. Pozdní vazba, virtuální metody

2 Formální jazyky a gramatiky

Vektory a matice. Obsah. Aplikovaná matematika I. Carl Friedrich Gauss. Základní pojmy a operace

Výčtový typ strana 67

Iterační výpočty. Dokumentace k projektu č. 2 do IZP. 24. listopadu 2004

Konstrukce relace. Postupně konstruujeme na množině všech stavů Q relace i,

UniLog-D. v1.01 návod k obsluze software. Strana 1

Virtuální počítač. Uživatelský program Překladač programovacího jazyka Operační systém Interpret makroinstrukcí Procesor. PGS K.

Typy souborů ve STATISTICA. Tento článek poslouží jako přehled hlavních typů souborů v programu

KAPITOLA 9 - POKROČILÁ PRÁCE S TABULKOVÝM PROCESOREM

zapište obslužnou metodu události Click tlačítka a vyzkoušejte chování polevýsledek.text = polečíslo1.text + polečíslo2.text;

Programování v jazyce C pro chemiky (C2160) 3. Příkaz switch, příkaz cyklu for, operátory ++ a --, pole

Software602 Form Designer

programátorský manuál

Převod na nový školní rok

Implementace LL(1) překladů

Importy a exporty KLIENTSKÝ DOPLNĚK PRO PODPORU IMPORTŮ VERZE 3.2.0

Vstupní požadavky, doporučení a metodické pokyny

UŽIVATELSKÝ MANUÁL PERSONALIZACE MOJE SODEXO V

Regulární výrazy. M. Kot, Z. Sawa (VŠB-TU Ostrava) Úvod do teoretické informatiky 14. března / 20

Lexikální analýza Teorie programovacích jazyků

Postup pro zpracování kontrolního hlášení

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE LL SYNTAKTICKÁ ANALÝZA DOKONČENÍ, IMPLEMENTACE.

Algoritmus. Přesné znění definice algoritmu zní: Algoritmus je procedura proveditelná Turingovým strojem.

Modul IRZ návod k použití

VY_32_INOVACE_In 6.,7.13 Vzorce vložení funkce

Definice 7.2. Nejmenší přirozené číslo k, pro které je graf G k-obarvitelný, se nazývá chromatické číslo (barevnost) grafu G a značí se χ(g).

Excel - pokračování. Př. Porovnání cestovních kanceláří ohraničení tabulky, úprava šířky sloupců, sestrojení grafu

Lokality a uživatelé

Západočeská univerzita v Plzni Dokumentace překladače PL/0 v PHP Předmět KIV/FJP

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech

= - rovnost dvou výrazů, za x můžeme dosazovat různá čísla, tím měníme

VYTVÁŘENÍ DATABÁZÍ, VKLÁDÁNÍ ÚDAJŮ

Kontingenční tabulky v MS Excel 2010

Vlastnosti regulárních jazyků

Stěžejní funkce MS Excel 2007/2010, jejich ovládání a možnosti využití

9. Soustavy rovnic DEFINICE SOUSTAVY LINEÁRNÍCH ROVNIC O DVOU NEZNÁMÝCH. Soustava lineárních rovnic o dvou neznámých je:

UŽIVATELSKÝ MANUÁL PERSONALIZACE MOJE SODEXO V

5 Orientované grafy, Toky v sítích

Příprava dat v softwaru Statistica

7. Rozdělení pravděpodobnosti ve statistice

Gymnázium Vysoké Mýto nám. Vaňorného 163, Vysoké Mýto

1 Uživatelská dokumentace

MANUÁL VÝPOČTOVÉHO SYSTÉMU W2E (WASTE-TO-ENERGY)

Popis programu EnicomD

Internetový přístup do databáze FADN CZ - uživatelská příručka Modul FADN BASIC

1.5.2 Číselné soustavy II

ALGORITMIZACE PRAKTICKÉ

Asistivní technologie a dohledové systémy Dyslexie čtení pomocí okénka

Tematický celek Proměnné. Proměnné slouží k dočasnému uchovávání hodnot během provádění aplikace Deklarace proměnných

Tiskové sestavy. Zdroj záznamu pro tiskovou sestavu. Průvodce sestavou. Použití databází

Přílohy. Příloha 1. Obr. P1.1 Zadání úlohy v MS Excel

Nemocnice. Prvotní analýza a plán projektu

Transkript:

OBSAH 1. ÚVOD... 2 2. TEORIE O GRAMATIKÁCH... 3 2.1. ZÁKLADNÍ POJMY TEORIE JAZYKŮ A GRAMATIK... 3 2.2. REGULÁRNÍ JAZYKY... 4 2.3. BEZKONTEXTOVÉ JAZYKY... 6 3. POPIS PROBLÉMU... 8 4. ANALÝZA A NÁVRH ŘEŠENÍ... 10 4.1. PROJEKT FAKE GAME... 10 4.2. NÁVRH STRUKTURY IMPLEMENTACE... 13 4.3. NÁVRH MATEMATICKÉHO ZJEDNODUŠENÍ... 14 4.4. PODPORA PRO NOVÉ FUNKCE... 15 5. REALIZACE... 17 5.1. PARSER... 18 5.2. GRAMMAR... 19 5.3. ITEM... 20 5.4. CORRECTION... 21 5.5. OUTPUT... 24 5.6. GRAMEXCEPTION... 24 5.7. GRAMATICKÁ PRAVIDLA... 25 5.8. ZAČLENĚNÍ MODULU DO PROJEKTU... 26 6. TESTOVÁNÍ... 27 6.1. TESTOVÁNÍ ZJEDNODUŠENÍ - MATHEMATICA... 27 6.2. FUNKČNÍ TESTOVÁNÍ EXCEL... 34 7. ZÁVĚR... 36 8. SEZNAM LITERATURY... 37 9. SEZNAM OBRÁZKŮ... 38 1

1. Úvod Bakalářská práce je zaměřena na téma zjednodušování složitějších matematických výrazů. Významným cílem tohoto projektu je začlenit výslednou implementaci algoritmu na zjednodušení matematických výrazů do již běžícího projektu Fake Game. První kapitola pojednává o gramatikách v teoretické rovině, aby byly osvěženy základní znalosti z tohoto důležitého a pro tuto práci stěžejního oboru. Tato úvodní kapitola je založena na skriptech Jazyky a překlady od Prof. Ing. Bořivoje Melichara, DrSc. Následující tematické celky budou věnovány již vlastní vývojové části práce a je v nich rozebrán postupný vývoj a algoritmy implementující zjednodušení. Vlastní zjednodušení matematického výrazu je jen polovinou z celkové programátorské práce. Druhou polovinou, nebo lépe v chronologickém pořadí řečeno první polovinou, implementace je syntaktický analyzátor vstupního matematického řetězce, který postupuje v rozkladu na jednotlivé matematické prvky podle vytvořených gramatických pravidel. V závěrečné části práce se dozvíte o výsledcích porovnání tohoto zjednodušovacího algoritmu se známým nástrojem Mathematica od softwarové firmy Wolfram Research. Tohoto produktu bylo také použito pro správné ověření výsledných matematických výrazů, které se sypaly z nově implementované projektu. Poslední stránky této publikace představují celkové vyhodnocení implementace a zabývají se dalšími možnostmi programového rozšíření práce. Projekty na téma tohoto typu mohou být velmi rozsáhlé a stále budou existovat další a další možnosti pro jejich rozšíření. 2

2. Teorie o gramatikách 2.1. Základní pojmy teorie jazyků a gramatik Formální jazyky Abeceda je konečná množina symbolů. Řetězcem nad danou abecedou rozumíme konečnou posloupnost symbolů abecedy. Prázdnou posloupnost symbolů nazýváme prázdný řetězec a označujeme písmenem ε. Množinu všech řetězců nad danou abecedou T (včetně prázdného řetězce) označíme. Tato množina je vždy nekonečná. Množinu všech neprázdných řetězců nad abecedou T označíme. Platí, že =. [1/7] Na množině řetězců je definována operace zřetězení takto: Jsou-li x a y řetězce nad T, pak připojením řetězce y za řetězec x vznikne řetězec xy. Prázdný řetězec se chová vzhledem k operaci zřetězení jako jednotkový prvek: = =. [1/7] Délku řetězce x (počet znaků, kterými je tvořen) označíme. Platí, že 0, =0. [1/7] Formální jazyk L nad abecedou T je libovolná podmnožina množiny všech řetězců nad abecedou T, tj.. S formálními jazyky můžeme proto provádět množinové operace sjednocení, průnik a rozdíl. [1/7] Definice gramatiky Gramatika pro specifikaci jazyka L používá dvou konečných disjunktních množin symbolů: a) množiny neterminálních symbolů, b) množiny terminálních symbolů. Neterminálních symbolů se používá k označení syntaktických celků (též metajazykové proměnné, syntaktické kategorie). [1/8] Množina terminálních symbolů je abeceda, nad kterou je definován jazyk L. [1/8] Gramatika je čtveřice G=(N, T, P, S), kde N je konečná množina neterminálních symbolů, T je konečná množina terminálních symbolů ( = ), P je konečná podmnožina množiny.., (element, z P zapíšeme a nazveme pravidlo), S je počáteční symbol gramatiky (též větný nebo startovací symbol). [1/8] Obsahuje-li množina pravidel pravidla tvaru:,,,, tj. pravidla se stejnou levou stranou, pak pro zkrácení použijeme zápisu:. [1/8] 3

Klasifikace gramatik Podle tvaru pravidel můžeme gramatiky klasifikovat. Nechť G=(N, T, P, S) je gramatika. Říkáme, že G je: 1. Neomezená, jestliže odpovídá definici gramatiky. 2. Kontextová, jestliže každé pravidlo z P má tvar, kde,,,. 3. Bezkontextová, jestliže každé pravidlo má tvar, kde,. 4. Regulární, jestliže každé pravidlo má tvar nebo, kde,,. Výjimku tvoří pravidlo v případě, že S se neobjeví na pravé straně žádného pravidla. [1/10] Každá regulární gramatika je bezkontextová. Každá bezkontextová gramatika je kontextová. Každá kontextová gramatika je neomezená. [1/11] 2.2. Regulární jazyky Nejmenší množina jazyků, která obsahuje všechny konečné jazyky a jazyky vzniklé pomocí operací sjednocení, součinu a iterace, je množina všech regulárních jazyků. [1/15] Regulární jazyk je potom prvkem množiny regulárních jazyků. Pro definici regulárních jazyků jako množin řetězců můžeme použít několik metod: 1. výpočet (hodí se pro konečné jazyky s malou mohutností), 2. množinový zápis (hodí se pro jazyky s jednoduchou strukturou řetězců), 3. regulární gramatiky, 4. konečné automaty, 5. regulární výrazy. [1/15] Regulární gramatiky, konečné automaty a regulární výrazy jsou univerzální formální systémy a lze pomocí nich popsat všechny regulární jazyky. Přitom je důležité, že rozsah takové formálního popisu je vždy konečný. [1/15] Gramatiky generující regulární jazyky Pro generování regulárních jazyků je možno použít tyto gramatiky: 1. pravé regulární gramatiky, 2. pravé lineární gramatiky, 3. levé regulární gramatiky, 4. levé lineární gramatiky. Tyto gramatiky se liší pouze tvarem pravidel. [1/15] 4

Gramatika G=(N, T, P, S) se nazývá (pro,,, ): 1. pravá regulární gramatika, jestliže pravidla v P mají tvar: v případě, že S není na pravé straně žádného pravidla, 2. pravá lineární gramatika, jestliže pravidla v P mají tvar:, 3. levá regulární gramatika, jestliže pravidla v P mají tvar: v případě, že S není na pravé straně žádného pravidla, 4. levá lineární gramatika, jestliže pravidla v P mají tvar:. Jazyky generované těmito gramatikami jsou regulární jazyky. [1/16] Všechny gramatiky pro generování regulárních jazyků mají tyto společné vlastnosti: 1. V každém pravidle je na pravé straně nejvýše jeden neterminální symbol. 2. Neterminální symbol je buď jen na začátku nebo jen na konci pravé strany všech pravidel gramatiky. [1/16] Bezkontextová gramatika G=(N, T, P, S) je bez ε-pravidel, když 1. P neobsahuje žádná ε-pravidla, nebo 2. P obsahuje jediné ε-pravidlo tvaru a S se nevyskytuje na pravé straně žádného pravidla v P. Regulární gramatiky neobsahují ani jednoduchá pravidla ani ε-pravidla. [1/17] Konečné automaty Deterministický konečný automat M je pětice =,,,,, kde Q je konečná množina vnitřních stavů, T je konečná vstupní abeceda, δ je zobrazení z do, je počáteční stav, F Q je množina koncových stavů. Deterministický konečný automat pracuje tak, že provádí posloupnost přechodů. Přechod je určen stavem, ve kterém se automat nachází a symbolem, který je čten ze vstupního řetězce. Při přechodu přejde automat do nového stavu a přečte jeden vstupní symbol. Čtení vstupních symbolů se provádí zleva doprava počínaje nejlevějším symbolem vstupního řetězce. [1/27] 5

Abychom mohli určit budoucí chování deterministického konečného automatu, potřebujeme znát: a) stav, ve kterém se automat právě nachází, b) zbylou část vstupního řetězce, kterou dosud automat nepřečetl. Tuto dvojici údajů nazýváme konfigurací automatu. [1/27] Nedeterministický konečný automat M je pětice =,,,,, kde Q, T,, F je stejné jako u deterministického konečného automatu, δ je zobrazení z do množiny podmnožin. Podstatný rozdíl oproti deterministickému konečnému automatu spočívá v tom, že, je množina stavů místo jednoho stavu. [1/31] V konečném automatu se mohou vyskytovat stavy, které při jeho aplikaci nejsou potřebné. Jedná se o stavy, které se nazývají nedosažitelné a zbytečné tyto stavy můžeme vynechat. [1/32] Jazyky přijímané konečnými automaty, jsou regulární jazyky. Je proto možné sestrojit konečné automaty pro jazyky vzniklé operacemi sjednocení, součinu a iterace. Dále je možné sestrojit konečný automat pro doplněk jazyka a průnik dvou jazyků. Pomocí těchto operací je možné postupnými kroky sestrojit konečný automat, který přijímá jazyk definovaný s použitím uvedených operací.[1/57] Regulární výrazy Regulární výraz V nad abecedou A je definován takto: 1.,, jsou regulární výrazy pro všechna. 2. Jsou-li, regulární výrazy nad A, pak: a) + (sjednocení, alternativa), b). (zřetězení) c) (iterace) jsou regulární výrazy nad A. [1/70] 2.3. Bezkontextové jazyky Bezkontextové gramatiky Ze čtyř typů gramatik v Chomského klasifikaci jsou bezkontextové gramatiky nejzajímavější z hlediska použití v oblasti konstrukce překladačů programovacích jazyků. Význam bezkontextových gramatik je dám těmito faktory: 6

1. Bezkontextové gramatiky je možno použít pro popis převážné většiny syntaktických struktur programovacích jazyků a dalších jazyků, které se používají při práci s počítači, a jsou často používány jako prostředek pro popis syntaxe takových jazyků v různých publikacích. 2. Jsou známy algoritmy, které umožňují efektivně analyzovat věty bezkontextových jazyků, tj. jazyků generovaných bezkontextovými gramatikami. [1/118] Syntaktická analýza je proces, jehož cílem je zjištění, zda daný řetězec je generován danou gramatikou G a dále zjišťění, jaká je struktura tohoto řetězce. Pro praktické účely požadujeme, aby syntaktická analýza skončila po konečném počtu kroků, to znamená, aby syntaktický analyzátor, tj. systém provádějící syntaktickou analýzu, byl algoritmem. [1/118] Normální tvary bezkontextových gramatik Bezkontextová gramatika může být transformována tak, aby její pravidla měla předepsaný, tzv. normální tvar bezkontextová gramatika podle Chomského a podle Greibachové. V gramatice, která je v normálním tvaru podle Chomského, obsahují pravé strany pravidel nejvýše dva symboly. V gramatice, která je v normálním podle Greibachové, začíná pravá strana každého pravidla terminálním symbolem. To znamená, že gramatika není rekurzivní zleva, což má praktický význam při některých metodách syntaktické analýzy. [1/124] Bezkontextová gramatika G=(N, T, P, S) je v normálním tvaru podle Chomského, jestliže každé pravidlo v P má jeden z následujících tvarů: 1. pro,,. 2. pro,. 3. Jestliže, pak je pravidlo v P a S se nevyskytuje na pravé straně žádného pravidla. [1/124] Neterminální symbol A v bezkontextové gramatice G=(N, T, P, S) nazveme rekurzivní, jestliže existuje derivace pro nějaké α a β. Jestliže =, pak A nazveme symbol rekurzivní zleva, podobně jestliže =, pak A nazveme symbol rekurzivní zprava. [1/126] Gramatiku s alespoň jedním neterminálním symbolem rekurzivním zleva (zprava) nazveme rekurzivní zleva (zprava). Gramatiku, ve které je alespoň jeden neterminální symbol rekurzivní, nazveme rekurzivní. [1/126] 7

3. Popis problému Projekt Fake Game, do kterého je určena implementace modulu umožňujícího zjednodušení matematických výrazů generovaných hybridními induktivními modely, slouží jako nástroj pro přirozený vývoj získání výsledných dat (Data Mining). Fake Game ve své vnitřní implementaci zahrnuje několik metod pro předzpracování zadaných dat, jejich optimalizaci a vizualizační metody zaměřené na tok získaných dat z vývojového učícího se procesu. Získaní nových dat (neboli znalostí) z velkého množství celkově zpracovaných údajů se provádí automaticky. [6] Obdržená výsledná data, zastoupená matematickými výrazy, jsou poměrně často ještě příliš rozsáhlé matematické rovnice plné velkého množství proměnných a rozložených jednoduchých matematických operací, které je možné upravit do přehlednější a kratší výsledné podoby. Další zjednodušení výstupních rovnic bude realizováno zjednodušujícím modulem, který je stěžejním tématem zadané bakalářské práce. Modul upraví rovnici do jednodušší podoby (pokud to bude podle matematických pravidel možné) a výsledek předá zpět do hlavního zpracovatelského procesu Fake Game, ze kterého byl modul na zjednodušení aktuálního výstupu zavolán. Zjednodušení vstupního matematického řetězce se provede podle základních matematických pravidel, která budou implementována v tomto nově vytvořeném zjednodušovacím modulu. Součástí modulu bude muset být i syntaktický analyzátor, sloužící k nalezení jednotlivých matematických prvků jako jsou operátory, závorky, čísla, proměnné a jiné prvky, které se vyskytují ve výrazech generovaných hybridními induktivními modely projektu Fake Game. Implementace zjednodušovacího modulu bude provedena ve stejném duchu jako již existující moduly v současném projektu Fake Game. Pro názvy tříd se bude používat základní anglická terminologie, protože na projektu spolupracují i anglicky hovořící vývojáři. Je doporučeno tuto jazykovou konvenci dodržovat i v ostatních částech tvořené implementace. Mezi důležité rady pro vývoj určitě patří i vhodně umístěné komentáře, kde jejich existence 8

bude oceněna jiným vývojářem, který se bude danou problematikou více zabývat (ať již z důvodu opravy špatně provedených akcí či pokračování v dalším vývoji). Určitě dobře poslouží i samotnému tvůrci programu po delší časové odmlce, aby zpětně nalezl své myšlenky a postupy pro takto realizovaný algoritmus. Zjednodušovací modul bude mít podobu samostatného balíku (package) a vstupní data představuje pouze jeden řetězec, který obsahuje matematickou rovnici v textovém tvaru. Návratovou hodnotou z tohoto modulu bude opět jeden řetězec představující matematickou rovnici, ale tentokráte již upravenou podle základních matematických pravidel do výsledné jednodušší podoby, pokud bude možné vstupní výraz zjednodušit. V nově vytvořeném balíku by se mělo nacházet více tříd, které budou v sobě obsahovat samostatná tematická zaměření vedoucí k řešení celkového problému. Není doporučeno, aby celá implementace byla provedena jen v rámci jedné třídy dojde ke vzniku nepřehlednosti a špatné orientace v celkovém významu jednotlivých metod uvnitř modulu. Samotná realizace může být rozčleněna do několika základních kroků, které v první fázi představuje syntaktická analýza vstupu a jeho uložení do struktur vhodných pro další zpracování. Takto uložená struktura analyzovaného vstupního řetězce by měla být předána do funkce pro zjednodušení podle základních matematických pravidel, která opět uloží zjednodušený výraz do vhodné struktury. Posledním krokem modulu se rozumí převedení upraveného matematického výrazu z uložené struktury do výsledného výstupního řetězce, který je předán funkci, která vyžadovala zjednodušení. 9

4. Analýza a návrh řešení Pro vlastní vývojovou tvorbu práce se doporučuje použít vývojové prostředí IntelliJ IDEA 7.0., které je určeno nejen pro programovací jazyk JAVA. Tento vývojový nástroj je možné stáhnout ze stránek www.jetbrains.com v sekci download. Produkt je bez registrace použitelný v plném rozsahu funkčnosti po dobu 30 dní. Pro studijní účely jsou ve škole k dispozici aktivační údaje k registraci tohoto produktu (www.civ.cvut.cz). Vývojové prostředí Intellij IDEA je svou funkční strukturou velmi podobné ostatním vývojovým produktům tohoto typu, takže ovládání jednotlivých funkcí je přibližně stejné. Jako velmi dobrou vlastnost vzhledu se dají ocenit postranní funkční záložky představující nejčastěji používané operace při vývoji a ladění vytvářeného programu. 4.1. Projekt Fake Game Pro začátek bude vhodné představit projekt Fake Game a jeho ovládání, aby se uživateli povedlo dostat k hlavnímu tématu této bakalářské práce. Jelikož modul pro zjednodušení výrazu vyžaduje na svém vstupu řetězec, tak si ukážeme postup krok po kroku, jak tyto vstupní data získáme. Po spuštění projektu Fake Game se nám zobrazí základní okno aplikace, ve kterém jsou vykresleny všechna podstatná podokna s výsledky a nabídky k jejich ovládání. Jejich obsah je doposud prázdný, jelikož ještě nebyla vybrána a zpracována žádná vstupní data. Vstupní data se načítají z externího souboru pomocí operací v hlavním menu aplikace: FILE LOAD. V okně pro načtení souboru z disku nalezneme soubor s příslušnými daty, která mají být použita pro běh aplikace Fake Game. Po načtení souboru se doplní v hlavním okně aplikace podokna s popisem INPUTS a OUTPUTS, které byly doposud prázdné (viz. Obr. 1). Zde jsou zobrazeny všechny načtené vstupní proměnné ze souboru. Po tomto načtení vstupních hodnot je možné nastavit důležitost jednotlivých vstupních parametrů pomocí šoupátek, které jsou umístěny pod jednotlivými vstupními proměnnými. Toto nastavení můžeme vynechat a rovnou přejít na spuštění generujícího algoritmu, který vytvoří základní model. Spuštění se provede přes hlavní menu: MODEL CREATE GAME MODEL. Po tomto úkonu se ještě objeví dotaz, jestli chceme provést konfiguraci modelu 10

pro vygenerování struktury dat plně postačí odpověď NO. Nyní se spustí časově náročnější výpočet nového modelu ze zadaných vstupních parametrů. Obr. 1: Základní okno aplikace Fake Game po otevření souboru s daty Výpočet je doprovázen kontrolními textovými výpisy a grafickým znázorněním v podokně SDI, takže máte neustále přehled, že se něco provádí a algoritmus je v provozu. Dokončení výpočtu se projeví v zobrazení podokna SDI. Poté je již možné vybrat a zobrazit konkrétní vygenerovaný model. Toto se provede v základním okně vpravo dole, kde se nachází podokno MODEL. Z listu možných vygenerovaných modelů si vybereme jeden model, který chceme zobrazit. Kliknutím na SHOW EQUATION se zobrazí okno s výslednou vygenerovanou rovnicí, kterou bude potřeba pomocí nového modelu zjednodušit. Místo zobrazení jen výsledné rovnice je vhodnější a mnohem přehlednější zobrazit celkový vygenerovaný model. V menu hlavního okna vybereme MODEL DISPLAY 11

STRUCTURE OF MODEL IN GUESS. Struktura vytvořeného modelu se zobrazí v nově otevřeném okně v podobě spojového grafu (viz. Obr. 2). Ve vrchní části okna jsou vykresleny vstupní parametry.a pod nimi se zobrazí body, které představují částečné výsledky výpočtu. Čáry mezi body zachycují postupnou cestu použití mezivýsledků ve výpočtu. Bod, který se od ostatních liší svou velikostí, obsahuje výslednou vygenerovanou hodnotu. Obr. 2: Struktura vygenerovaného modulu Jak již bylo řečeno výše, jednotlivé body zastupují výsledek konkrétního výpočtu, ať se jedná o mezihodnotu nebo výslednou hodnotu. K prohlížení těchto výsledků postačí dvojklik na vybraný bod a otevře se nové okno s vypsaným výsledkem (viz. Obr. 3). Tento výstup bude vstupní proměnnou pro zjednodušovací modul, který je hlavním úkolem bakalářské práce. Úkolem bude i vhodná změna grafické úpravy okna, aby použití akcí k zjednodušení bylo intuitivní. Zjednodušený výraz bude přehledně zobrazen ve stejném okně. 12

Grafická struktura zobrazeného okna s výsledkem výpočtu je programově provedena v souboru EquationWindow.java, který se nachází v adresáři src/game/model. Do tohoto souboru bude potřeba přidat další grafické prvky, aby bylo dosaženo odpovídajícího vzhledu výsledného okna. Obr. 3: Okno s vygenerovanou rovnicí 4.2. Návrh struktury implementace Zjednodušovací modul se bude skládat z více částí programu, které budou rozděleny do samostatných tříd. Základní třídou bude CORRECTION, ve které se bude odehrávat samotný proces zjednodušení matematických prvků. Dříve než půjde zadaný výraz zjednodušit, bude potřeba vstupní text analyzovat a rozložit na jednoduché matematické prvky. Tento proces bude obsluhovat třída GRAMMAR, která bude úzce a často spolupracovat s třídou PARSER. Třída GRAMMAR v sobě implementuje všechna gramatická pravidla odpovídající všem možnostem různých výskytů matematických prvků ve vstupním řetězci. Pravidla bude potřeba navrhnout jednoduchá, aby se implementace příliš nekomplikovala a taky zůstala možnost pro snadné přidání dalších pravidel v budoucnu, pokud to bude potřeba. Algoritmus na základě těchto gramatických pravidel bude rozlišovat jednotlivé vstupní znaky a provede jejich uložení do vhodné reprezentace datové struktury. Třída PARSER bude ze vstupního řetězce načítat jednotlivé vstupní znaky a provádět na nich syntaktickou analýzu k odlišení základních prvků a operací. Základním prvkem se rozumí číslo, proměnná, závorky, základní matematické operace ( + * / ). Po načtení jednoho kompletního matematického elementu jej předá třídě GRAMMAR, které rozhodne o dalším postupu algoritmu. 13

Kontrolní mezivýsledky a pomocné výstupy bude potřeba nějakou metodou zobrazit. Pro tento účel se vyvine samostatná třída OUTPUT, která bude zajišťovat nejen kontrolní vývojové výpisy, ale i celkový výstup z modulu zjednodušení. V této třídě budou implementovány všechny výstupu z modulu zjednodušení, aby se udržovaly na jednom centrálním místě. Z vnějšku bude viditelná pouze třída GRAMMAR, které se bude předávat vstupní řetězec. Ta jej předá třídě PARSER, která si ho uloží a bude na něm postupně provádět analýzu znaků. Po načtení matematického prvku, předá řízení třídě GRAMMAR. Ta získaný prvek uloží a na jeho základě rozhodne o dalším postupu algoritmu a opět předá řízení třídě PARSER. Toto chování se opakuje, dokud nebude třídou PARSER přečten celý zadaný řetězec. Třída GRAMMAR postupně ukládá načtené prvky a po ukončení třídy PARSER, je předá třídě CORRECTION. Třída CORRECTION přijme předaná předzpracovaná data a bude se snažit o jejich zjednodušení podle implementovaných matematických operací. Základem budou jednoduché operace k sečtení, rozdílu, součinu a podílu čísel či proměnných. Po dosažení konce úprav bude třídě GRAMMAR předáno řízení spolu se zjednodušeným matematickým výrazem. Výstupní řetězec se získá z třídy GRAMMAR, která požádá třídu OUTPUT o převod datové struktury matematických prvků na řetězec, který je vhodný k exportu z modulu zjednodušení. 4.3. Návrh matematického zjednodušení Nově implementovaný modul zjednodušení matematických výrazů generovaných induktivními modely v projekt Fake Game, by se měl zaměřit na zjednodušení základních matematických operací. Složitější operace budou rozeznány, ale zatím nebudou řešeny návrh další fáze vývoje tohoto modulu. Složitějšími úpravami, které nejsou v popisu současné fáze vývoje, se rozumí především výrazy EXP( ) a 1/(1+exp( )). Dále nebudou prováděny základní zjednodušovací operace s nimi. Tím se rozumí žádné sčítání, odčítání, násobení a dělení. Výjimku bude tvořit pouze operace násobení výrazu EXP( ) či 1/(1+exp( )) samostatným číslem. Dále se nebude provádět násobení mezi závorkami, které mají dva a více členů. 14

Cílem této implementační bakalářské práce je vytvořit základ modulu pro zjednodušení matematických výrazů, které se skládají ze základních jednoduchých matematických operací. Jednoduché operace se provádění na stejné úrovni, tj. v rámci stejné závorky. Nesmí se stát, aby prvek na konci závorky k sobě připočítal odpovídající prvek mimo závorku, pokud závorka ještě nebyla zjednodušena a odstraněna. Dále musí zůstat možnost pro pozdější snadné rozšíření modulu o složitější výrazy a operace s nimi spojené. Jednoduchými matematickými zjednodušovacími operacemi se rozumí: sčítání na stejné úrovni mezi čísly a stejnými proměnnými vedle sebe odčítání na stejné úrovni mezi čísly a stejnými proměnnými vedle sebe násobení dvou prvků na stejné úrovni kombinace čísla a proměnné nebo číslo a výraz EXP( ) či 1/(1+exp( )) dělení dvou prvků na stejné úrovni kombinace čísla a proměnné roznásobení závorky číslem vydělení závorky číslem úprava závorky záporným znaménkem (může se vyskytnout před závorkou) odstranění závorek, není-li před či za závorkou znaménko krát či děleno proměnné budou vypisovány bez závorek kolem sebe zjednodušení bude postupovat od nejvnitřnější závorky směrem ven Tyto základní operace by měly být implementovány a připraveny k použití do projektu Fake Game, kde je bude potřeba na různých vstupech otestovat a popř. přidat poznámky pro další vývoj modulu. 4.4. Podpora pro nové funkce Po úspěšné první fázi vývoje bude časem zahájen vývoj navazující na tuto práci, který bude implementovat nedostatky prvotního návrhu a přidávat nové zjednodušovací funkce. 15

Přidání nové funkčnosti bude již jednodušší, protože základní operace budou vytvořeny a provede se jen rozšíření modulu zjednodušení, které bude spočítat v připsání nových metod, které rozšíří stávající algoritmy, které byly vytvořeny v první fázi. Při nalezení nového prvku ve vstupním matematickém výrazu, který neprojde syntaktických analyzátorem, je potřeba upravit algoritmus načítající vstup znak po znaku. Tento algoritmus je umístěn ve třídě PARSER, kde se načtený znak porovnává se všemi možnostmi na vstupu pomocí SWITCH větvení. Načtený znak se přidá k ostatním načteným znakům v předchozích krocích, dokud není složen kompletní jeden matematický prvek (zaručuje SWITCH v cyklu). Nově načtený prvek je potřeba přidal i do gramatických pravidel, která odpovídají složení vstupního řetězce. Implementace je uskutečněna ve třídě GRAMMAR, kde jednotlivá pravidla jsou zastoupena SWITCH přepínačem. K připsání nového pravidla plně postačí inspirace v ostatních, již hotových, pravidlech. Ale ještě je potřeba takto ověřený nový vstupní prvek uložit do vnitřní struktury úspěšně načtených dat. To si vyžádá chvilku k zamyšlení, aby nebyl zkomplikován samotný algoritmus pro vlastní zjednodušení této struktury dat. Pro uložení prvku je využívána třída ITEM, která v sobě implementuje datovou strukturu jednoho prvku. Po přidání nového prvku do vnitřní reprezentace uloženého vstupního řetězce, nesmíme zapomenout o tento prvek rozšířit primární algoritmus na zjednodušení, který je uložen ve třídě CORRECTION. Podle charakteru nového elementu, musíme najít vhodné místo k implementaci odpovídajících matematických operací. Poslední částí, kde je potřeba při přidání nového prvku ještě něco zmodifikovat, je třída OUTPUT. Ta je využívána k převodu vnitřní datové reprezentace na výstupní řetězec. Jednotlivé prvky se postupně skládají do řetězce za sebe a při jejich převodu na text je využito informace o typu prvku (např. číslo, proměnná, exp výraz). 16

5. Realizace Zadaná práce se po celou dobu tvorby neustále vyvíjela a měnila svou tvář. Důvodem pro tyto změny byl neustále se zvětšující objem zdrojového kódu a jednotlivé třídy začaly praskat ve švech. Uvnitř tříd se objevovaly metody, které se ze začátku jevily jako neškodné a příliš nevyčnívaly z řady. Ale vývoj šel neustále dopředu a tyto v rohu krčící se metody nabíraly na svém objemu a postupně musely být vyčleněny do své vlastní třídy. Ve finálním stádiu vývoje modulu jsou k dispozici níže uvedené třídy. Všechny patří do balíku (package) simplify a v modulu zjednodušení jsou používány výhradně jen tyto třídy: Parser.java vstupní řetězec převádí na jednotlivé matematické prvky Grammar.java podle zadaných gramatických pravidel kontroluje převedené vstupní prvky a ukládá je do vnitřní datové struktury Item.java reprezentuje jednu položku vnitřní struktury Correction.java uložená data ve vnitřní struktuře se snaží podle algoritmu zjednodušit Output.java data z vnitřní struktury převádí na výstupní řetězec GramException.java ošetření výjimek v průběhu činnosti modulu Nyní se s nimi podrobněji seznámíme a každé třídě věnujeme jednu podkapitolu. 17

5.1. Parser Z názvu třídy mnohého bystřejšího čtenáře napadne, že se jedná o implementaci metod založených na načítání vstupu neboli parsování. Analyzátor načte jeden vstupní znak a snaží se ho přiřadit ke specifickému matematickému prvku. Konstrukční metoda této třídy je volána z třídy Grammar, která Parser inicializuje předaným vstupním řetězcem. Na předaný vstupní řetězec je v těle konstruktoru zavolána metoda vymazmezery() ze vstupního řetězce odstraní všechny mezery, jelikož by při parsování mohly překážet a zbytečně by komplikovaly implementaci analyzátoru. Hlavní funkčnost analyzátoru je soustředěna v metodě analyza(), kde je v cyklu opakován příkaz SWITCH, který rozhoduje o charakteru jednotlivých znaků. Cyklus běží do té doby, dokud není načten jeden úplný matematický prvek. Tímto prvkem jsou myšleny matematické operátory, čísla, proměnné a výrazy exp. Takto načtený prvek je předán třídě Grammar a jeho další zpracování bude popsáno v následující podkapitole. Třída Parser v sobě definuje velké množství konstant, které se hojně používají v celém zjednodušovacím modelu. Jedná je o textovou reprezentaci čísel (např. kwplus, kwkrat, kwcislo, kwexp, ) bližší informace naleznete ve zdrojových kódech, zde je zbytečné zabíhat do detailů. Implementováno je i několik pomocných metod, které svým rozsahem dosahují několika málo řádků a je zbytečné rozebírat je všechny. Ve zkratce zmíním metody: srovnej() Grammar předá očekávaný vstupní symbol, který se porovná s načteným symbolem ze vstupního řetězce nactisymbol() spouští metodu analyza() k načtení prvku 18

5.2. Grammar Konstruktor Grammar() aktivuje základní objekty, které jsou potřeba k správné funkčnosti modulu zjednodušení. Taky inicializuje datovou strukturu, do které se ukládá rozparsovaný vstupní řetězec ve vhodném tvaru, ale o tom až ve třídě Item. Do package simplify se řízení programu předává právě přes tuto třídu. Řízení přebírá metoda simplify() představující hlavní komunikační uzel celého modulu zjednodušení. Metoda simplify() není ani na 10 řádků, ale postupně v sobě volá všechny důležité metody potřebné k celkovému zjednodušení zadaného matematického výrazu. Jako první je potřeba spustit analýzu vstupu podle gramatických pravidel metoda start() ve třídě Grammar (bude vysvětlena v zápětí). Pak následuje hlavní zjednodušovací metoda upravcelepole() ze třídy Correction. Po úpravě prvků již zbývá učinit poslední krok metoda getvystup() ze třídy Grammar. Nyní se vrátíme k popisu jednotlivých metod uvnitř třídy Grammar a začneme metodou start(), o které padla zmínka na začátku této podkapitoly. Metoda v sobě implementuje gramatická pravidla a její název odpovídá prvnímu z těchto pravidel. Metoda volá další metody, které svými názvy odpovídají názvům levých stran gramatických pravidel. Uvnitř těchto gramatických metod se provádí volání do třídy Parser za pomocí metod nactisymbol() a srovnej(). Dalšími gramatickými metodami jsou implementace pravidel v podobě F() a E(). K nim stačí jen říci, že implementují gramatická pravidla a volají metody nactisymbol() a srovnej() ze třídy Parser. Taky se starají o uložení načteného prvku pomocí metody ulozf() ve třídě Grammar. Pokud se narazí na nesrovnalost mezi vstupním řetězcem a gramatickými pravidly, je algoritmus ukončen výjimkou, která je obsluhována ve třídě GramException. Po úspěšné analýze celého vstupního řetězce jsou jednotlivé matematické prvky uloženy ve vnitřní datové struktuře, která je využita k dalšímu zpracování. Po zdárném ukončení metody start() se vrátí řízení metodě simplify(), která zavolá metodu upravcelepole() ze třídy Correction, kde se provádí zjednodušení matematického výrazu. 19

5.3. Item Načtené matematické prvky se musí nějakým způsobem ukládat a za tímto účelem je implementována třída Item. V konstruktoru třídy Grammar je provedena inicializace statického pole. Jeho velikost je odvozena od délky vstupního řetězce, který je předán ke zjednodušení, podle následujícího vztahu: vstup.length() / 6 + 3. Tento vztah byl určen experimentálně. Někomu se možná nebude zdát, že je pro uložení vstupního řetězce použito statické pole místo dynamického. Pro toto řešení jsem se rozhodl, protože práce se statickým polem se mi jevila jako snadnější řešení hlavně když jsem potřeboval předávat indexy a rychle po pohybovat v takto vytvořeném poli prvků. Určitě to šlo implementovat i do dynamického pole, ale necháme námět pro další vylepšení. Při zjednodušování se některé prvky ze statického pole přesunují do dynamického, ale to bude vysvětleno později. Nyní se zaměříme na datovou strukturu jedné položky pole, která je zastoupena objektem v podobě třídy Item. Její vzhled je následující: int level hladina zanoření prvku v závorkách, u prvku mimo závorky je 0 int otviraci počet otvíracích závorek těsně před prvkem ( >= 0), def. 0 int zaviraci počet zavíracích závorek těsně za prvkem ( >= 0), def. 0 int symbol určuje matematický typ prvku (např. kwcislo, kwexp, ) int oppred určuje matematický typ operace před prvkem (např. kwplus, ) String promenna uložen načtený text z analyzátoru (název proměnné) či float hodnota převedená číselná hodnota, defaultně 1.0 int mocnina proměnné mohou být umocněny, defaultně 1 Item dalsi odkaz na první dynamický prvek Item zavorka odkaz z dynamického prvku na další dynamický prvek Struktura uložených dat se v průběhu implementace stále měnila. S přibývajícími operacemi na zjednodušení byla potřeba uložení nových informací nezbytností. V dalším vývoji zjednodušovacího modulu bude nejspíše nutné zvětšit tuto strukturu o další datové položky. 20

5.4. Correction Základní zjednodušovací matematické operace implementuje třída Correction. Spuštění této třídy je závislé na úspěšném dokončení analýzy vstupního řetězce a jeho uložení do vnitřní datové struktury. Z metody simplify() ve třídě Grammar je volána metoda upravcelepole(item[]). Jako parametr se jí předá upravený vstupní řetězec v podobě pole. Uvnitř metody upravcelepole() je zavolána metoda upravpole(level, index), kde vstupní parametr level představuje úroveň zanoření prvku v závorkách a parametr index pozici prvku v poli. Vstupní parametry byly zvoleny dva, aby se snadněji hlídal algoritmus na zjednodušování zanořených závorek do sebe. Metoda upravpole(level, index) rekurzivně volá sama sebe podle toho, jestli vlastnosti právě načteného prvku neodpovídají předaným parametrům. Pokud aktuální prvek má level = 4 a zavolaná metoda upravpole(2, 8) je s těmito parametry, tak se provede na stejném prvku zavolání upravpole(3, 8) a pak ještě jednou upravpole(4, 8). Volání je provedeno vícekrát, protože prvek na index = 8 má před sebou nejspíše dvě závorky a bude potřeba nejdříve zjednodušit závorku na vyšší úrovni a pak se zpětnou rekurzí algoritmus dostane i na úroveň 3, kterou by jinak přeskočil - to by vedlo k selhání zjednodušení. Metoda upravpole() v sobě soustřeďuje všechny potřebné metody k zjednodušení prvků na stejné úrovni, mezi nimiž se nenachází žádný jiný prvek s vyšší úrovní. Pokud se tam stane a takový prvek se najde, zavolá se na něj metoda upravpole(aktualnilevel + 1, index) zvětšení level o jedničku bylo popsáno výše. Po jeho zjednodušení se bude opět pokračovat na předchozí úrovni zanoření. Postupně se k zjednodušení použijí tyto algoritmy: upravnasobeni(index) násobení na stejné úrovni mezi dvěma prvky vedle sebe upravsoucet(start, stop) sečtení prvků v závorce ohraničené těmito indexy upravexppredzavorkou(start, stop) závorka za EXP je přesunuta do dynamického pole, aby indexy prvků na stejné úrovni tvořily posloupnost upravnasobenimimozavorku(start, stop) předány parametry závorky a algoritmus v sobě zahrnuje další metody, které by měly pomoci ve snížení závorky o jednu úroveň 21

Metoda upravnasobenimimozavorku(start, stop) je zavolána až po celkově možném zjednodušení uvnitř závorky. Parametry představují první a poslední index prvku závorky. Proto je důležité, udržovat si posloupnost prvků ze stejné úrovně za sebou. Je to založeno na logickém principu, že první se musí zjednodušit vyšší úroveň a pak se teprve může přejít na zjednodušování nižší úrovně. Tato metoda upravuje rozšíření závorky jedním prvkem (číslo, proměnná). Uvnitř této metody se volají další zjednodušující algoritmy: upravnasovenizaporpredzavorkou(start, stop) před závorkou je znaménko mínus a tedy je potřeba celou závorku roznásobit číslem -1 upravnasovenipredzavorkou(start, stop) řeší roznásobení závorky číslem nebo proměnnou umístěnou před závorkou upravnasovenizazavorkou(start, stop) řeší roznásobení či vydělení závorky číslem nebo proměnnou, která je za závorkou Tyto metody, na zjednodušení mimo závorku, vracejí speciálně definovanou konstantu (LEVEL_KONEC), která představuje indikaci, že se závorku některou ze zjednodušovacích metod podařilo odstranit a tudíž zjednodušení upravpole(level, index) se ukončí a bude se zpětně pokračovat v činnosti upravpole(level-1, index) na předchozí úrovni. Při zjednodušování prvkem mimo závorku, se musí dát velký pozor na to, aby prvek byl jen o jednu úroveň níže (může se stát, že je i o více úrovní níže některé závorky končí současně i tři odrazu), jinak porušíme matematické pravidlo, aby se zjednodušování provádělo od nejvyšší úrovně k úrovní nižší. Toto jsou všechny zjednodušovací metody, které jsou doposud implementovány a pokud se prvek dostane mimo tyto metody, tak modul s největší pravděpodobností skončí chybou. Po zjednodušení, které vedlo k snížení o prvek (např. sečtením dvou čísel vzniklo číslo jen jedno), je potřeba zbytečný prvek odstranit - odstrannull(index), kde index představuje prvek, který se zruší. Zrušení probíhá tak, že prvky v poli od INDEX+1 do konce, se posunou na pozici o jednu menší. Při upravnasobeni(index) se násobí dva prvky vedle sebe na pozicích INDEX a INDEX+1. Jestli násobení probíhá mezi dvěma stejnými proměnnými, jejich mocniny se sčítají. Pokud dojde k násobení mezi různými proměnnými, násobí se jen jejich číselné hodnoty a jeden z prvků přejde do dynamického seznamu, umístěného v položce PRVEK[INDEX].DALSI na příslušném prvku (aby se zneklidněný prvek mohl odstanit). 22

Nyní se ještě vrátím k úpravě upravexppredzavorkou(start, stop), kdy závorka za výrazem EXP přejde na dynamické pole. Tento důvod přechodu na dynamické pole byl již zmíněn, ale raději dvakrát než špatně. Pokud se upravují závorky, tak jim předávám index START a STOP, které představují prvky na stejné úrovni. Tudíž nemůžu nechat neupravené prvky z vyšší úrovně ve statickém poli, kde by překáželi další v korektní matematické úpravě. Za tímto účelem byly přidány dynamické prvky DALSI a ZAVORKA. Pokusím se to vysvětlit na příkladu 1+(3*(EXP(A+5)-2) +4)-6 Nejvyšší úroveň má závorka (A+5), která již nejde zjednodušit, protože není implementována metoda na EXP. Jediné co jde, je přesunout obsah závorky do dynamického pole prvku EXP. Pak v prvku EXP bude ukazatel DALSI směřovat na přesunutý prvek A a ukazatel ZAVORKA zůstane NULL. Ale v závorce ještě zůstalo číslo 5. To je třeba taky přesunout a to za výraz A. Jelikož A a 5 byly spolu v závorce, tak z prvku A bude ukazatel DALSI směřovat na NULL a ukazatel ZAVORKA na přesunutý prvek 5. Získali jsme úpravu pole, po které můžeme pokračovat v dalším zjednodušení. 1+(3*(EXP-2) +4)-6 na EXP je navázáno dynamické pole 1+(3EXP-6 +4)-6 roznásobení trojkou 1+(3EXP-2)-6 sečtení čísel -6+4 1+3EXP-2-6 odstranění závorky -1 +3EXP-6 sečtení čísel 1-2 -7+3EXP sečtení čísel -1-6, konec zjednodušení Na výraz EXP zůstal navázán dynamický seznam, který nám nebránil ve zjednodušení. Tímto příkladem jsem se snažil naznačit význam dynamických prvků DALSI a ZAVORKA. Pokud ukládám první prvek do dynamického pole prvku, který je ve statickém poli, tak přijde do položky DALSI (naznačuji tím, že je o úroveň mimo). Následující prvky ze stejné úrovně již na sebe ukazují pomocí ZAVORKA. 23

5.5. Output Třída Output je implementačně nejmladší třídou, protože vznikla poměrně nedávnou. Důvodem k jejímu vzniku byla skutečnost, že výstupy se prováděly jak z třídy Grammar, tak i z Correction. V každé této metodě byly v podstatě úplně stejné algoritmy pro výstup a je problémové udržovat stejné funkce na dvou různých místech. Z tohoto důvodu vznikla třída Output, do které se metody pro výstup přenesly a obě třídy je využívají voláním stejné metody. Třída Output pod sebou shromažďuje všechny metody, které slouží k výstupu ať se jedná o kontrolní výpisy či o metody pro finální výstup zjednodušeného řetězce. Pro ladící výstup je použito statické metody void kontrolnivypis(string), která přímo vypíše zadaný text. Pro průběžný výstup pole prvků je připravena metoda void vypispoletemp(item[]). Pro získání finálního zjednodušeného řetězce se volá String getvystup(item[]). Obě metody pracují stejně (volají stejnou metodu String sestavvystup() na převod pole na řetězec), jen se liší v návratovém typu. Metoda pro průběžný výstup řetězec rovnou vypíše, zatímco metoda pro finální výstup předá řetězec metodě, která ji vyvolala. Metoda String sestavvystup() v cyklu prochází pole a jednotlivé prvky předává metodě String vypispolozku(item). Ta již projde strukturu získaného prvku a převede jej na řetězec. Při tomto převodu dochází k zaokrouhlování čísla na 3 desetinná místa. Zaokrouhlování (metoda String upravhodnotu(float)) je provedeno z důvodu, že při zjednodušení dochází k tvorbě čísel s velkým počtem desetinných míst, které ve výsledku vizuálně znehodnocují výstup. 5.6. GramException Třída pro zpracování výjimek, kde se z metody String tostring() získá vyvolaná hláška, která se snaží specifikovat, ve která části modulu k výjimce došlo a na jaké pozici pole se nachází prvek, který tuto výjimku vyvolal. 24

5.7. Gramatická pravidla Základní gramatická pravidla syntaktického analyzátoru jsou tvořena bez zbytečných a složitých pravidel, která by jen komplikovala jejich implementaci a znepřehledňovala jejich snadné použití. V modulu zjednodušení jsou zatím implementována níže uvedená pravidla, a jestliže se narazí na prvek, který je v rozporu s těmito pravidly či v nich není vůbec uveden, syntaktická analýza skončí chybou a bude ukončen i modul zjednodušení. Použitá gramatická pravidla: START C F E C proměnná = F číslo proměnná ( F E ) ( F E ) EXP( F E ) 1/(1+exp( F E )) ε E + F E F E * F E / F E ε Význam použitých symbolů v gramatických pravidlech: neterminální symbol START, C, F, E terminální symbol =, +,, *, /, ε, (, (, EXP(, 1/(1+exp(, ), )) číslo, proměnná (pseudo-terminální symboly) V gramatice jsou použity pseudo-terminální symboly, jejich význam je následující: číslo představuje klasické číslo složené z číslic (0-9) desetinným oddělovačem je tečka může se jednat o záporné číslo může být napsáno ve tvaru např. 1.65E-5 nebo 1.65e-5 25

proměnná začíná znaky a-z nebo A-Z dále pokračuje znaky a-z, A-Z, 0-9 nebo znakem podtržítko jiné znaky mimo výše uvedené nejsou podporovány 5.8. Začlenění modulu do projektu Projekt Fake Game je souborově velmi rozsáhlý a bez rady vedoucího projektu, bych nejspíše pěkně dlouho hledal konkrétní soubor, do kterého je potřeba přidat volání nově implementovaného modulu zjednodušení. Cílový soubor EquationWindow.java (adr. src/game/modul) v sobě obsahuje grafické prvky, které slouží k vykreslení nového okna a zobrazení požadované rovnice. Původní okno vzhledově vypadalo stejně jako okno s nově otevřenou rovnicí (Obr. 4), jen neobsahovalo tlačítko Simplify k zjednodušení, které bylo potřeba dodělat a navázat na něj akci k zavolání modulu pro zjednodušení. Zjednodušený výraz se zobrazí ve spodní polovině (Obr. 5). Obr. 4: Okno s nezjednodušeným matematickým výrazem Obr. 5: Okno se zjednodušeným matematickým výrazem 26

6. Testování Modul zjednodušení implementovaný do projektu Fake Game, je podroben testovacím akcím, které mají ověřit správnost jeho algoritmu na zjednodušení zadaného vstupního matematického výrazu. Testování bude probíhat stylem, že vstupní řetězec z projektu Fake Game bude zkopírován do jiné externí aplikace, která je na projektu Fake Game nezávislá. 6.1. Testování zjednodušení - Mathematica Jako externí aplikace, která je zvolena jako základní bezchybný zjednodušovací referenční modul, je využit software Mathematica od společnosti Wolfram Research. Použití tohoto softwaru bylo doporučeno vedoucím. Nebudu se zde zabývat popisem všech položek menu. Na to, co dělají, snadno přijdete sami. Pokusím se zde popsat ty funkce programu, které jsou potřeba pro řešení některých konkrétních zadání. Ale nejdříve k tomu, jak se vůbec zadávají výpočty. Založte si nový soubor (v programu se nazývají notebooky). Výpočty se zadávají do buněk. Zkuste napsat třeba 1+2. Potom stiskněte Shift+Enter. Stiskem Shift+Enter spustíte výpočet označené buňky. [7] Z tohoto rozsáhlého matematického programu je pro testovací účely využita jen jeho malá část příkaz Simplify. Takže si ukážeme, jak umí program zjednodušovat matematické výrazy. Slouží k tomu funkce Simplify nebo FullSimplify. Tyto funkce vyzkouší všechny možné matematické úpravy zadaného výrazu a potom zvolí tu nejjednodušší variantu. Rozdíl je mezi nimi jenom v rozsahu zkoušených matematických úprav. FullSimplify jich vyzkouší daleko více než Simplify, to znamená, že mnohdy najde ještě jednodušší podobu výrazu než Simplify, ale je časově náročnější. [8] Metoda Simplify se v Mathematice zapisuje ve tvaru: Simplify[matematický výraz] 27

Nyní můžeme přistoupit k vlastnímu testování nově implementovaného modulu zjednodušení. Testování bude probíhat na reálných matematických výrazech generovaných z aplikace Fake Game. Test 1: Jednoduché zjednodušení Obr. 6: Fake Game jednoduché zjednodušení Obr. 7: Mathematica jednoduché zjednodušení První základní jednoduché zjednodušení proběhlo mezi Fake Game (Obr. 6) a Mathematica (Obr. 7) v pořádku. Jediným rozdílem, který můžeme pozorovat, je odlišné pořadí prvků Mathematica řadí na první místa čísla a pak následují proměnné. 28

Test 2: Složitější zjednodušení s výrazem EXP Obr. 8: Fake Game - složitější zjednodušení s výrazem EXP Obr. 9: Mathematica - složitější zjednodušení s výrazem EXP Druhý test se složitějším zjednodušením s výrazem EXP již nedopadl ani zdaleka stejně. Rozdíl je v tom, že Mathematica (Obr. 9) výraz EXP interpretuje jako proměnnou. Je pravda, že výraz EXP je typický matematický prvek projektu Fake Game (Obr. 8) a Mathematica používá pro jeho reprezentaci odlišný symbol. Rozdíl mezi Fake Game a Mathematica lze pozorovat i v přesnosti čísel modul Fake Game má implemetováno zaokrouhlování na tři desetinná místa. Pro ověření správnosti výstupu Fake Game jsem do Mathematica zadal jen vnitřní závorku výrazu EXP zjednodušení proběhlo správně. 29

Test 3: Zjednodušení vnořených závorek Obr. 10: Fake Game - zjednodušení vnořených závorek Obr. 11: Mathematica - zjednodušení vnořených závorek Třetí test proběhl v pořádku (rozdíl jen v pořadí prvků a zaokrouhlení). Modul Fake Game optimálně zjednoduší libovolně dlouhý vstupní výraz, pokud je složen jen z lineárních jednotek. Hlavní síla současného modulu je soustředěna na výpočet takovýchto rovnic, které jsou složeny z jednoduchých členů. 30

Test 4: Zjednodušení s výrazem 1/(1+exp( )) Obr. 12: Fake Game - zjednodušení s výrazem 1/(1+exp( )) Obr. 13: Mathematica - zjednodušení s výrazem 1/(1+exp( )) Test 4 se zjednodušením výrazu 1/(1+exp( )) nemůže Mathematica (Obr. 13) správně interpretovat, protože výraz exp se v ní zadává jiným způsobem. Fake Game (Obr. 12) výraz zjednodušil podle současné implementace modulu správně (zkontrolována vnitřní závorka výrazu exp v Mathematica). Chybějící zjednodušení výrazu exp je dalším námětem v pokračování vývoje modulu zjednodušení v projektu. 31

Test 5: Vnořené výrazy 1/(1+exp( )) Obr. 14: Fake Game - vnořené výrazy 1/(1+exp( )) V testu 5 nemá cenu zjednodušovat celý výstupní řetězec pomocí Mathematica, ale provedl jsem v něm jen částečné zjednodušení závorek. Modul Fake Game (Obr. 14) provedl korektní zjednodušení, které odpovídá jeho implementaci. Ověřeno pomocí menších zjednodušovacích výpočtů v Mathematica. 32

Test 6: Složitější výraz s násobením mezi 1/(1+exp( )) Obr. 15: Fake Game - složitější výraz s násobením mezi 1/(1+exp( )) Tento test prokázal, že zjednodušení složitějšího výraz s násobením mezi 1/(1+exp( )) není provedeno korektně a vyvolá chybu. Tato chyba je předvídatelná, protože operace s výrazem exp budou plně implementovány v dalším vývoji modulu. Zjednodušovací modul sice vypsal chybu, ale je velmi pravděpodobné, že výraz je ekvivalentní výrazu zadanému. Kontrolu správnosti tohoto výrazu jsem neprováděl z důvodu jeho velké složitosti a ztrácel bych se ve vnořených závorkách, kterých je velký počet. Chyba nastala z důvodu, že není provedeno ošetření matematické operace násobení mezi výrazy exp a zjednodušovací modul tudíž neví, jak se má zachovat.. 33

6.2. Funkční testování Excel Pomocí Excelu byly provedeny funkční testy, které spočívaly v dosazení číselných hodnot do proměnných v rovnici. Dosazení probíhalo do rovnic INPUT a SIMPLIFY. Jedna testovací série obsahuje různé kombinace hodnot a je provedena na 506 kombinacích. Popis vzhledu testu: ve sloupečcích vlevo jsou vstupní proměnné, které se dosazují do rovnic. Sloupeček INPUT obsahuje zadanou nezjednodušenou rovnici. Sloupeček SIMPLIFY představuje zjednodušenou rovnici. Poslední sloupeček DEVIATION odpovídá absolutnímu rozdílu takto dosažených výsledků z obou rovnic. Podle velikosti této absolutní hodnoty můžeme usoudit, jestli si obě rovnice funkčně odpovídají. INPUT: MEDV=(-0.848*((AGE-3.561)/5.218)+ 0.732)*36.24+1.73 SIMPLIFY: MEDV=-5.89*AGE+49.23 Obr. 16: Excel funkční test 1 34

INPUT: MEDV=( 0.334*(1/(1+exp(-(-5.558*(CRIM-5.0)/45.0+ 1.046))))+1.541*(- 0.848*((AGE-3.561)/5.218)+ 0.732)*(1/(1+exp(-(-5.558*(CRIM-5.0)/45.0+ 1.046))))+0.054)*36.24+1.73 SIMPLIFY: MEDV=(0.334*1/(1+exp(0.124*CRIM-1.664))+(- 0.25*AGE+2.02)*(1/(1+exp(0.124*CRIM-1.664)))+0.054)*36.24+1.73 Obr. 17: Excel funkční test 2 INPUT: SIMPLIFY: MEDV=EXP((-0.177*(-0.562*(CRIM)+ 25.247)-0.069*(0.339*(RM)-6.105)- 2.133)*-0.352)*2.658-5.413 MEDV=2.658*EXP(-0.035*CRIM+0.0080*RM+2.176)-5.413 Obr. 18: Excel funkční test 3 35

7. Závěr Algoritmy pro zjednodušování základních matematických operací se podařilo na lineárních členech dosáhnout optimálního zjednodušení. Na vnořených výrazech EXP algoritmus funguje dobře a jeho vnitřní závorku zjednoduší. Testování nového modulu pomocí nástroje Mathematica dopadlo výborně podle implementovaných matematických operací byly výrazy zjednodušeny správně a na minimální tvar. Výstup z Mathematica to jen potvrdil. Funkčním testováním v Excelu bylo zjištěno, že zaokrouhlování výsledných hodnot, má určitý vliv na číselné výsledky. Z porovnání obou rovnic se výsledky občas trošku vzdálily, ale jinak si myslím, že výpočet proběhl správně. Této práci jsem věnoval hodně úsilí a času, ale taky jsem se na ní hodně naučil a pochopil spoustu věcí kolem analyzátoru, gramatik a zjednodušování výrazů. Projekt mi dal i praxi ohledně rozdělování zdrojových souborů na tematické celky a mohl jsem se přesvědčit, že to má své opodstatnění. Stejně tak jako psaní komentářů do zdrojových kódů. Implementace nového modulu do projektu Fake Game je pro mě velkou zkušeností a jsem rád, že se mi povedlo implementaci nového modulu provést do zdárného konce. Člověk má největší radost, když vidí, že jeho snaha k něčemu novému přispěje. Ve zjednodušování výrazů u tohoto modulu je stále ještě v čem pokračovat. Věřím, že časem se modul rozroste o další algoritmy na zjednodušování složitějších výrazů. 36