Semestráln´ı práce

Transkript

Semestráln´ı práce
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)

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á...

Více

1 Základy 2Zivotn´ı cyklus vývoje software

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...

Více

2004 - matematicky klokan

2004 - matematicky klokan (E) záležı́ na čı́slicı́ch daného čı́sla

Více

Měření zpoždění mezi signály EEG

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ı...

Více

Ploché střechy

Ploché střechy IF/IG-C-82x40, IRD 82x40

Více

Zadán´ı bakalárské práce

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...

Více