ŘEŠENÍ KOLIZÍ FREKVENCE SÍTĚ VYSÍLAČŮ
Transkript
Obrázky a loga mají být vektorové nebo aspoň v dostatečném rozlišení... ŘEŠENÍ KOLIZÍ FREKVENCE SÍTĚ VYSÍLAČŮ Semestrální práce z předmětu KIV/PC Alena Švelchová (A12B0526P) 3.1.2015 Obsah 1 Zadání 1 2 Analýza úlohy 2.1 Interpretace dat . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Graf kolizí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Obarvování grafu . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 3 4 3 Popis implementace 5 3.1 Funkce main() . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.2 Knihovna input.h . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.2.1 int freq in(FILE *input, int **p) . . . . . . . . . . . . 6 3.2.2 int radius in(FILE *input) . . . . . . . . . . . . . . . . 6 3.2.3 int trans in(FILE *input, struct trans **last, int r, int f) 6 3.3 Knihovna trans.h . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.3.1 Struktury . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.3.2 void add trans(struct trans **list, int id, float x, float y, int f) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.3.3 void new neigh(struct trans *list, int r) . . . . . . . . . 7 3.3.4 Uvolňování paměti . . . . . . . . . . . . . . . . . . . . 7 3.4 Knihovna color.h . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.4.1 void coloring(struct trans *last, int freq) . . . . . . . . 7 3.4.2 void color print(struct trans *last, int *pole) . . . . . . 8 3.4.3 void error(int i) . . . . . . . . . . . . . . . . . . . . . . 8 4 Uživatleská přírůčka 4.1 Přeložení aplikace . . . . 4.1.1 Pro OS Windows 4.1.2 ProOS Linux . . 4.2 Ovládání aplikace . . . . 4.3 Výstup aplikace . . . . . 5 Závěr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 9 9 9 9 10 1 Zadání Naprogramujte v ANSI C přenositelnou konzolovou aplikaci, která jako vstup načte z parametru na příkazové řádce název textového souboru, který obsahuje informaci o pozici vysílačů na mapě a přidělí těmto vysílačům frekvenci, tak aby jeho signál nekolidoval s vysílači v blízkém okolí. Dostupné frekvence a radius vysílání jsou součásti vstupního souboru. Program se bude spouštět příkazem freq.exe <soubor>. Symbol <soubor> zastupuje jméno vstupního souboru. Výsledkem práce programu bude výpis do konzole se seznamem přidělených frekvencí každému vysílači ze vstupního souboru. V případě chyby nebo neřešitelné situace skončí program výpisem příslušné chybové hlášky Pokud nebude funkce spuštěna právě s jedním argumentem, vypište chybové hlášení a stručný návod k použití programu v angličtině podle běžných zvyklostí (viz např. ukázková semestrální práce na webu předmětu Programování v jazyce C). Vstupem programu je pouze argument na příkazové řádce – interakce s uživatelem pomocí klávesnice či myši v průběhu práce programu se neočekává. Kompletní zadání, včetně detailních požadavků a specifikací se nacházejí v souboru dostupném na adrese : http : //www.kiv.zcu.cz/studies/predmety/pc/doc/work/sw2014 − 01.pdf 1 2 2.1 Analýza úlohy Interpretace dat Vstupní data, získaná ze vstupního souboru je potřeba načíst a uložit do paměti ve formátu vhodném pro další využití. Vstupní soubor obsahuje seznam frekvencí, poloměr vysílání a poté vysílače a jejich pozici. Přesný formát vstupního souboru je vidět na obrázku č.1. Frekvence je potřeba uložit tak, aby k nim byl snadný přístup, protože právě je budeme přiřazovat vysílačům. Ideální způsob je pole. Bohužel nevíme předem kolik frekvencí budeme mít k dispozici, takže je potřeba nastavit velikost pole na dostatečnou velikost a ošetřit možnost, že nastane situace, že alokovat spíš: bude nedostatečně velké, a nebo pole allokovat dynamicky, tj. napřed spočítat nebude dostatečně počet frekvencí, vytvořit pole a až poté uložit jednotlivé frekvence. Dalším způsobem je vytvoření spojového seznamu, ale musíme počítat s tím, že bude velké nutné procházet celý seznam, abychom se dostali ke konkrétní hodnotě, což bude, zvláště při větším počtu frekvencí náročnější než práce s polem. Radius neboli poloměr signálu je nejednodušší uložit do globální proměnné, neboť se ní bude pracovat v dalších částech programu. Proč vkládáte text jako obrázek? Navíc v malém rozlišení... Obrázek 1: Příklad vstupního souboru zvýrazňovat K jednotlivým vysílačům bude potřeba snadný přístup jako k frekvencím a stejně jako ony by se daly interpretovat pomocí pole nebo spojového seznamu. Kromě id a souřadnic vysílače, které získáme ze vstupního souboru budou k jednotlivým vysílačům patřit další proměnné. Pole by pro takové 2 množství informací muselo být hodně obsáhlé a nebo dvou nebo více rozměrné a opět nastane problém s jeho allokací, neboť předem neznáme počet vysílačů. Za předpokladu, že budou vysílače procházeny postupně a není potřeba je vyhledávat dle indexu, je ideální je ukládat do spojového seznamu pomocí struktur, které obsáhnou všechny potřebné proměnné. 2.2 Graf kolizí K řešení úlohy je potřeba sestavit graf kolizí. Platí pro něj, že každý vysílač je reprezentován unikátním vrcholem, každý vrchol nese informaci o přiřazené frekvenci a jednotlivé vrcholy propojuje hrana pouze tehdy, když mezi nimi může docházet ke kolizi signálu. Tato kolize signálu se zjistí pomocí euklidovské vzdálenosti dvou bodů, která v tomto případě nesmí být menší \times místo "x" než 2x poloměr signálu. Výpočet kolize vysílačů A a B s poloměrem vysílání R. Zvýraznit! q (a1 + b1 )2 + (a2 + b2 )2 > 2R (a1 - b1)^2 + (a2 - b2) ^ 2 !!! Zjištěné kolize vysílačů a výsledný graf kolizí, lze interpretovat mnoha způsoby jedním z nich je vytvářet graf jako seznam hran, tato implementace vyžaduje ještě seznam grafů vytvořených z množiny vysílačů. Obdobně by bylo možné použít pole a jako seznzam grafů využít pole ukazatelů na tyto pole. Další možností,je hrany nebo přímo konkrétní sousedy přiřazovat rovnou do proměné patříci konkrétnímu vysílači. spíš struktury Chápu, že se Vám to nechtělo překreslovat vektorově, ale mohla jste udělat screenshot alespoň v pořádném rozlišení... Po vytištění by tohle vypadalo hrozně... Obrázek 2: Vytvoření grafu kolizí na základě překrytí signálu znázorněného modrými kruhy. (Zdroj: Zadání SP) 3 2.3 Obarvování grafu Po vytvoření grafu kolizí, musíme nalézt vhodný algoritmus na obarvování grafů. Samotné obarvování je přiřazení vrcholu barvy takové, kterou není obarven ani jeden z jeho sousedů. Naším cílem je použít co nejméně barev, volíme tedy vždy nejnižší možnou barvu. Největším problémem je vyhodnocení v jakém pořadí budou vrcholy grafu barveny. Jednou z možností je obarvování podle dostupných barev, kdy pořadí obarvování dosud neobarveních vrcholů závisí na tom, kolika barvami jsou obarveni jeich sousedé. Přednost má vrchol s nejméně možnostmi, čili pokud máme k dispozici pět barev a sousedi vrcholu A již jsou obarveni na dvě z nich a sousedi vrcholu B čtyřmi, pak má předost vrchol B. Pokud narazíme na případ, že má stejný počet možností více vrcholů, volíme ten, který má nejvíce neobarvených sousedů. Pokud i nadále máme více kandidátů, můžeme vybrat libovolný z nich. Daší možností, je obarvování podle nazávislých množin. Z grafu vybereme maximální množinu vzájemně nezávislých prvků a ty obarvíme na nejmenší barvu. Ve zbylém podgrafu hledáme opět největší nezávisou podmnožinu a tu obarvíme na následující barvu. Takto postupujeme dokud není celý graf obarvený. Další algoritmus provádí spojování nesousedních uzlů. Provádíme ho tak, že ze dvou nesousedních uzlů A a B vytvoříme nový uzel AB, který spojíme hranami se všemi sousedy uzlů A a B. Takto pokračujeme, dokud je možné nějaké dva uzle propojit. Výsledný úplný graf pak nelze obarvit jinak, než že každému jeho uzlu přiřadíme jinou barvu. Následně spojené uzly opět rozpojíme na půlovdní uzly, kterým zůstane barva přidělená uzlu z úplného grafu. Existují i další algoritmy na barvení, nebo vylepšování výše uvedených možností, ale tyto reprezentují nejčastější přístupy k problematice. Pro první uvedený algoritmus, je třeba mít u každého vrcholu možnost přístupu k jeho sousedům, kvůli zjišťování jejich počtu a použité barvy, aby bylo možné správně určit pořadí. Naproti tomu druhý a třetí algoritmus vyžadují hlavně správně zvolit reprezentaci vrcholů a jejich hran. 4 3 Popis implementace Poté co funkce otevře vstupní soubor, načítá z něho jednotlivé řádky a ukládá je do proměných. První část vstupního souboru jsou frekvence a ty ukládá do pole frekvencí. Protože jejich počet nezná předem musí pole allokovat dynmicky. Druhá část vstupního souboru je poloměr signálu vysílání, kteoru uloží do globální proměné. Poslední a nejobsáhlejší částí vstupního souboru jsou vysílače a jejich umístění. Ty ukládá pomocí struktrur do spojového seznamu. V okamžiku kdy načítá a ukládá nový vysílač, porovná jeho vzdálenost se všemi doposud načtenými a pokud neplatí výše uvedená nerovnice (viz 2.2), přidá do seznamu sousedů nového vysílače vysílač se kterým dochází ke kolizi zvýraznit a naopak. Každý vysílač, reprezentovaný strukturou trans, tak obsahuje seznam vysílačů se kterými sousedí. Zároveň s tím do proměnné zaznamenává nárůst počtu sousedů, který později slouží k indikaci počtu neobarvených sousedů. Když je zjištěno, které vysílače mají mezi sebou hrany, mohu přistoupit k přiřazování frekvencí. Rozhodla jsem se použít první z algoritmů popsanerovnice ných výše (viz 2.3). Všechny vysílače mají proměnnou index frekvence (in- zvýraznit dex do pole kde jsou frekvence uloženy), který je defaultně nastavený na -1. K tomu abych vysílače (vrcholy) mohla efektivně porcházet potřebuji zásobník, kam ukládám neobarvené vrcholy, které mají při obarvování přednost, potože jsou sousedy již zpracovaného vysílače a patří do stejného podgrafu. Obarvovací funkce projde seznam vrcholů a první neobarvený vrchol obarví na nejnižší možnou hodnotu, která nekoliduje se sousedními vysílači. Poté všechny jeho sousedy uloží do zásobníku. Pokud zásobník není prázdný, vybere další vrchol z něj a opět ho obarví a uloží jeho sousedy do zásobníku. Tento výběr provádí na základě dvou kritérií - podle počtu dostupných frekvencí a podle počtu neobarvených sousedů. Když je zásobník prázdný čili je celý podgraf obarvený, vezme další neobarvený vrchol ze seznamu vysílačů a začne tak obarvovat další podgraf grafu kolizí. Samotné obarvoání řeší pomocí pole dostupných frekvencí, pole odpovídá počtu dostupných frekvencí a při inicializaci je nastaveno na samé nuly. Vyhodnoty sílači bude do proměné, kde je index frekvence, uložen místo -1 index prvního psát v TeXu výskytu 0 v poli dostupných vysílačů. Součástí funkce je zakázat sousedům matematicky $-1$ vrcholu použít stejnou frekenci. Když je frekvence přiřazena, zakáže se pou- nebo jinak zvýražít sousedům tak, že se hodnota příslušného indexu v jejich poli dostupných znit frekvencí přepíše na 1 a zárověň se sníží počet jejich neobarvených sousedů. Na závěr funkce vypíše naobrazovku sezam vysílačů a jejich frekvenci. 5 3.1 Zvýraznit Funkce main() Funkce main() je řídící část programu, která deklaruje globální proměné a volá všechny další potřebné funkce. Mezi globální proměné programu patří poloměr signálu (int r), počet frekvencí (int count f), počet vysílačů (int count t), pole frekvencí (int *fr) a první položka seznmamu vysílačů (struct trans *last). Napřed volá tři funkce z knihovny input.h - freq in(), radius in() a trans in(). Ty načítají vstupní soubor a ukládají počáteční hodnoty. Poté přijde nařadu samotné obarvování pomocí funkce coloring(), výpis výsledku na konzoli má na svědomí funkce color print(). Na konci funkce main uvolňuje funkcemi free() a free list() allokovanou paměť. 3.2 3.2.1 Knihovna input.h int freq in(FILE *input, int **p) Vstupními parametry jsou vstupní soubor a pole frekvencí. Pomocí funkce fscanf() načítá vstupní soubor. Funkce počítá počet frekvencí, čili počet řádek kde jsou čísla a ne text a dle toho allokuje pole frekvencí. Pomocí funkce rewind() se vrátí na začátek a vstupní soubor prochází znovu. Tetokrát načtené frekvence ukládá do allokovaného pole. Funkce vrací počet frekcencí. 3.2.2 int radius in(FILE *input) Tato funkce ze vstupního souboru načte, uloží a vrací hodnotu poloměru signálu. Využívá funkci fscanf(). 3.2.3 int trans in(FILE *input, struct trans **last, int r, int f ) Poslední krok načítání dat ze vstupního souboru načítá samotné vysílače. Jednotlivé vysílače jsou zastoupeny strukturou trans (viz 3.3.1). Struktura je definovaná v knihovně trans.h. Nový vysílač po načtení funkcí scanf() ukládá pomocí funkce add trans(), která vysílač přidá na konec seznamu vysílačů. Zárověň nový vysílač porovná pomocí funkce new neigh() s již načtenými vysílači, aby zjistila k jakým dochází kolizím. Funkce vrací počet načtených vysílačů. 6 3.3 3.3.1 Knihovna trans.h Struktury Ve funkci jsou definovány dvě struktury -trans a neigh Struktura trans (vysílač) obsahuje id vysílače, jeho souřadnice, index přiřazené frekvence, pole dostuoných frekvencí, počet sousedů a odkaz na seznam sousedů a odkaz na následující vysílač v seznamu Struktura neigh (soused) obsahuje odkaz na následujícího souseda v seznamu a na vysílač, se kterým má vysílač, kterému patří tento seznam sousedů, kolizi. 3.3.2 void add trans(struct trans **list, int id, float x, float y, int f ) Funkce přidává na konec seznamu nejnovější načtený vysílač. Čísla id, x a y přiřazuje položkám id,x a y nově vzniklé struktury a číslo f je velikost pole availableFreq. Nová struktura má hodnotu count n nastavenou na 0 a freq index nastavenou na -1, a odkaz na sousedy a následující položkou na NULL. 3.3.3 void new neigh(struct trans *list, int r) Když přibyde nový vysílač do seznamu tato funkce počítá zda dochází ke kolizi s ostatními vysílači. V případě že k nějaké kolizi dojde, zavolá 2x funkci add neigh() s opačnými parametry. Ta přiřazuje souseda do seznamu sousedů, takže na první zavolání přidá novému vysílači do seznamu sousedů toho s kým má kolizi a napodruhé tomu s kým má kolizi do seznamu přiřadí nový vysílač, a zároveň navýší proměnou count n (počet sousedů). 3.3.4 Uvolňování paměti Tato knihovna ještě obsahuje funkce na uvolnění paměti seznamu vysílačů a sousedů -free list() a free n(). 3.4 3.4.1 Knihovna color.h void coloring(struct trans *last, int freq) Na začátku mají všechny vysílače index frekvence (index do pole kde jsou frekvence uloženy) nastavený na -1. K tomu aby sousedící vysílače (vrcholy) mohla funkce efektivně porcházet vytváří funkce frontu *front, kam ukládá neobarvené vrcholy, které mají při obarvování přednost, potože jsou sousedy 7 již zpracovaného vysílače a jsou tedy součástí stejného podgrafu. Začne procházet seznam vrcholů. Když má vybraný vrchol freq index -1 zavolá funkci color neigh(). Tato funkce projde pole dostupných frekvencí vrcholu (availableFreq) a najde nejnižší index který obsahuje 0. Poté všem vysílačům ze seznamu sousedů tohoto vrcholu (pokud nějací jsou) hodnotu v poli dostupných frekvencí na tomto indexu změní na 1 a sníží hodnoctu count n. Pokud má vysílač nějaké sousedy, přidá je funkcí frontadd() do fronty (*front). Funkce zkontroluje jestli už vysílač v seznamu není a pokud ne, tak ho přidá na konec seznamu. Pokud seznam není prázdný vezme další vysílač k obarvování z něj pomocí funkce next colored().Ta provádí výběr na základě počtu nedostupných frekvencí, tedy počtu jedniček v poli dostupných frekvencí. Přednost dostane ten vrchol, který má v tomto poli nejvíce jedniček. Pokud má maxiální počet jedniček více vrcholů, vezme ten který má větší count n - více neobarvených sousedů. Pokud i nadále zůstává více kandidátů obarvuje ten, který byl v seznamu první. Funkce delete() odebere tento vrchol z fronty čekajících. Pokud seznam je prázdný vezme další neobarvený ze seznamu vysílačů a začne tak obarvovat další podgraf. Takto seznam prochází dokud nejsou obarvené všechny vrcholy. 3.4.2 void color print(struct trans *last, int *pole) Prochází seznam vysílačů a vypíše do konzole id a frekvenci vysílače, kterou získá z pole frekvencí pomocí freq index vysílače. Pokud narazí na vysílač, který má tuto hodnotu -1 zavolá funkci error() s paramtertem 3, která ukončí běh programu zdůvodu nedostatku frevencí. 3.4.3 void error(int i) Tato funkce ošetřuje možné chybové stavy. Program je spustitelný právě s jedním argumentem a to vstupním textovým souborem, pokudt to tak není vypíše funkce ERR1: Missing argument! a ukončí se s návratovou hodnotou 1. Další chyba může nastat při nedostatku paměti při allokování proměných (ERR2: Out of memory!, 2). Pokud nastane situace kdy funkce není schopná přiřadit barvu všem vrcholům, navrátí po ukončení hodnotu 3 s hláškou ERR3: Non-existent solution! 8 4 4.1 Uživatleská přírůčka Přeložení aplikace Před použitím musíte aplikaci přeložit. Pro překlad potřebujete mít nainstalovaný překladač podporující ANSI C jako je například gcc (pro Windows i Linux). Pokud již máte pžekladač nainstalovaný, překlad aplikace spustíte tak, že ve složce se zdrojovými soubory otevřete konzoli a zadáte následující příkaz. 4.1.1 Pro OS Windows make -f makefile.win 4.1.2 ProOS Linux make 4.2 Ovládání aplikace Přeloženou aplikaci již můžeme spustit, její název je freq.exe. Aplikaci je předáván vstupní textový soubor jako parametr při spuštění. Jiný způsob ovládání aplikace není implementován. Spuštění aplikace s parametry musí mít tvar graph.exe <soubor>. Kde <soubor> zastuuje název vstupního souboru (např. vyslilace-25.txt). 4.3 Výstup aplikace Při správném zadání vstupních argumentů a dostatku paměti nám aplikace do konzole vypíše seznam vysílačů s přiřazenou frekvencí. Pokud zadané argumenty nejsou správné, nebo program v průběhu narazí na chybu či dojde paměť zařízení, vypíše aplikace chybovou hlášku v angličtině a ukončí svůj běh. Chybové hlášení obsahuje popis příčiny vzniku problému. měření výkonu 9 5 Závěr S jayzkem C jsem doposud neměla velké zkušenosti. Toto je druhá větší aplikace, kterou jsem v něm vytvářela a prakticky se při tom učila jak jazyk funguje. Jsem si jistá, že v samotná aplikace není bez chybičky, například algoritmus obarvování grafu jde nejspíše implementovat efektivněji a s měnšími nároky na paměť, navíc by bylo zajímavé vyzkoušet si i funkčonst a náročnost implementace ostatních algoritmů uvedených v analytické části a moci je mezi sebou porovnat. Během práce jsem se nejvíce potýkala s nedostatkem znalosti jazyka C a programátorské praxe, zvláště v oblasti implementace struktur a funkcí naplánovaných a vymyšlených během analýzy problému, nezřídka jsem až po několikahodinové práce zjistila, že musím problém zanalyzovat znovu a zkusit to jinou cestou. Velký praktický přínos této práce je pro mě psaní samotné dokumentace. Díky tomu, že musí být napsaná pomocí typografického systému LATEX, jsem se naučila s LATEXem pracovat alespoň na základní úrovni a příjemě mne potěšilo co všechno s ním dokážu i jako nezkušený uživatel. Rozhodně ho budu dále využívat. 10
Podobné dokumenty
Prevodník pH a redox ORP Liquisys CPM221 CPM 221
Displej ukazuje současně momentální
měřenou hodnotu a teplotu. Tím jsou
k dispozici nejdůležitější provozní hodnoty na jeden pohled (současně). V konfiguračním menu pomáhají při nastavení
parametrů...
Katalog DuPont Personal Protection
Výběr vhodného ochranného oděvu pomáhá
zabránit nejen úrazům, ale i nemocem
z povolání, které se mohou projevit po dlouhé
době. Vaši zaměstnanci mohou riskovat své
zdraví. Proto potřebují ochranu, ...
VisionBook 10Wi Pro
často zobrazovaných stránek. Můžete připnout své oblíbené aplikace jako dlaždice a
přizpůsobit si tak obrazovku Start.
Na úvodní obrazovce také můžete změnit obrázek na pozadí.
Zoznam vyradených knižničných jednotiek GT Platnosť súboru: do
elektrotechnický a elektronický slovník SNTL
HOSPITALin 9/2015
a rehabilitaci pro osoby s vážným duševním onemocněním v domácím prostředí. Je určena
primárně lidem nemocným psychózou (F20 – F29), poruchami nálady (F30-F39) a obsedantně
Návod k obsluze PUE7
11.3. Úrovně přístupu (autorizace) ....................................................................................................................35
12. NAVIGACE V MENU ..........................
1. Úvod .........................................................
7. Struktury, unie, enumy, typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
7.1 enum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...
Přehrávání - Lan-Shop
proudem, nevystavujte přístroj dešti
ani vlhkosti.
UPOZORNĚNÍ
Tento výrobek obsahuje optické zařízení,
jehož nesprávné používání může způsobit
poškození zraku. Při používání ovládacích
prvků nebo p...