Semestráln´ı práce
Transkript
Semestrálnı́ práce Programovánı́ v jazyce C Řešenı́ kolizı́ frekvencı́ sı́tě vysı́lačů Jan Šedivý A14B0448P 30.12.2015 Obsah 1 Zadánı́ 3 2 Analýza úlohy 4 3 Popis implementace 3.1 Main, zpracovánı́ souboru . . . 3.2 Vysı́lače a struktura transmitter 3.3 Matice sousednosti . . . . . . . 3.4 Obarvovánı́ grafu, zásobnı́k . . . . . . 7 7 8 8 9 4 Uživatelská přı́ručka 4.1 Přeloženı́ programu . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Vstupnı́ soubor . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Spuštěnı́ programu . . . . . . . . . . . . . . . . . . . . . . . . 10 10 11 12 5 Závěr 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1. Zadánı́ Naprogramujte v ANSI C přenositelnou konzolovou aplikaci, která jako vstup načte z parametru přı́kazové řádky název textového souboru obsahujı́cı́ informaci o pozici vysı́lačů na mapě a na jeho základě přidělı́ každému vysı́lači frekvenci tak, aby jeho signál nekolidoval s vysı́lači v blı́zkém okolı́. Program se bude spouštět přı́kazem freq.exe hsoubor-s-vysı́lači i. Symbol hsoubor-s-vysı́lači i zastupuje jméno textového souboru, který obsahuje informaci o rozmı́stěnı́ vysı́lačů na mapě a o dostupných vysı́lacı́ch frekvencı́ch, které jim je možné přidělit. Výsledkem práce programu bude výpis do konzole se seznamem přidělených používejte frekvencı́ každému vysı́lači ze vstupnı́ho souboru. V přı́padě chyby nebo rozdělování slov neřešitelné situace skončı́ program výpisem přı́slušné chybové hlášky. 3 2. Analýza úlohy Prvnı́m problémem je čtenı́ vstupnı́ch dat ze souboru, jehož název je zadán jako argument programu. Pokud nebude zadán argument, nebo bude zadán vı́ce než jeden argument, program skončı́ chybovou hláškou. Stejně tak dojde k ukončenı́ programu, pokud bude zadán špatný název souboru a nedojde tak k jeho úspěšnému otevřenı́. V programu je uvažováno s tı́m, že vstupnı́ soubor bude vždy ve stejném formátu. Pro vysı́lače je vytvořeno dynamické pole struktur, kam jsou data o vysı́lačı́ch ukládána. Index prvku pole je pak roven indexu daného vysı́lače. Každému vytvořenému vysı́lači je přidělena barva -1 jako neobarvený vysı́lač. Obrázek 2.1: Znázorněnı́ reprezentace vysı́lačů grafem Následně je na řadě graf kolizı́ (znázorněn na obrázku 2.1), potřebný k vyřešenı́ úlohy. Graf kolizı́ je reprezentován maticı́ sousednosti. Matice sousednosti je sice při většı́m objemu dat náročnějšı́ na operačnı́ pamět’ než napřı́klad seznam sousednosti, ale matice byla zvolena v úvaze, že bude snadnějšı́ na implementaci. 4 Dva vrcholy propojuje hrana, pokud je jejich Euklidovská vzdálenost menšı́ než dvojnásobek poloměru kruhu, ve kterém vysı́lač propaguje signál. Euklidovská vzdálenost bodů A a B v n-rozměrném prostoru je definovaná vztahem: s n X (ai − bi )2 |AB| = i=1 kde ai a bi jsou i -té souřadnice bodů A a B. Bereme v úvahu, že vrchol sám se sebou nesousedı́, tudı́ž na diagonále matice jsou nuly, aby tak nedocházelo ke zbytečnému zaplňovánı́ zásobnı́ku. Přidělovánı́ frekvencı́ vysı́lačům je řešeno pomocı́ metody obarvovánı́ grafu, která byla v zadánı́ navrhnuta jako možné řešenı́. Obarvovánı́ grafu je postup, při kterém každému vrcholu přiřadı́me celé čı́slo (barvu) tak, aby každá dvojice vrcholů spojená hranou měla rozdı́lnou barvu. Zároveň požadujeme, aby k tomuto obarvenı́ bylo použito co nejméně barev (frekvencı́ vysı́lačů). V tomto přı́padě bude obarvován graf kolizı́. Rozdı́lná barva v tomto přı́padě znamená rozdı́lná vysı́lacı́ frekvence, a je tedy zřejmé, že pokud správně obarvı́me koliznı́ graf, ke kolizi signálů nemůže dojı́t.1 Pop Push Obrázek 2.2: Model zásobnı́ku, názorné vloženı́ a vyjmutı́ prvku ze zásobnı́ku Nejprve se tedy musı́ vytvořit zásobnı́k, do kterého se budou vkládat neobarvené vysı́lače. Dále je postupováno podle následujı́cı́ho algoritmu: 1. Vzestupné procházenı́ vrcholů grafu, dokud nenı́ nalezen neobarvený vrchol. Ten je vložen do zásobnı́ku. 1 Výňatek ze zadánı́ 5 2. Nenı́-li zásobnı́k prázdný, vyjme se vrchol ze zásobnı́ku. 3. Je-li aktuálnı́ vrchol obarvený, algoritmus se opakuje od bodu 2. Je-li zásobnı́k prázdný, pokračuje se na dalšı́ neobarvený vrchol v grafu (bod 1). Může totiž dojı́t k situaci, kdy se jeden vrchol v zásobnı́ku vyskytuje vı́cekrát a při jeho prvnı́m obarvenı́ se tak v zásobnı́ku mohou objevovat i obarvené vrcholy. Tı́mto krokem můžeme předejı́t jeho zbytečnému přebarvenı́. 4. Nalezenı́ všech sousednı́ch vrcholů a jejich barev. Je-li sousednı́ vrchol neobarvený, vložı́ daný vrchol do zásobnı́ku. 5. Aktuálnı́mu vrcholu jsou postupně přiřazovány barvy 0, 1, ...,Nf − 1, dokud nenı́ nalezena barva, která nekoliduje se sousednı́mi vrcholy (těmi, do kterých z aktuálnı́ho vrcholu vede hrana). Aktuálnı́mu vrcholu je vždy přiřazována nejnižšı́ možná barva, která tuto podmı́nku splňuje. Pokud je nejnižšı́ nalezená barva většı́ než dostupný počet barev (frekvencı́), algoritmus se ukonči a program s vypsánı́m chybové hlášky skončı́. 6. Tento postup se opakuje od bodu 2. Je-li zásobnı́k prázdný, pokračuje se na dalšı́ neobarvený vrchol v grafu (bod 1). Obrázek 2.3: Možný výsledek obarvenı́ grafu, každá barva představuje jednu frekvenci Pokud je algoritmus úspěšně ukončen, každý vysı́lač by měl mı́t přiřazenou frekvenci tak, aby nekolidoval se sousednı́mi vysı́lači. Zbývá jen vypsat výsledky do konzole. 6 3. Popis implementace 3.1. Main, zpracovánı́ souboru Celý běh programu má na starosti funkce main() v souboru main.c. Tento soubor obsahuje globálnı́ proměnné využı́vané během běhu programu. V tomto souboru je také funkce read file(). Ve funkci main() se nejprve zkontroluje argument zadaný při spuštěnı́ programu. Pokud nenı́ argument zadaný, přı́padně je argumentů vı́ce, program se ukončı́ chybovou hláškou. Pokud je zadaný právě jeden argument, program se pokusı́ otevřı́t datový proud funkcı́ fopen(). Pokud nedojde k otevřenı́ datového proudu, je vypsaná chybová hláška a program je ukončen. Zde je chyba brána jako neplatný argument, např. zadánı́ názvu souboru bez přı́pony, kdy k otevřenı́ souboru nedojde. Pokud je otevřenı́ datového proudu úspěšné, předá se funkci read file(), která zpracovává vstupnı́ soubor. Při zpracovánı́ souboru je předpokládáno, že vstupnı́ soubor bude mı́t vždy stejný formát (viz. 4.2. Vstupnı́ soubor). Čtenı́ souboru je rozděleno na tři části pomocı́ přepı́nače switch, který je přepı́naný pomocı́ proměnné input type typu char. Ta je na začátku nastavena na hodnotu f (frekvence). Redundantnı́ části souboru, jako jsou názvy sekcı́ (Available frequencies, ...) jsou předávány do proměnné ignore, stejně tak id frekvencı́. Samotné frekvence jsou ukládány do dynamického pole freq array[], dokud se při čtenı́ souboru nenarazı́ na řádku Transmission radius, kde je proměnná input type nastavena na hodnotu r (radius). Tı́m se přejde na část zpracovánı́ poloměru vysı́lánı́. Jelikož je očekávána pouze jedna hodnota, uložı́ se do proměnné rad a přejde se k poslednı́ části zpracovánı́ souboru. Zde jsou ukládány informace o vysı́lačı́ch do pole struktur, kde index pole představuje id vysı́lače a ve struktuře jsou souřadnice vysı́lače [X, Y ] a barva -1 jako neobarvený vrchol. Pole je dynamické, pokud dojde k naplněnı́ současného pole a přijde dalšı́ prvek, současné pole se zvětšı́ o dvojnásobek. Základnı́ velikost pole je 25 prvků. Pokud nenı́ dostatek operačnı́ paměti, program se s chybovou hláškou ukončı́. 7 3.2. Vysı́lače a struktura transmitter Vysı́lače jsou ukládány ve formě struktury transmitter definované v souboru transmitter.h, která obsahuje barvu vysı́lače a jeho souřadnice [X, Y ]. Dále jsou v knihovně transmitter.c následujı́cı́ funkce. Funkce check collide(), která pomocı́ Euklidovské vzdálenosti zjišt’uje, zda spolu dva vysı́lače kolidujı́. Tato funkce se využı́vá při vytvářenı́ matice sousednosti. Funkce color colliding(), která kontroluje, zda zvolená barva vrcholu nekoliduje s barvami sousednı́ch vrcholů. Dalšı́ dvě funkce jsou print result() pro vypsánı́ výsledku do konzole, kde barva představuje index pole frekvencı́, a funkci free trans() pro uvolněnı́ struktury vysı́lačů z paměti. 3.3. Matice sousednosti Matice sousednosti má svou vlastnı́ knihovnu matrix.c a hlavičkový soubor matrix.h. Pro práci s maticı́ jsou zde dvě funkce. Prvnı́ funkcı́ je create matrix() pro vytvořenı́ matice. Dvourozměrná matice je reprezentována jednorozměrným polem s počtem prvků 2 · Nt , kde Nt je celkový počet vysı́lačů. Na jednotlivé indexy pole se pak přistupuje pomocı́ matrix[i * trans count + j] kde i představuje řádek dvourozměrné matice, trans count je celkový počet vysı́lačů a j představuje sloupec matice. Jednotlivé hodnoty matice jsou definovány takto: 1, pro i, j kolidujı́cı́ ∧ i 6= j Mij = 0, pro i = j 0, jinak Druhou funkcı́ v knihovně matrix.c je funkce pro uvolněnı́ matice z operačnı́ paměti. Veškeré funkce pracujı́cı́ se zásobnı́kem se nacházejı́ ve vytvořené knihovně stack.c. Definice datové struktury a deklarace funkcı́ se nacházı́ v hlavičkovém souboru stack.h 8 3.4. Obarvovánı́ grafu, zásobnı́k Celý algoritmus obarvovánı́ grafu, společně s funkcemi zásobnı́ku, se nacházı́ v knihovně stack.c, struktura zásobnı́ku je pak definována v hlavičkovém souboru stack.h. Strukturu zásobnı́ku tvořı́ počet prvků zásobnı́ku, velikost jednoho prvku zásobnı́ku, ukazatel na zásobnı́k a ukazatel na data v zásobnı́ku. V knihovně pak obsahuje funkci create stack() pro vytvořenı́ zásobnı́ku, která vracı́ vytvořený zásobnı́k. Dále funkce push a pop pro vloženı́/vyjmutı́ prvku ze zásobnı́ku a funkci pro uvolněnı́ zásobnı́ku z paměti. Obarvenı́ grafu probı́há ve funkci assign colors(). Funkce procházı́ všechny vrcholy grafu, dokud nenajde neobarvený vrchol, který vložı́ do zásobnı́ku. Dokud nenı́ zásobnı́k prázdný, vyjme vrchol ze zásobnı́ku. Pokud je vyjmutý vrchol neobarvený (v zásobnı́ku se může vyskytnout i již obarvený vrchol, viz. 3. bod algoritmu obarvenı́ grafu v analýze úlohy), zavolá funkci adjacent trans color(). Ta naplnı́ pole color arr[] barvami sousednı́ch vrcholů, pokud je vrchol ještě neobarvený, vložı́ ho do zásobnı́ku. Podmı́nka ve funkci adjacent trans color() if (sel_trans == 0) { ... } else { ... } kde sel trans je vrchol vyjmutý ze zásobnı́ku, sloužı́ pouze k upravenı́ vyhledávacı́ho indexu matice pro nultý vrchol (kvůli záporným hodnotám). Návratovou hodnotou funkce je počet sousednı́ch vrcholů. Po vykonánı́ funkce adjacent trans color() se nastavı́ barva vyjmutého vrcholu na 0. Dokud barva vyjmutého vysı́lače koliduje s některou z barev sousedů, přičı́tá hodnotu barvy o 1. Pokud je výsledná barva nižšı́ než počet dostupných barev (frekvencı́), přiřadı́ ji vyjmutému vysı́lači, jinak uvolnı́ zásobnı́k z paměti a funkce vrátı́ hodnotu 0 a v funkci main tak vypı́še chybovou hlášku s neexistujı́cı́m řešenı́m. Tento cyklus je vykonáván, dokud jsou vrcholy v zásobnı́ku, nebo dokud jsou v grafu neobarvené vrcholy. Po skončenı́ cyklu se již nepotřebný zásobnı́k uvolnı́ z paměti a funkce vrátı́ hodnotu 1 jako úspěšné řešenı́. Funkce main poté už jen zavolá funkci print result() pro vypsánı́ výsledků do konzole a ukončı́ celý program s návratovou hodnotou 0. 9 4. Uživatelská přı́ručka 4.1. Přeloženı́ programu Pro spuštěnı́ programu je potřeba nejprve zkompilovat zdrojové kódy na spustitelný soubor pomocı́ Makefile souboru. Pro operačnı́ prostředı́ Win32/64 (tj. operačnı́ systémy Microsoft Windows NT/2000/XP/Vista/7/8/10) je k tomu určený soubor Makefile.win, pro běžné distribuce Linuxu (např. Ubuntu, Mint, OpenSUSE, Debian, atp.) je určen soubor Makefile. Při úspěšné kompilaci vznikne v adresáři spustitelný soubor freq.exe. Názorné zkompilovánı́ programu (v operačnı́m systému Linux/Ubuntu je ukázáno na obrázku 4.1. Obrázek 4.1: Názorná ukázka kompilace programu 10 4.2. Vstupnı́ soubor Soubor se vstupnı́mi daty musı́ být textový s následujı́cı́m formátem: Available frequencies: IDf0 f0 IDf1 f1 IDf2 f2 ... IDfNf −1 fNf −1 Transimission radius: R Transmitters: IDt0 Xt0 Yt0 IDt1 Xt1 Yt1 IDt2 Xt2 Yt2 ... IDtN −1 XtN −1 YtN −1 Kde IDfi je čı́selný identifikátor i-té vysı́lacı́ frekvence a fi je přı́slušná vysı́lacı́ frekvence v Hertzı́ch. Nf je celkový počet dostupných vysı́lacı́ch frekvencı́ a N je celkový počet vysı́lačů. Konstanta R udává poloměr kruhu v kilometrech, v němž má vysı́lač pokrytı́ signálu a kde může docházet ke kolizı́m. V sekci Transmitters se nacházı́ identifikátory a pozice jednotlivých vysı́lačů. IDti je identifikačnı́ čı́slo i-tého vysı́lače a Xti a Yti jsou jeho přı́slušné souřadnice [X, Y ] na mapě. Tyto souřadnice jsou stejně jako R udávány v kilometrech. 11 4.3. Spuštěnı́ programu Program je možno spustit z konzole s právě jednı́m argumentem, kterým je název souboru se vstupnı́mi daty (včetně přı́pony souboru). To je také jediný možný vstup programu. Obrázek 4.2: Názorná ukázka spuštěnı́ programu Při běhu programu uživatel nemůže s programem nijak interagovat. Odhalı́-li program chybu, reaguje výpisem jedné z chybových hlášek uvedených v tabulce. Pokud žádná chyba nenastane, vypı́še program do konzole id vysı́lačů a jim přiřazené frekvence. Následně se program sám ukončı́. Chybové hlášenı́ ERR#1: Missing argument! Popis chyby Na přı́kazové řádce nebyl programu předán parametr, specifikujı́cı́ vstupnı́ soubor s informacemi o vysı́lačı́ch. ERR#2: Out of memory! Nenı́ k dispozici dostatek operačnı́ paměti. ERR#3: Non-existent solution! Řešenı́ pro daný počet vysı́lacı́ch frekvencı́ nebylo nalezeno. 12 5. Závěr Vytvořený program úspěšně řešı́ problém v poměrně uspokojivém čase. Při testovánı́ se vstupem s 1000 vysı́lači se časy běhů pohybovaly mı́rně pod 1 sekundou. Výsledky pro vstup s 25 vysı́lači jsou stejné s poskytnutými vzorovými výsledky. Pro vstup s 1000 vysı́lači se sice oproti vzorovým výsledkům lišı́, ale stále splňujı́ požadavky zadánı́. Některé části programu by mohly být řešeny lepšı́m způsobem. Napřı́klad při vkládánı́ vrcholů do zásobnı́ku nastávajı́ situace, kdy je do zásobnı́ku vložen vrchol, který se již v zásobnı́ku nacházı́. Tı́m docházı́ ke zbytečnému zabı́ránı́ paměti a při velkém objemu dat by zřejmě docházelo i ke zpomalenı́ celkového běhu programu. Dalšı́m vylepšenı́m by mohlo být přesunutı́ funkce pro čtenı́ vstupu ze souboru do jejı́ samostatné knihovny pro lepšı́ čitelnost kódu. Pro mě nejnáročnějšı́ částı́ programu, předevšı́m časově, byla implementace obarvovánı́ grafu i přesto, že jsme měli algoritmus srozumitelně popsaný v zadánı́. Uvı́tal jsem také nutnost tvořenı́ dokumentace v typografickém systému TeX. Jinak si myslı́m že obtı́žnost semestrálnı́ práce byla přiměřená. 13
Podobné dokumenty
Přehledový katalog LIKA (PDF, česky, 0.7MB)
aniž by ztrácela individuální přístup k zákazníkovi.
Lika Electronic je certifikovaná v souladu s normami ISO
9001:2000 management kvality systémů a zavázána
splnit normu ISO 14001:2004 enviromentá...
1 Základy 2Zivotn´ı cyklus vývoje software
• Brainstorming – konference s moderátorem, vı́ce nápadů, odstraňuje rozpory
• Společný vývoj aplikacı́ (JAD) – moderátor, pı́sař, zákaznı́ci a vývojáři
• Rychlý vývoj aplikacı́ (RAD...
Měření zpoždění mezi signály EEG
důležitých informacı́ z naměřených dat EEG přı́strojů.
K nadstavbovým analýzám prováděným nad EEG záznamy, které poskytujı́ počı́tače, se
však stále pohlı́žı́ jako na doplňujı...
Zadán´ı bakalárské práce
Současný technologický vývoj umožňuje vytvářet aplikace spustitelné ve webovém prostředı́,
které se svým vzhledem a chovánı́m blı́žı́ desktopovým aplikacı́m. Přesně takovou techno...