algoritmi nad gra v jeziku linearne algebreeprints.fri.uni-lj.si/1840/1/toš_t-1.pdfpoglavje 1...
TRANSCRIPT
Univerza v Ljubljani
Fakulteta za racunalnistvo in informatiko
Fakulteta za matematiko in fiziko
Tinkara Tos
Algoritmi nad grafi v jeziku linearne
algebre
DIPLOMSKO DELO
UNIVERZITETNI STUDIJSKI PROGRAM PRVE STOPNJE
RACUNALNISTVO IN MATEMATIKA
Mentor: doc. dr. Tomaz Dobravec
Ljubljana 2012
Rezultati diplomskega dela so intelektualna lastnina avtorja in Fakultete za racunalnistvo
in informatiko Univerze v Ljubljani. Za objavljanje ali izkoriscanje rezultatov diplom-
skega dela je potrebno pisno soglasje avtorja, Fakultete za racunalnistvo in informatiko
ter mentorja.
Izjava o avtorstvu diplomskega dela
Spodaj podpisana Tinkara Tos, z vpisno stevilko 63090185, sem avtorica diplom-
skega dela z naslovom:
Algoritmi nad grafi v jeziku linearne algebre
S svojim podpisom zagotavljam, da:
• sem diplomsko delo izdelala samostojno pod mentorstvom doc. dr. Tomaza
Dobravca,
• so elektronska oblika diplomskega dela, naslov (slov., angl.), povzetek (slov.,
angl.) ter kljucne besede (slov., angl.) identicni s tiskano obliko diplomskega
dela,
• soglasam z javno objavo elektronske oblike diplomskega dela v zbirki ”Dela
FRI”.
V Ljubljani, dne 17. avgusta 2012 Podpis avtorice:
Kazalo
Povzetek
Abstract
1 Predstavitev 1
1.1 Motivacija, cilji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2 Definicije in zapisi 3
2.1 Definicije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Zapisi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3 Redke matrike 11
3.1 Definicija in opis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2 Teorija grafov . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 Shranjevanje redkih matrik . . . . . . . . . . . . . . . . . . . . . . . 15
3.4 Operacije na redkih matrikah . . . . . . . . . . . . . . . . . . . . . 21
3.5 Cilj uporabe redkih matrik . . . . . . . . . . . . . . . . . . . . . . . 24
4 Linearna algebra matrik in vektorjev 25
4.1 Vektorji v prostoru . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.2 Matrike . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
5 Algoritmi 31
5.1 BFS - iskanje v sirino . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.2 Algoritem minimalne poti . . . . . . . . . . . . . . . . . . . . . . . 34
KAZALO
5.3 Bellman-Fordov algoritem . . . . . . . . . . . . . . . . . . . . . . . 41
5.4 Floyd-Warshallow algoritem . . . . . . . . . . . . . . . . . . . . . . 51
5.5 Primov algoritem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6 Testiranje algoritmov 63
6.1 Uvod v testiranje . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.2 Mnozenje matrike z vektorjem . . . . . . . . . . . . . . . . . . . . . 64
6.3 Iskanje v sirino (BFS algoritem) . . . . . . . . . . . . . . . . . . . . 68
6.4 Iskanje minimalnih poti . . . . . . . . . . . . . . . . . . . . . . . . 73
6.5 Bellman-Fordov algoritem . . . . . . . . . . . . . . . . . . . . . . . 77
6.6 Floyd-Warshallov algoritem . . . . . . . . . . . . . . . . . . . . . . 84
6.7 Primov algoritem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
7 Zakljucek 95
Povzetek
Diplomsko delo predstavlja uporabnost dualnosti med grafom in njegovo sosedno
matriko. V teoreticnem delu predstavi osnove teorije grafov in matricne algebre,
predvsem se osredotoci na redke matrike in moznosti zapisov le-teh, ki upostevajo
stevilo nenicelnih elementov matrike. V delu so predstavljene operacije na redkih
matrikah, preko katerih se naveze algoritme, ki v osnovi delujejo na grafih, a jih
s pomocjo dualnosti grafa in matrike lahko spremenimo v zaporedje operacij na
matrikah.
V nadaljevanju delo podrobneje predstavi nekaj algoritmov na grafih ter njihove
komplementarne interpretacije na matrikah, ki v nadaljevanju postanejo predmet
raziskovanja. Opisana je implementacija teh algoritmov v programskem jeziku
Java in v nadaljevanju testiranje delovanja algoritmov na matrikah.
Pri prakticnem delu je poudarek na primerjavi med delovanjem teh algoritmov, ki
uporabljajo standardni zapisa matrike s poljem, ter razlicico, ki uporablja zapis
redke matrike. V delu je raziskano tudi, kdaj je katera razlicica boljsa oziroma
slabsa.
Kljucne besede
Matrika, sosedna matrika, matrika cene, redka matrika, teorija grafov, iskanje v
sirino, minimalne poti, Bellman-Fordov algoritem, Floyd-Warshallov algoritem,
minimalno vpeto drevo, Primov algoritem.
Abstract
The thesis presents usefulness of duality between graph and his adjacency ma-
trix. The teoretical part provides the basis of graph theory and matrix algebra
mainly focusing on sparse matrices and options of their presentation witch takes
into account the number of nonzero elements in the matrix. The thesis includes
presentation of possible operations on sparse matrices and algorithms that basi-
cally work on graphs, but with help of duality between graph and his adjacency
matrix can be presented with sequence of operations on matrices.
Practical part presents implementation of some algorithms that can work both
with graphs or their adjacency matrices in programming language Java and testing
algorithms that work with matrices.
It focuses on comparison in efficiency of algorithm working with matrix written
in standard mode and with matrix written in format for sparse matrices. It also
studies witch presentation of matrices works beter for witch algorithm.
Keywords
Matrix, adjacency matrix, sparse matrix, grapg theory, breath first search, min-
imum path, Bellman-Ford algorithm, Floyd-Warshall algorithm, minimum span-
ning tree, Prim’s algorithm.
Poglavje 1
Predstavitev
1.1 Motivacija, cilji
Dualnost med kanonicno predstavitvijo grafov kot abstraktno kolekcijo vozlisc in
povezav ter redko sosedno matriko je del teorije grafov vse od njenega zacetka,
matricna algebra pa je pri predstavitvi te dualnosti lahko zelo uporaben pri-
pomocek. Vseeno se matrike tradicionalno niso uporabljale za prakticno racunanje
z grafi, predvsem zato, ker predstavitev matrike kot 2-dimenzionalna tabela ni
najucinkovitejsa predstavitev redkega grafa. Z razvojem in vecanjem ucinkovitosti
podatkovnih struktur in algoritmov za redka polja in matrike je postalo mogoce
razviti prakticen pristop, povezan s polji za izvajanje operacij na velikih redkih
matrikah.
Vsak problem na matrikah je problem na grafih in vsak problem na grafih je
problem na matrikah.
Ta dualnost je osnovni koncept pri algoritmih, ki delujejo na grafih, prestavljenih
z matrikami.
Ker so matrike postale zelo primeren nacin za predstavitev grafov, so na primer v
MATLABU matrike postale najpogosteje uporabljena struktura za resevanje pro-
blemov, povezanih z grafi. Veliko raziskovalnih skupin gradi knjiznice za paralelne
algoritme na grafih s pomocjo redkih matrik.
Nasa naloga v tem diplomskem delu bo preuciti nekaj algoritmov na grafih, pred-
1
2 POGLAVJE 1. PREDSTAVITEV
stavljenih z matrikami, ter mozne nacine zapisa redkih matrik in gostih matrik ter
operacij na le-teh. Ugotovili bomo, kateri algoritmi, operacije in zapisi matrik so
casovno najmanj potratni.
Predvidevam, da bo na ucinkovitost algoritmov poleg velikosti matrik vplivala tudi
uporaba zapisa redke matrike.
Nas cilj bo ugotoviti, ne samo kateri zapis redke matrike je manj casovno potraten,
ampak tudi kdaj, saj predvidevam, da se bodo na razlicnih matrikah razlicni zapisi
matrik obnasali razlicno.
Poglavje 2
Definicije in zapisi
2.1 Definicije
Definicija KOLOBAR je mnozica K z dvema racunskima operacijama, ki ju za-
radi preprostosti imenujemo sestevanje in mnozenje, ni pa nujno, da pomenita
klasicno sestevanje in mnozenje. Oznacimo ju z znakoma + (plus) in * (krat). Za
poljubne elemente kolobarja a,b,c mora veljati [9] :
• a+ b = b+ a
(komutativnost za sestevanje)
• a+ (b+ c) = (a+ b) + c
(asociativnost za sestevanje)
• obstaja nevtralni element za sestevanje (oznacimo z oznako 0) , da velja
a+ 0 = 0 + a = a
• poljubni element a ima nasprotni element -a, tako da velja a + (−a) =
(−a) + a = 0
• a ∗ (b ∗ c) = (a ∗ b) ∗ c
(asociativnost za mnozenje)
3
4 POGLAVJE 2. DEFINICIJE IN ZAPISI
• distributivnost iz leve in desne strani, ki povezuje sestevanje in mnozenje
a ∗ (b+ c) = a ∗ b+ a ∗ c
(a+ b) ∗ c = a ∗ c+ b ∗ c
Kolobar je za operacijo + Abelova grupa.
Kolobar dolocajo tile podatki: K mnozica njegovih elementov, operacija “+” ime-
novana sestevanje in “*” imenovana mnozenje. Ce enega izmed teh podatkov
spremenimo, dobimo drug kolobar [3].
Definicija OBSEG je v abstraktni algebri ime za algebrsko strukturo, v kateri je
mozno brez omejitev sestevati, odstevati, mnoziti in deliti (razen deljenja z 0).
Obseg je mnozica O z dvema racunskima operacijama, ki ju zaradi preprostosti
imenujemo sestevanje in mnozenje in ju oznacimo z znakoma + (plus) in * (krat),
lahko pa ti operaciji pomenita kaj drugega kot navadno sestevanje in mnozenje
stevil.
Da bo algebrska struktura res obseg, mora veljati:
• (O, + ,*) je kolobar
• obstaja nevtralni element za mnozenje, ki ga oznacimo z 1 (enota) in je
razlicen od nevtralnega elementa za sestevanje (0)
1 ∗ a = a ∗ 1 = a
• za vsak od 0 razlicen element a obstaja inverzni element a−1, tako da velja:
a ∗ a−1 = a−1 ∗ a = 1
Ce v nekem obsegu velja se komutativnost za mnozenje (a ∗ b = b ∗ a), potem je
to komutativni obseg [9].
Definicija Naj bo V mnozica in F obseg (na primer obseg realnih ali kompleksnih
stevil) in naj bosta definirani naslednji operaciji:
- operacija vektorske vsote ali sestevanja vektorjev, oznacena kot v + w (kjer sta
v, w ∈ V )
2.1. DEFINICIJE 5
- operacija mnozenja s skalarjem, oznacena z a ∗ v (kjer je v ∈ V in a ∈ F )
Mnozico V tedaj po definiciji imenujemo VEKTORSKI PROSTOR nad obsegom
F, ce veljajo naslednje znacilnosti [9] :
• ce v, w ∈ V , potem tudi v + w ∈ V
(z drugimi besedami: V je zaprta za sestevanje vektorjev)
• u+ (v + w) = (u+ v) + w
(asociativnost sestevanja vektorjev v V)
• v mnozici V obstaja nevtralni element 0, da za vse elemente v ∈ V velja
v + 0 = v
(obstoj aditivne identitete v V)
• za vsak v ∈ V obstaja element w ∈ V , da je v + w = 0
(obstoj nasprotnih vrednosti v V)
• v + w = w + v
(komutativnost vektorske vsote v V)
• a ∗ v ∈ V
(zaprtost V za mnozenje s skalarjem)
• a ∗ (b ∗ v) = (ab) ∗ v
(asociativnost mnozenja s skalarjem v V)
• Ce 1 oznacuje identiteto za mnozenje v obsegu F, potem velja 1 ∗ v = v
(nevtralnost elementa 1)
• a ∗ (v + w) = a ∗ v + a ∗ w
(distributivnost glede na sestevanje vektorjev)
• (a+ b) ∗ v = a ∗ v + b ∗ v
(distributivnost glede na sestevanje v obsegu)
6 POGLAVJE 2. DEFINICIJE IN ZAPISI
Definicija MATRIKA je v matematiki pravokotna razpredelnica stevil ali v splosnem
elementov poljubnega kolobarja. V tem delu bodo elementi realna stevila, ce ni
drugace receno. Vodoravni “crti” matrike recemo vrstica, navpicni pa stolpec.
Matrika z m vrsticami in n stolpci se imenuje m x n matrika, m in n pa sta njeni
razseznosti. Element, ki lezi v i-ti vrstici in j-tem stopcu matrike (kjer vrstice in
stolpce ponavadi stejemo od 1 naprej, razen v kaksen programskem jeziku od 0
naprej), je (i,j)- ti element, v delu bomo za matriko A oznacili (i,j)-ti element z
ai,j. Matriko A razseznosti m x n lahko torej definiramo s predpisom
A := (ai,j)mxn [3].
Definicija REDKA MATRIKA je matrika, ki ima vec nicelnih elementov kot pa
nenicelnih.
Definicija GRAF G je neprazna mnozica elementov, ki jih imenujemo vozlisca
grafa, in mnozica (neurejenih) parov vozlisc, ki jih imenujemo povezave grafa.
Mnozico vozlisc oznacimo z V(G) ali pa kar z V, mnozico povezav pa E(G)
oziroma krajse kar E. Ce sta v in w tocki grafa G, potem za povezavi vw oziroma
wv recemo, da povezujeta tocki v in w [8].
UTEZENI GRAF je definiran kot mnozica vozlisc V= v1, v2, ...vn, mnozico povezav
E= (vi, vj : wij); i,j =1,2,...n, pri cemer z (vi, vj : wij) oznacimo povezavo, ki
povezuje vozlisce vi z vozliscem vj, z utezmi wij, ter preslikavo W iz E v R utezeni
graf pa kot G(V,E,W). Utezeni graf je lahko usmerjen ali neusmerjen, ciklicen ali
neciklicen [12].
USMERJEN GRAF je tisti graf, ki ima vse povezave usmerjene. Iz enega vozlisca
se lahko premaknemo v drugega (tako da sledimo smeri povezave), nazaj pa po
isti poti ne moremo, razen ce je le-ta dvosmerna [12] .
NEUSMERJEN GRAF je tisti graf, ki nima usmerjenih povezav, ce med vo-
zliscema obstaja povezava, lahko gremo iz prvega v drugo vozlisce in tudi obratno.
CIKLICNI GRAF je graf, ki ga sestavlja samo en cikel oziroma so vozlisca med
seboj povezana v zaprto verigo. Pri takem grafu je stevilo vozlisc enako stevilu
2.1. DEFINICIJE 7
povezav in vsako vozlisce ima stopnjo 2. Oznacujemo ga z Cn, kjer je n stevilo
vozlisc [9].
NECIKLICNI GRAF je graf, pri katerem povezave ne sestavljajo nobenega cikla
(na sprehodu iz katerikoli tocke se nam ne more zgoditi, da bi se vrnili v isto tocko,
ce se ne vrnemo po isti poti nazaj) [9] .
POVEZAN GRAF je graf, katerega vozlisc ne moremo razporediti v 2 skupini
tako, da med eno in drugo skupino ne bi obstajala povezava, ki bi ju povezovala.
Definicija STOPNJA VOZLISCA je stevilo povezav, ki so vezane na vozlisce.
Pri tem se zanke stejejo dvakrat. Stopnjo oglisca oznacujemo z deg(v).
Definicija ZANKA je cikel dolzine 0 oziroma pot iz vozlisca v vozlisce samo.
Definicija DREVO je v teoriji grafov graf, v katerem sta poljubni dve vozlisci
povezani z natanko eno enostavno potjo. Drevo je v bistvu vsak povezan graf brez
ciklov. Gozd je nepovezana unija dreves [9].
Definicija POVEZANOST VOZLISC
V neusmerjenem grafu sta vozlisci u in v povezani, ce obstaja med njima neka
pot, kar pomeni, da lahko nekako pridemo po grafu od ene do druge.
V usmerjenem grafu sta vozlisci u in v [14]
• mocno povezani natanko takrat, ko obstaja neka pot od u do v, in tudi
neka pot od v do u upostevajoc smeri povezav;
• sibko povezani natanko takrat, ko obstaja neka pot med u in v, ce zane-
marimo smeri povezav.
(Krepko, sibko) povezana komponenta je mnozica vozlisc, ki so vse paroma
(krepko, sibko) med seboj povezane in v katero ne moremo dati nobene nove
tocke, ne da bi prejsnji pogoj nehal veljati [14] .
Definicija NEODVISNA MNOZICA je neusmerjen graf oziroma mnozica vozlisc
grafa, ki so paroma neodvisne. To pomeni, da noben par vozlisc iz te mnozice
ni soseden. Neodvisna mnozica je najvecja, ce ni poddmnozica katerikoli druge
neodvisne mnozice.
8 POGLAVJE 2. DEFINICIJE IN ZAPISI
2.2 Zapisi
MNOZENJE
Mnozenje med vektorjem in matriko ali pa med dvema matrikama bomo vcasih
zapisali kar z Matlab zapisom
A op1.op2 v.
Namesto vektorja (v) bi seveda lahko bila matrika (B).
Za osnovno matricno mnozenje bi torej veljalo op1 = + in op2 = ∗Ta zapis nam bo mocno olajsal zapis nekaterih algoritmov.
Ce na primer namesto kolobarja z operacijama + (plus) in * (krat) uporabimo
produkt v tropski algebri, kjer namesto plusa uporabimo max, namesto krat pa
+, dobimo za produkt zapis A max. + v. Se bolj prav nam bo prisel produkt
A min.+ v, a o tem kasneje.
GRAF
Grafe bomo zapisovali kot G=(V,E), kjer bo V mnozica N vozlisc grafa in E
mnozica M povezav grafa. Drug mozen zapis grafa bo z matriko A, kjer je A
matrika dimenzije N x N in ima M nenicelnih elementov oziroma A(i,j) (element
matrike v i-ti vrstici in j-tem stolpcu) bo razlicen od 0, kadar bo med vozliscema i
in j obstajala povezava. Vrednost tega elementa je odvisna od tega, kaj vse zelimo
z matriko na grafu predstaviti (cene povezav, obstoj povezave), zato bo pri vsakem
primeru posebej oznaceno, kaj natanko predstavljajo elementi matrike.
MATRIKE
Matrike lahko vsebujejo logicne vrednosti B celostevilske Z ali realne R.
Zapis na primer A : R5x6x7 pove, da je A 3-dimenzionalno polje z 210 realnimi
elementi dimenzije 5× 6× 7.
Indeksiranje A(i,j) uporabimo tudi na vektorju, v(i) pomeni i-ti element vektorja.
Indeksiranje pa lahko uporabimo tudi na izrazih,f na primer [(I − A)−1](i, j) je
zapis (i,j) v inverzu matrike I-A.
Deli matrik bodo zapisani z Matlab zapisom. Na primer A(1:5;[3 1 4 1]) je matrika
dimenzije 5 x 4, ki vsebuje elemente prvih petih vrstic iz stolpcev 3 1 4 1 v tem
vrstnem redu.
2.2. ZAPISI 9
Ce je I indeks ali pa mnozica indeksov, je A(I; : ) podmatrika iz A z vrsticami, ki
so oznacene v I in vsemi stolpci (znak : pomeni vsi mozni)
DIMENZIJA IME PRIMER
0 skalar s
1 vektor v
2 matrika A
Tabela 2.1: Tabela algebrskih struktur in zapisov
Poglavje 3
Redke matrike
3.1 Definicija in opis
Definicija Redka matrika je matrika, ki ima vec nicelnih elementov kot pa
nenicelnih.
Redke matrike lahko razdelimo na 2 vrsti, in sicer na strukturirane in nestruktu-
rirane.
• STRUKTURIRANE so tiste, pri katerih nenicelni zapisi ustvarjajo nek
vzorec, najveckrat v obliki nekega stevila diagonal. Nenicelni zapisi lahko
lezijo v blokih (podmatrike) istih velikosti.
• NESTRUKTURIRANE so tiste, pri katerih nimamo pravilne postavitve
nenicelnih elementov.
Vecina tehnik je narejenih za nestrukturirane redke matrike, tako da razlike med
tema dvema tipoma vsaj v preteklosti niso kazale na to, da bi zaradi strukturi-
ranosti ali nestrukturiranosti ti algoritmi bolje oziroma hitreje delovali. Mocno
vlogo pa lahko ima ta lastnost redkih matrik pri iterativnih resitvah problemov,
kjer je ena pomembnejsih operacij mnozenje matrike z vektorjem. Ucinkovitost te
operacije je lahko mocno odvisna od tega ali je matrika strukturirana ali ne. Na
vektorskih racunalnikih je naprimer shranjevanje matrik po diagonalah idealno,
bolj splosne sheme pa lahko trpijo, ker zahtevajo indirektno naslavljanje [5] .
11
12 POGLAVJE 3. REDKE MATRIKE
3.2 Teorija grafov
Graf je odlicen za prikaz relacij med nekimi tockami, na primer nase tocke so lahko
mesta; povezava med tocko A in B pa pomeni, da med njima obstaja prevozna
cesta. Ce pa zelimo pri racunanju z grafi uporabiti se linearno algebro, moramo
graf znati predstaviti z matriko, kar lahko storimo na vec moznih nacinov.
Ta dualnost omogoci algoritmom na grafu, da jih prestavimo kot zaporedje li-
nearnih algebraicnih operacij. Z matriko lahko predstavimo vec lastnosti grafa, v
vecini primerov pa graf predstavimo s trojicami (u,v,w), kar predstavlja usmerjeno
povezavo s ceno w iz vozlisca u do v. Ta povezava se odraza v nenicelni vrednosti
w na lokaciji (u,v) v nasi matriki.
Prednosti zapisa grafa z matriko [1]
• Sintakticna kompleksnost
(Veliko algoritmov na grafih postane z linearno algebro in predstavitvijo z
matrikami bolj kompaktno in lazje za razumevanje.)
• Enostavna implementacija
(S pomocjo matrik lahko algoritmi na grafih izkoriscajo programsko infra-
strukturo za paralelno racunanje.)
• Zmogljivost
(Ker ti algoritmi bolj poudarjajo ucinkovit podatkovni dostop, jih je lazje
optimizirati.)
Slika 3.1 prikazuje splosen primer dualnosti med grafom in matriko; glede na to,
kaj so X-i na sliki, pa locimo vec razlicnih matrik.
3.2.1 Matrika sosednosti
Usmerjen graf G=(V,E) lahko predstavimo z matriko sosednosti (ang. adjacency
matrix) A, za katero velja, da ai,j = 1 natanko takrat, ko v originalnem grafu
obstaja povezava med vozliscem i in vozliscem j [1]. Glede na to, da matrika
predstavlja sosede vozlisca, moramo definirati, ali je vozlisce sosed samemu sebi.
3.2. TEORIJA GRAFOV 13
Slika 3.1: Primer dualnosti med grafom in matriko
Rekli bomo, da vozlisce ni samemu sebi sosed, saj iz vozlisca i do samega sebe ne
moremo v natanko 1 koraku, do sebe ”pridemo”v 0 korakih ali pa v najmanj 2.
Zato definiramo ai,i = 0.
i-ta vrstica v matriki A nam pove, v katera vozlisca lahko pridemo iz vozlisca i v 1
koraku. Ce imamo v i-ti vrstici j-ti stolpec enak 0, to pomeni, da iz i ne moremo
do j v enem koraku.
V primeru, ko so povezave obojestranske (ce lahko pridemo od A do B in tudi od
B do A), dobimo simetricno matriko.
x
x
x
x
x
x
x
x
1 2
4 3
Slika 3.2: Primer matrike sosednosti za 4 tocke
Transponirana matrika sosednosti
Transponirati matriko pomeni, da i-ti stolpec matrike A postane i-ta vrstica ma-
trike AT (transponirana matrika matrike A).
14 POGLAVJE 3. REDKE MATRIKE
x x x x x x x xx x x x x x x x
1
23
4
5
67
8
9
Slika 3.3: Primer matrike sosednosti za vec tock
Pri transponirani matriki sosednosti i-ta vrstica pove, iz katerih vozlisc pridemo v
vozlisce i v 1 koraku.
Uporaba matrike sosednosti
S potenciranjem matrike sosednosti dobimo matriko, katere elementi predstavljajo
stevilo poti med dvema vozliscema v toliko korakih, kakrsna je potenca (npr. s
cetrto potenco matrike A dobimo informacijo o stevilu poti med poljubnima 2
vozliscema v 4 korakih).
Trditev 3.2.1 Arij je stevilo poti med i in j dolzine r.
Dokaz (z indukcijo)
• za r=1 trditev drzi po definiciji
• r − 1 7−→: r : arij =∑n
k=1 ar−1ik akj
i
k
j
Pomoc s sliko: Sestejemo vse ar−1ik pri katerih je akj razlicna od 0, dobimo skupno
stevilo vseh poti med i in j dolzine r [4].
3.3. SHRANJEVANJE REDKIH MATRIK 15
3.2.2 Matrika dosegljivosti
A je matrika sosednosti, matriko G:= A + I imenujemo matrika dosegljivosti. Ce
je element matrike G gij 6= 0, to pomeni, da lahko iz vozlisca i do vozlisca j pridemo
v NAJVEC enem koraku.
Trditev 3.2.2 r-ta potenca matrike G v kolobarju z operacijama ALI in IN pred-
stavlja dosegljivost v r korakih.
G�r 6= 0⇔ iz vozlisca i lahko pridem v vozlisce j v najvec r korakih
Dokaz (z indukcijo)
G�r(i, j) je produkt i-te vrsticeG�r−1(i, j) in j-tega stolpca G.G�r(i, j) = ORk(G�r−1(i, k)
AND G(k,j)). Torej G�r(i, j) = 1, ce lahko pridem iz i v k v r korakih in iz k v j
v enem koraku za katerikoli k [4].
3.2.3 Matrika cen
Utezen graf G=(V,E,w) predstavimo z matriko cen C, kjer za element velja:
cij =
0; i = j
wij; ce med i in j obstaja povezava
∞; sicer
Matrika C oziroma element cij nam pove, koliko nas stane, da pridemo iz vozlisca
i v j. S to matriko si lahko pomagamo predvsem pri problemih iskanja minimalnih
poti.
1 2
1
2
3
5 4
3
2
5
3
21
0 1 ∞ 1 3
∞ 0 2 ∞ ∞∞ ∞ 0 3 ∞∞ 2 ∞ 0 ∞2 ∞ ∞ 5 0
3.3 Shranjevanje redkih matrik
Pri operacijah na grafih, ki so predstavljeni z matrikami, si v najvecji meri poma-
gamo z redkimi matrikami, zato sta seveda uspesnost in casovna zahtevnost takih
16 POGLAVJE 3. REDKE MATRIKE
algoritmov odvisna od implementacije in shranjevanja redkih matrik. Nas osnovni
cilj pri redkih matrikah je ucinkovito shranjevanje, saj ima malo nenicelnih ele-
mentov. Nasa ideja temelji na tem, da shranjujemo le nenicelne elemente in ne cele
matrike s pripadajocim velikim stevilom nicel. Zelimo, da bi velikost porabljenega
prostora bila proporcionalna s stevilom nenicelnih elementov in ne z velikostjo cele
matrike.
Primeri bodo prikazani na matriki:
A =
1 0 0 2 0
3 4 0 5 0
6 0 7 8 9
0 0 10 11 0
0 0 0 0 12
3.3.1 CSR ZAPIS (Compressed Storage by Rows)
CSR zapis (Compressed Storage by Rows) shranjuje nenicelne elemente, ki so
urejeni v odvisnosti od svoje pozicije v matriki po vrsticah, torej elementi so
shranjeni po vrsti, po vrsticah in v vsaki vrstici po stolpcih od leve proti desni.
Shraniti moramo 3 polja data, ind in poin. Data je polje z realnimi elementi
matrike, ki so urejeni po vrsti po vrsticah kot lezijo v matriki. Ind vsebuje naravna
stevila, ki predstavljajo indekse stolpcev elementov. Data in ind sta povezana tako,
da ima element i iz data shranjen svoj indeks stolpca v i-tem elementu polja ind.
(ce data[k] = aij, potem je ind[k]=j) Poin pa shranjuje indeks elementa v data,
s katerim se zacne posamezna vrstica, npr na prvem mestu polja poin bo indeks
elementa v data, s katerim se zacne prva vrstica matrike. Poin je vedno dolzine
n+1, kjer je n dimenzija matrike, za n+1 polje dolocimo nnz + 1, kjer je nnz
stevilo nenicelnih elementov v matriki.
Prihranek prostora pri shranjevanju v tem zapisu je precej opazen, saj namesto n2
polj potrebujemo le 2nnz + n + 1 polj.
Pri simetricnih matrikah lahko se bolj prihranimo, saj lahko shranjujemo le zgornji
trikotnik matrike, tezava je le v tem, da s takim zapisom matrike tezko racunamo
oziroma so algoritmi veliko bolj kompleksni.
3.3. SHRANJEVANJE REDKIH MATRIK 17
CSR zapis je precej splosen, ne potrebujemo nobenih predpostavk o redkosti ma-
trike, da ga lahko uporabimo, in ne shranjujejo nobenih nepotrebnih polj; njegova
pomanjkljivost je, da potrebujemo indirektno naslavljanje polj na skoraj vsakem
koraku uporabe [5] [1].
data 1 2 3 4 5 6 7 8 9 10 11 12
ind 1 4 1 2 4 1 3 4 5 3 4 5
poin 1 3 6 10 12 13
Slika 3.4: Primer CSR zapisa na matriki A
3.3.2 CSC ZAPIS (Compressed Storage by Columns)
CSC zapis je variacija CSR zapisa . V bistvu je CSC zapis CSR zapis, ki namesto
z vrsticami vrstni red elementov doloca s stolpci. Lahko bi rekli, da je CSC CSR
zapis za AT . V data shranjujemo vrednosti matrike po stolpcih od levega proti
desnemu, v vsakem stolpcu pa od zgoraj navzdol. Ind shranjuje zaporedno stevilko
vrstice, v kateri se element nahaja. Povezava med data in ind ostaja enaka kot pri
CSR zapisu. Poin shranjuje indeks elementa v data, s katerim se zacne posamezen
stolpec, namesto vrstice, kot pri CSR [5] [1] .
data 1 2 3 4 5 6 7 8 9 10 11 12
ind 1 1 2 2 2 3 3 3 3 4 4 5
poin 1 4 7 2 9 13
Slika 3.5: Primer CSC zapisa na matriki A
18 POGLAVJE 3. REDKE MATRIKE
3.3.3 ZAPIS KOORDINATNEGA SISTEMA (ZAPIS S
TERKAMI)
Manjkrat uporabljen je zapis s terkami, kjer preprosto shranjujemo terke oblike
(podatek, vrstica, stolpec).
V ta namen moramo shraniti 3 polja data, row in col, kjer je data polje z realnimi
elementi matrike, row vsebuje naravna stevila, ki predstavljajo indekse vrstic ele-
mentov v matriki, col pa vsebuje naravna stevila, ki predstavjajo indekse stolpcev
elementov v matriki.
Polja so povezana tako, da imamo za k-ti element v polju data na k-tem mestu v
row shranjen indeks vrstice tega elementa v matriki in na k-tem elementu v col
indeks stolpca elementa v matriki [5] [1].
Prednosti: enostavnost in fleksibilnost.
data 1 2 3 4 5 6 7 8 9 10 11 12
row
col 1 4 1 2 4 1 3 4 5 3 4 5
1 1 2 2 2 3 3 3 3 4 4 5
Slika 3.6: Primer zapisa s terkami na matriki A
3.3.4 MSR ZAPIS (Modified Sparse Row)
MSR zapis izkorisca dejstvo, da ima vecina matrik obicajno nenicelno diagonalo
(veliko algoritmov to celo zahteva) in/ali do te diagonale dostopamo pogosteje kot
do drugih elementov v matriki. Zato je uporabno, da jo hranimo posebej oziroma
prej.
V ta namen pri tem zapisu shranjujemo le 2 polji, data in ind, data z realnimi
stevili in ind z naravnimi. V polju data so na prvih n mestih vrednosti elementov
na diagonali urejene po vrsti, n+1 pozicija ponavadi ni zasedena, lahko pa to
polje nosi kaksno drugo informacijo o matriki; s pozicijo n+2 pa se zacnejo ostali
3.3. SHRANJEVANJE REDKIH MATRIK 19
nenicelni elementi matrike, ki jih shranjujemo po vrsti po vrsticah, podobno kot
pri CSR, le da spuscamo elemente na diagonali, saj so zapisani ze na zacetku. Za
prvih n elementov polja data torej velja, da na i-ti poziciji lezi element v matriki,
ki je v i-tem stolpcu in i-ti vrstici.
Ind ima naslednjo strukturo:
• v prvih n poljih imamo shranjen indeks elementa matrike, s katerim se zacne
vrstica, pri cemer ignoriramo diagonalne elemente. Ce je diagonalni element
edini element v neki vrstici matrike, tja vstavimo indeks, ki ne obstaja v
tabeli data.
• n+1 element je indeks, ki ne obstaja v tabeli data (lahko kar za ena povecan
maksimalen indeks v data).
• Od n+2 elementa v ind naprej velja, da za k-ti element v data (kjer je k
vecji ali enak n+2) hranimo indeks stolpca, v katerem se ta element nahaja
v matriki.
Poraba prostora je malce manjsa kot pri zgornjih zapisih, zapis pa je najbolj upo-
raben, kadar potrebujemo hitro identificiranje elementov na diagonali [10] .
data 1 4 7 11 12 * 2 3 5 6 8 9 10
ind 7 9 10 13 14 14 4 1 4 1 4 5 3
Slika 3.7: Primer MSR zapisa na matriki A
Zvezdica prikazuje neuporabljen element.
Opazimo, da ind(n)= ind(n+1)=14, kar pomeni, da je zadnja vrstica vrstica nicel,
ce bi umaknili diagonalne elemente (edini element v tej vrstici je diagonalni ele-
ment).
20 POGLAVJE 3. REDKE MATRIKE
3.3.5 SHRANJEVANJE DIAGONALNIH MATRIK
Definicija Diagonalna matrika je matrika, ki ima nenicelne matrike samo na
majhnem stevilu diagonal.
Te diagonale lahko shranimo v pravokotnem polju DIAG(1:n,1:Nd), kjer je Nd
stevilo diagonal. Oddaljenost diagonale od glavne diagonale mora seveda biti
znana. Te oddaljenosti shranimo v polju IOFF(1:Nd). Torej je element ai,i+ioff(j)
originalne matrike na poziciji (i,j) polja DIAG
DIAG (i,j) ← ai,i+ioff(j)
Vrsti red shranjevanja diagonal ni pomemben, razen ce do katere od diagonal do-
stopamo veckrat, potem bomo v prednosti, ce te diagonale shranimo na zacetek.
Opazimo tudi, da so vse diagonale krajse od glavne diagonale, zato nekateri ele-
menti DIAG ne bodo uporabljeni [5] .
B =
1 0 2 0 0
3 4 0 5 0
0 6 7 0 8
0 0 9 10 0
0 0 0 11 12
DIAG=
* 1 23 4 56 7 89 10 *11 12 *
IOF= -1 0 2
Slika 3.8: Primer shranjevanja diagonalne matrike na matriki B
Splosnejsa resitev, uporabljena na vektorskih racunalnikih, je Ellpack-Itpack za-
pis. Predpostavka, ki jo moramo privzeti, je, da imamo najvec Nd nenicelnih
elementov v vrstici, kjer je Nd majhen. Nato potrebujemo 2 polji velikosti n x Nd
3.4. OPERACIJE NA REDKIH MATRIKAH 21
COEF in JCOEF. Nenicelne elemente vsake vrstice matrike shranimo v vrstico
COEF(1:n,1:Nd), pri cemer zapolnimo vrstice z niclami, ce je potrebno. V polje
JCOEF(1:n,1:Nd) shranimo pozicijo stolpca za vsak zapis v COEF [5].
COEF=
1 2 03 4 56 7 89 10 011 12 0
JCOEF=
1 3 11 2 42 3 53 4 44 5 5
Slika 3.9: Primer shranjevanja diagonalne matrike z Ellpach-Itpackovim zapisom
na matriki B
Dolocena stevilka stolpca mora biti izbrana za vsak nicelen element, ki je dodan,
da zapolni vrstico v A. V tem primeru je to za vrstice 1, 4 in 5. Tukaj smo dolocili,
da se v JCOEF zapise kar stevilka vrstice, v kateri je nicla. Katero stevilko tu
izberemo, ni pomembno, dobra bi bila vsaka med 1 in n, vseeno pa je dobro, da
ne vstavljamo iste stevilke prepogosto, npr. vedno neko konstanto, saj nam lahko
to poslabsa ucinkovitost nekaterih algoritmov.
3.4 Operacije na redkih matrikah
3.4.1 Mnozenje matrik
Za ucinkovite algoritme potrebujemo tudi ucinkovito matricno mnozenje redkih
matrik. Neodvisno od nacina shranjevanja je casovna zahtevnost za mnozenje
matrike dimenzije NxN z vektorjem z M nenicelnimi elementi priblizno 2M2/N . Z
uporabo tega modela je tudi enostavno izracunati kompleksnost vecine linearnih
algebraicnih algoritmov na grafih.
22 POGLAVJE 3. REDKE MATRIKE
3.4.2 Mnozenje matrike z vektorjem
Produkt med matriko in vektorjem (y= Ax) je zelo pomembna operacija, ki jo po-
trebujemo za vecino iterativnih algoritmov za resevanje redkih linearnih sistemov.
Implementacija je odvisna od nacina shranjevanja matrike. Recimo, da imamo
matriko shranjeno v CSR zapisu.
Operacijo v tem zapisu lahko izrazimo na obicajem nacin : yi =∑
j ai,jxj, saj
mnozenje prehaja cez vrstice matrike.
Algoritem 3.4.2: Mnozenje matrike v CSR zapisu z vektorjem [13]
for i :=1 to n step 1 {y ( i )=0;
}for j := poin ( i ) to poin ( i +1)−1 step 1{
y ( i )=y ( i )+data ( j )∗x ( ind ( j ) ) ;
}
Resitev dobimo v y.
Opazimo, da vsaka iteracija izracuna drugo komponento koncnega rezultata (vek-
torja). To je prednost, saj lahko vsako komponento izracunamo neodvisno, torej
lahko uporabimo paralelizem. Prav tako opazimo, da metoda mnozi le nenicelne
elemente, zato naredimo le 2nnz operacij, medtem ko jih pri obicajnem mnozenju
matrik potrebujemo kar 2n2 (n predstavlja dimenzijo matrike, nnz pa stevilo
nenicelnih elementov v matriki).
Za produkt y = ATx ne moremo uporabiti direktne enacbe yi =∑
j(AT )i,jxj =∑
j aj,ixj, saj to pomeni, da bi morali preckati stolpce matrike, kar pa je zelo
neucinkovito, ce imamo matriko shranjeno v CSR zapisu. Zato moramo upostevati
naslednje:
• namesto za vse j naredi za vse i;
• yi postane yi + aj,ixj.
3.4. OPERACIJE NA REDKIH MATRIKAH 23
Algoritem 3.4.4: Mnozenje transponirane matrike v CSR zapisu z vek-
torjem [6] [1]
for i :=1 to n step 1 {y ( i )=0;
}for i := poin ( j ) to poin ( j +1)−1 step 1 {
y ( ind ( i ))=y ( ind ( i ))+ data ( i )∗x ( j ) ;
}
MSR ZAPIS
Recimo, da imamo matriko shranjeno v MSR zapisu. Ta zapis ni ravno idealen za
mnozenje matrike z vektorjem, saj pri tej operaciji potrebujemo podatek o stolpcu
in vrstici elementa, s katerim trenutno mnozimo vektor, kar pa iz tega zapisa ni
direktno razvidno.
Algoritem deluje tako, da gre po vseh elementih, od n+2 elementa naprej, ugotovi,
v kateri vrstici matrike se nahaja ta element (stolpec je viden neposredno iz tabele
ind) in nato zmnozi element z elementom v ustrezni vrstici vektorja in ga pristeje
rezultatu v ustrezno vrstico. Na koncu pristeje se vrednosti, ki jih dobimo, ce
mnozimo diagonalo, tu ni vecjih tezav, saj imajo ti elementi isti indeks stolpca in
vrstice, element, s katerim mnozimo (iz vektorja x), pa je tudi v isti vrstici.
Algoritem 3.4.6: Mnozenje matrike v MSR zapisu z vektorjem [7]
for j :=n+1 to end o f data s tep 1 {for k:=1 to n step 1{
i f ( ( j < ind [ k ] AND j> ind [ k+1])
OR j=ind [ k ] ) {v r s t i c a=k ;
}}y ( v r s t i c a )=y ( v r s t i c a ) + data ( j )∗x ( ind ( j ) )
}
24 POGLAVJE 3. REDKE MATRIKE
for i :=1 to n step 1 {y ( i )=y ( i )+data ( i )∗x ( i ) ;
}
ZAPIS S TERKAMI
Recimo, da imamo matriko shranjeno v zapisu s terkami. Zapis je precej primeren
za mnozenje matrike z vektorjem, saj je algoritem zelo preprost, enostavno gremo
cez vse elemente v polju data in zmnozimo element z elementom v vektorju, ki
lezi na pravem mestu. Enostavno je ugotoviti, kako med seboj mnoziti elemente,
saj imamo za vsak element v data neposredno dostopna tudi podatka o indeksu
vrstice in stolpca.
Algoritem 3.4.8: Mnozenje matrike v zapisu s terkami z vektorjem [1]
for i :=1 to end o f data s tep 1{y ( row ( i ))=y ( row ( i ))+ data ( i )∗x ( c o l ( i ) ) ;
}
3.5 Cilj uporabe redkih matrik
• Prostor pri shranjevanju redke matrike bi moral biti sorazmeren s stevilom
vrstic, stevilom stolpcev in stevilom nenicelnih elementov.
• Casovna zahtevnost operacije na redki matriki bi morala biti sorazmerna z
velikostjo podatkov, do katerih dostopamo, in s stevilom aritmeticnih ope-
racij, izvedenih na nenicelnih elementih.
Poglavje 4
Linearna algebra matrik in
vektorjev
4.1 Vektorji v prostoru
Mnozici vseh n-terk realnih stevil, ki jo oznacimo z Rn, recemo n-prostor.
Strukturi u=(a1, a2...an) recemo vektor.
Stevila ai so koordinate, komponente, vnosi oziroma kar elementi vektorja u. Ka-
dar govorimo o prostoru Rn, recemo elementom (stevilom) iz R kar skalarji.
Vektorja u in v sta enaka, ce imata enako stevilo elementov in imata istolezece
elemente enake. Primer: (1,2,3) in (2,3,1) imata sicer enake elemente, a ne na istih
mestih, zato nista enaka. [2]
Vektor (0,0,...,0), ki ima vse elemente enake 0, se imenuje nicelni vektor in ga
ponavadi oznacimo kar z 0.
Vcasih vektor v n-prostoru napisemo navpicno, namesto horizontalno. Taksnemu
vektorju recemo stolpicni vektor, obratno vektorjem, zapisanim horizontalno,
recemo vrsticni vektorji.
Vse operacije, definirane na vrsticnih, so analogno definirane na stolpicnih vektor-
jih. [2]
OPERACIJE NA VEKTORJIH
Recimo, da imamo dva vektorja u in v ∈ Rn, recimo u=(a1, a2...an), v=(b1, b2...bn)
25
26 POGLAVJE 4. LINEARNA ALGEBRA MATRIK IN VEKTORJEV
VSOTA teh dveh vektorjev, ki jo zapisemo kot u + v, je vektor, ki ga dobimo
tako, da sestejemo elemente, ki lezijo na istih indeksih vektorjev.
u+ v = (a1 + b1, a2 + b2, ..., an + bn) [2]
MNOZENJE S SKALARJEM oziroma produkt vektorja u in skalarja k, je
vektor, ki ima vse elemente iz u pomnozene s skalarjem k.
ku = k(a1, a2, ...an) = (ka1, ka2, ..., kan) [2]
Opazimo, da sta tudi u+v in ku vektorja v Rn. Vsota vektorjev razlicnih dimenzij
ni definirana.
NEGIRANJE IN RAZLIKA sta definirana tako:
−u = (−1)u
u− v = u+ (−v)
Vektor -u imenujemo nasprotni vektor u-ja in u-v imenujemo razlika u in v.
Lastnosti
Za poljubne vektorje u, v, w ∈ Rn in poljubne skalarje k,l ∈ R velja [2]:
• (u+ v) + w = u+ (v + w)
• u+ 0 = u
• u+ (−u) = 0
• u+ v = v + u
• k(u+ v) = ku+ kv
• (k + l)u = ku+ lu
• (kl)u = k(lu)
• 1u = u
4.2. MATRIKE 27
4.2 Matrike
Podpoglavje je povzeto po [3].
K naj bo dan kolobar. Matrika je kvadratna shema elementov iz K s tole obliko
A =
a11 a12 ... a1n
a21 a22 ... a2n
... ... ... ...
an1 an2 ... ann
. In sicer je A kvadratna matrika dimenzije n x n, ker je v njej n vodoravnih vrstic
in v vsaki vrstici stoji po n elementov kolobarja K. Vseh elementov aij v matriki
dimenzije n x n je n2. Indeksa i in j pri elementu aij povesta, kje lezi ta element v
matriki. Prvi indeks nam pove, v kateri vrstici lezi, drugi pa, v katerem stolpcu.
Na primer a23 je na kriziscu druge vrstice in tretjega stolpca.
Mnozico vseh kvadratnih matrik dimenzije n x n, sestavljenih z elementi kolo-
barja K, bomo zaznamovali s Kn. Zdaj bomo definirali racunske operacije med
matrikami, tako da bo postala mnozica Kn kolobar.
Sestevanje matrik
Naj bosta A in B poljubni matriki dimenzije n x n z elementi iz kolobarja K. Vsota
A + B je matrika dimenzije n x n, katere elementi so vsote istoleznih elementov
matrike A in matrike B.
V vsoti A+B stoji na preseku i-te vrstice in j-tega stolpca vsota elementov aij in
bij, ki lezita na istem mestu v matrikah A in B.
Ker veljajo v kolobarju obicajni zakoni za sestevanje, iz definicije vidimo, da veljata
za sestevanje matrik asociativnostni in komutativnostni zakona:
(A+B) + C = A+ (B + C)
in
A+B = B + A.
Matrike dimenzije n x n odstevamo tako, da odstevamo istolezne elemente. Od
tod sledi, da je mnozica Kn vseh matrik dimenzije n x n za sestevanje Abelova
28 POGLAVJE 4. LINEARNA ALGEBRA MATRIK IN VEKTORJEV
grupa. Element 0 te aditivne grupe je matrika0 0 ... 0
0 0 ... 0
... ... ... ...
0 0 ... 0
, ki ima vse elemente enake 0.
Nasprotna matrika -A matrike A je matrika iz nasprotnih elementov −aij. Res
je A+ (−A) = 0.
Mnozenje matrik
Naj bosta a=a1, a2...an in b=b1, b2...bn vektorja z n elementi poljubnega kolobarja
K.
Vsoto produktov s=a1b1 + a2b2 + ... + anbn imenujemo skalarni produkt a z
b. Skalarni produkt je seveda element kolobarja K.
Produkt matrike A dimenzije n x n in matrike B dimenzije n x n oznacimo z AB
in je matrika C dimenzije n x n, pri kateri je element cij, ki lezi na kriziscu i-te
vrstice in j-tega stolpca produkta AB, enak skalarnemu produktu i-te vrstice in
j-tega stolpca.a11 a12 ... a1n
a21 a22 ... a2n
... ... ... ...
an1 an2 ... ann
∗b11 b12 ... b1n
b21 b22 ... b2n
... ... ... ...
bn1 bn2 ... bnn
=
c11 c12 ... c1n
c21 c22 ... c2n
... ... ... ...
cn1 cn2 ... cnn
pri cemer je cij = ai1b1j + ai2b2j + ...+ ainbnj
Komutativnost v splosnem ne velja, ceprav je osnovni kolobar K komutativen.
Veljata pa asociativnostni in distributivnostni zakon. Torej velja
• (AB)C = A(BC)
• C(A ∗B) = CA+ CBin(A+B)C = AC +BC
Naj ima kolobar K element 1. V tem primeru je tudi v Kn identiteta I, to je
4.2. MATRIKE 29
matrika
I =
1 0 ... 0
0 1 ... 0
... ... ... ...
0 0 ... 1
, ki ima v glavni diagonali povsod element 1 kolobarja K, na vseh drugih pa je
element 0.
Velja:
AI = IA = A
za vsako matriko A dimenzije n x n.
Zamenjajmo v matriki A vodoravne vrstice s stolpci, torej zrcalimo A cez glavno
diagonalo. Tako dobimo transponirano matriko matrike A, ki jo oznacimo z AT
Torej:
AT =
a11 a21 ... an1
a12 a22 ... an2
... ... ... ...
a1n a2n ... ann
Transponiranost je vzajemna. K matriki AT transponirana matrika je prvotna
matrika A.
ATT = A
Vidimo tudi, da je transponirana matrika vsote enaka vsoti transponirank suman-
dov:
(A+B)T = AT +BT
Potence matrike
Naj bo A matrika dimenzije n x n z elementi iz kolobarja K. Potence matrike A
so definirane tako:
A2 = AA, A3 = A2A,...An+1 = AnA,... in A0 = I
Mnozenje matrike z vektorjem
Produkt matrike A dimenzije n x n in vektorja x z n elementi oznacimo z Ax.
Rezultat je vektor y, ki ima za i-ti element skalarni produkt i-te vrstice matrike z
vektorjem x.
30 POGLAVJE 4. LINEARNA ALGEBRA MATRIK IN VEKTORJEV
Torej:
a11 a12 ... a1n
a21 a22 ... a2n
... ... ... ...
an1 an2 ... ann
∗x1
x2
...
xn
=
y1
y2
...
yn
,
pri cemer je yi = ai1x1 + ai2x2 + ...+ ainxn.
Pri uporabi bi namesto + in * lahko uporabili kaksen drug kolobar, na primer
(min,+).
Takrat bi veljalo yi = min{ai1 + x1, ai2 + x2, ..., ain + xn}.
Poglavje 5
Algoritmi
Vsi algoritmi v poglavju so implementirani po [1], prav tako so vsi opisi algoritmov
in delovanja algoritmov povzeti po [1], ce ni drugace zapisano.
5.1 BFS - iskanje v sirino
Iskanje v sirino je ena od strategij preiskovanja grafa, kjer je iskanje po grafu
omejeno na dve operaciji
• obisk in preiskovanje vozlisca grafa,
• narediti en korak od trenutnega preiskovanega vozlisca do vseh najblizjih
sosedov vozlisca.
Lahko bi rekli, da algoritem deluje tako, da na vsakem koraku “razsiri” ze obiskano
obmocje en nivo vozlisc naprej, kjer nivo pomeni najblizje sosede [9] .
Na sliki 5.1 vidimo, kako po vrsti preiskujemo vozlisca po pravilu “najprej sosede”.
Pri preiskovanju grafa se lahko osredotocimo na iskanje marsicesa, v nasem primeru
pa nas bo zanimalo, do katerih vozlisc lahko pridemo iz zacetnega vozlisca v r
korakih. Ce bi r bil 1, bi odgovor bil: najblizji sosedi (oddaljeni za 1 korak).
Pri resevanju tega problema je pomembna dualnost, ki obstaja med osnovno ope-
racijo v linearni algebri (mnozenje vektorja in matrike) z iskanjem v sirino (BFS)
na grafu G, z zacetkom v vozliscu s.
31
32 POGLAVJE 5. ALGORITMI
1
222
3 3 3 3
4 4 4
Slika 5.1: Slika nivojev pri preiskovanju v sirino
Pomagamo si z zgoraj opisano matriko sosednosti in (ALI,IN) kolobarjem.
0 0 1 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 1 1 1 0 0 0
0 0 1 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 1 1 1 0 0 0
|.& =
1 0 0 1 0 1 1 0 0 1 0 1 1 0 1 1 1 0 1 1 0 0 1 1 1
(0&0) | (0&0) | (1&1) | (0&0) | (0&1) = 0 | 0 | 1 | 0 | 0 = 1
Slika 5.2: Primer racunanja v kolobarju (ALI,IN)
Resitev je i-ti stolpec G�r.
Za iskanje iz vozlisca i zacnemo z x(i) = 1, x(j) = 0 za j 6= i. Potem y = G ∗ xpobere stolpec i iz G, ki vsebuje sosede vozlisca i. Mnozenje med y in G�2 da
vozlisca, ki so 2 koraka stran in tako naprej, to pa je natanko iskanje v sirino.
Ce namesto matrike sosednosti, vzamemo matriko dosegljivosti, lahko s tem algo-
ritmom dobimo vsa vozlisca v razdalji NAJVEC k na k-tem koraku.
5.1. BFS - ISKANJE V SIRINO 33
x x x x x xx x x x x x
A
= x
x
-> x
xA
x
x
-> x
x(A)
x
x
2
x
x
->
12
3
4 5
6
7
Slika 5.3: Simulacija BFS algoritma
0 0 1 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 1 1 1 0 0 0
A =1
2
3
45
1 0 0 1 0 1 1 0 0 1 0 1 1 0 1 1 1 0 1 1 0 0 1 1 1
A =1
2
3
45
V 1 koraku lahko iz vozlišča 3 pridemo v 1 ali 4
2
V 2 korakih lahko iz vozlišča 3 pridemo v 2, 3 ali 5
0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1
A =1
2
3
45
3
V 3 korakih lahko iz vozlišča 3 pridemo v 1,2, 4 ali 5
Slika 5.4: Simulacija BFS algoritma na primeru
Kot smo videli, lahko izvajamo vec neodvisnih iskanj naenkrat, tako da uporabimo
mnozenje med dvema redkima matrikama, saj se pri takem mnozenju izracunajo
34 POGLAVJE 5. ALGORITMI
stolpci neodvisno eden od drugega. Namesto vektorja x torej uporabimo matriko
X, s stolpcem za vsako zacetno vozlisce. Po mnozenju Y = G ∗ X, stolpec j v
Y vsebuje rezultat BFS za vozlisce, specificirano s stolpcem j v X. Z uporabo
nepotratne podatkovne strukture za operiranje z redkimi matrikami je casovna
kompleksnost iskanja enaka, kot bi bila s tradicionalno podatkovno strukturo za
redek graf.
5.2 Algoritem minimalne poti
PROBLEM
Imamo usmerjen graf G z N vozlisci in M povezavami ter matriko cen C (na mestu
(i j) je cena poti od vozlisca i do vozlisca j v enem koraku). Zapisi na lokacijah
A(i,i) bodo 0 (cena, da pridemo do vozlisca, v katerem smo ze, je 0). Zelimo najti
drugo matriko, ki bi imela na poziciji (i, j) zapis, ki bi povedal najmanjso mozno
ceno pri sprehodu od i do j, pri tem pa ni pomembno, v koliko korakih bi to bilo.
V bistvu iscemo najcenejse poti od nekega vozlisca s do vseh drugih vozlisc.
Problem bi ze znali resiti z iskanjem v sirino, ce bi imeli vse cene enake 1.
Ideja
Ce je π = (u0, ..., uk−1, uk) najcenejsa pot od u0 do uk, potem je (u0, ..., uk−1)
najcenejsa pot od u0 do uk−1.
Dokaz
Ce bi obstajala od u0 do uk−1 neka cenejsa pot p, ki bi jo lahko podaljsali s korakom
(uk−1, uk) in tako dobili neko pot med u0 in uk, ki bi bila cenejsa od π, ki pa je po
predpostavki najcenejsa, bi zasli v protislovje [14].
Torej je vsaka najcenenjsa pot podaljsek neke druge najcenejse poti. Vse, kar
moramo storiti, ce iscemo po grafu, je, da za vsak i najdemo njegovo predhodnico
na najcenejsi poti od s do i.
Porodi se ideja, da bi namesto navadnega produkta C(i,j)=∑
k(A(i, k) ∗ B(k, j)
zeleli produkt v kolobarju z operacijama min in + (C=A min.+ B) C(i, j) =
mink{A(i, k) +B(k, j)}.Zakaj nam ta operacija pride prav?
5.2. ALGORITEM MINIMALNE POTI 35
Naj bo ui = cena najcenejse poti od zacetnega vozlisca do vozlisca i
• ce je i = 1, potem je u1 = 0,
• ce i 6= 1, potem pride najcenejsa pot v i iz nekega k (k 6= i). Kot smo
premislili zgoraj, je to del najcenejse poti do k (z ceno uk). Ostane se
vprasanje, kateri je k. K je tisti, za katerega je uk + cki minimalno. Torej:
ui = mink 6=iuk + cki, natanko to pa nam da produkt v kolobarju (min,+).
Kadar graf G nima povezave med i in j, bi po definiciji v matriki A imeli zapis
A(i,j)=0. To pa bi pomenilo, da med tema vozliscema ni cene (je pot zelo poceni),
mi pa bi morali nekako zagotoviti, da nam bo element v bistvu povedal, da je pot
med i in j nemogoca oziroma mora biti cena taka, da se nam zagotovo nikoli ne
bo splacalo iti po njej. Najlazje to storimo tako, da za take primere definiramo
A(i,j)= ∞.
Poglejmo sedaj naso operacijo A min.+ A med enakima matrikama:
C(i, j) = mink{A(i, k) + A(k, j)}
A(i,k) je cena na poti od vozlisca i do vozlisca j in A(k,j) je cena na poti od vozlisca
k do vozlisca j. Torej je A(i, k) +A(k, j) vsota cen na poti v ”2 korakih”, in sicer
od vozlisca i do vozlisca j, ki gre skozi k, torej mink{A(i, k) +A(k, j)} pomeni od
vseh moznih poti od i do j, ki grejo skozi razlicne k (gledamo po vseh moznih k)
vzamemo minimalno.
Iz tega sledi, da imamo v C na poziciji i, j res najmanjso ceno poti od vozlisca
i do vozlisca j v natanko 2 korakih. Ker pa smo prej dolocili, da je A (i,i)=0,
minimizacija za C vkljucuje k = i in k = j, kar predstavlja pot od i do j v
natanko 1 koraku, zato bomo raje rekli, da imamo v C(i,j) najnizjo mozno ceno v
NAJVEC 2 korakih. Tudi v nadaljevanju bomo pri govoru o poti dane dolzine v
bistvu govorili o tej poti.
NOTACIJA
A�n
A�1 = A
A�2 = Amin.+ A
in v splosnem A�n = Amin.+ A�(n−1)
36 POGLAVJE 5. ALGORITMI
Algoritem 5.2.10: Mnozenje v kolobarju (min,+): A min.+A
for i :=1 to v i s i n a A step 1 {for j :=1 to s i r i n a A step 1 {
minimum= In t eg e r .MAX VALUE;
for k:=1 to s i r i n a A step 1{temp=A[ i ] [ k]+A[ k ] [ j ] ;
i f ( temp<minimum) {minimum=temp ;
}}r e z u l t a t [ i ] [ j ]=minimum ;
}}
Kjer je:
• rezultat na zacetku matrika s samimi niclami enakih dimenzij kot A
• v minimum se shranjuje trenutni minimum za polje
• temp je trenutni zmnozek
• Integer.MAX VALUE prikazuje ∞
0 1 2 3 0 4 5 0 6 7 0 8 9 10 0
|.& =
0 1 2 5 8 3 0 5 4 12 8 5 0 9 6
17 12 7 0 8 9 10 11 10 0
min{(3+0),(0+3),( + ),( 4+ ),( +9)} = min{3,3, , , } = 3
0 1 2 3 0 4 5 0 6 7 0 8 9 10 0
Slika 5.5: Primer mnozenja v kolobarju (min,+)
A(i,j) ima minimalno ceno od vseh poti od i do j v 1 koraku, v bistvu obstaja
samo ena tak pot, to je cena povezave med i in j. A�2 vsebuje minimalno ceno za
5.2. ALGORITEM MINIMALNE POTI 37
najvec 2 koraka in A�3 minimalno ceno za najvec 3 korake, v nadaljevanju bomo
pokazali, da se ta vzorec nadaljuje tudi za visje potence. Torej obrazlozimo, da
vnos na mestu (i,j) v matriki A�n, ko uporabljamo kolobar (min,+), vsebuje ceno
najcenejse poti od i do j z uporabo najvec n korakov.
Dokaz Trditev bomo dokazali z matematicno indukcijo.
Recimo, da to velja za n, pokazati pa moramo, da to velja tudi za n+1. Prav tako
ze vemo, da to velja za n=1, saj je A definiran tako, da je v ai,j cena poti med i
in j (kar je pot dolzine 1)
Najcenejsa pot v (najvec) 1 koraku iz vozlisca i v vozlisce k je dana v A in naj-
cenejsa pot v najvec n korakih iz kateregakoli vozlisca k v vozlisce j je dano v
B = A�n, ampak na poti od i do j mora obstajati neko vozlisce k na najcenejsi
poti od i do j v najvec n+1 korakih. Bellmanov princip nam pove, da mora vsaka
podpot na optimalni poti tudi biti optimalna podpot. Ce je torej k na optimalni
poti od i do j, mora biti podpot od i do k (trivialno) optimalna in je njena cena
A(i,k). Podpot v najvec n korakih od k do j mora biti tudi optimalna in njena
cena je B(j,k).
Izracun A min.+ B eksplicitno doloca, katero vozlisce k minimizira A(i, k)+B(k, j),
to pa je ravno cena poti najvec n+1 koraki.
MATRICNO POTENCIRANJE
B=A�K bi lahko izracunali z naslednjo zanko
Algoritem 5.2.12: potenciranje v kolobarju (min,+)
B=A;
for i :=2 to K step 1{B=A min.+ B;
}
Kjer je A matrika cen.
Kot smo prej pokazali, bi B(i,j) vseboval najcenejso pot od i do j v najvec K
korakih. Kaj pa, ce nas zanima absolutna najcenejsa pot (ne glede na stevilo
38 POGLAVJE 5. ALGORITMI
A =1
2
3
45
23
1
58
7
V 1 koraku pot iz vozlišča 3 v 1 stane 1 v 4 pa 5, v ostala vozlišča ne moremo
0 1 0 2 3 1 0 5 2 0 8 3 0
A =1
2
3
45
12
7
5
2
V NAJVEČ 2 korakih lahko iz vozlišča 3 pridemo v 1 in 4 po isti ceni, 2 po 7 v 5 pa po 12
0 1 6 11 0 2 3 1 7 0 5 12 2 0 5 8 3 9 5 0
A =3
V vse ostale najkrajše poti iz vozlišča 3 ostanejo iste, razen v 5, ki sedaj stane 10
0 8 1 6 13 11 0 11 2 3 1 7 0 5 10
12 2 16 0 5 8 3 9 5 0
1
2
3
45
1
5
23
Slika 5.6: Primer iskanja minimalnih poti
korakov)? Za to ceno ocitno ne bomo nikoli potrebovali vec kot N-1 korakov, kjer
je N stevilo vozlisc, torej se A�n ne spreminja vec, ko n postane vecji od N-1, saj
pot gotovo ne bo cenejsa, ce bomo po istih povezavah hodili veckrat (opomba:
vsa ta spoznanja veljajo samo za povezan graf, ki ima same pozitivne cene).
B=A�K vsebuje samo informacijo o najmanjsi ceni poti, ne pa tudi o poti sami,
ta informacija se je izgubila, ko smo si v enacbi A(i, k) + B(k, j) zapomnili samo
minimum takih poti, nismo pa si zapomnili vozlisca k, s katerim smo dobili naj-
cenejso pot. Ce zelimo ohraniti se informacijo o poti sami, moramo pri kalkulaciji
B = A min. + B imeti se vzporedno matriko D, v kateri je element (i,j) vozlisce
k, za katerega je bil ta minimum dosezen.
Za bolj ucinkovito racunanje A�Kmoramo najprej povedati, da za vsaka pozitivna
5.2. ALGORITEM MINIMALNE POTI 39
p in q velja
A�(p+q) = A�pmin.+ A�q.
To pa je v bistvu se ena trditev Bellmanovega principa .
Za katerokoli vozlisce k R�p vsebuje minimalne cene poti med vozliscema i in k
s p koraki (R(i,k) je cena minimalne poti med vozliscema i in k) in S�q vsebuje
minimalno ceno poti med vozliscema i in k s q koraki. (S(k,j) je cena minimalne
poti med vozliscema k in j.)
Ce gre minimalna pot s p+q koraki skozi neko vozlisce k, morajo biti
podpoti iz vozlisca i do vozlisca k ter od vozlisca k do vozlisca j mini-
malne podpoti.
Torej R min.+ S najde vozlisce k, ki minimizira R(i, k)+S(k, j). Po Bellmanovem
principu mora to biti najcenejsa od cen poti s p+q koraki. Racun, ki smo ga opisali,
je v bistvu kar A�(p+q).
S pomocjo te trditve lahko bolj ucinkovito izracunamo A�K , in sicer, ce za K iz-
beremo najmanjso moc dveh vecjih ali enakih stevil od N-1, lahko ekonomicno
racunamo matriko, ki ima za element (i,j) absolutno minimalno ceno poti od vo-
zlisca i do vozlisca j:
B�(0) = A
B�(1) = B�(0)min.+B�(0) = A�2
B�(2) = B�(1)min.+B�(1) = A�4
...
B�(r) = B�(r−1)min.+B�(r−1) = A�2r
Algoritem 5.2.14: Algoritem iskanja minimalnih poti brez shranjevanja
poti
B=A;
mnozenje=c e i l ( l og ( do l z i na A)/ log ( 2 ) ) ;
for i :=1 to mnozenje s tep 1 {temp=B min.+B;
B=temp ;
40 POGLAVJE 5. ALGORITMI
}r e z u l t a t=B;
Kjer je:
• temp=matrika s samimi niclami istih dimenzij kot A;
• A je matrika cen;
• min.+ je mnozenje v kolobarju (min,+).
Ne smemo pozabiti, da nam A�2r
daje cene minimalnih poti in ne poti samih, ce pa
zelimo se poti, moramo shranjevati se serijo matrik D(m); m=1,2,...r z vrednostmi
k, ki so bila vozlisca, preko katerih smo prisli do minimalne cene poti v vsakem
izracunu min.+.
Lahko redefiniramo min.+ operacijo v [C,D] = A min. + B tako, da hkrati
racunamo
C(i, j) = mink{A(i, k) + A(k, j)}D(i, j) = argmin{A(i, k) + A(k, j)}ALGORITEM
B�(0) = A
[B�(1), D�(1)] = B�(0)min.+B�(0)
[B�(2), D�(2)] = B�(1)min.+B�(1)
.....
Ce od tod zelimo dobimi celotno optimalno pot iz i do j, pogledamo najprej v
D�(r)(i, j), tu najdemo k, ki je na “polovici” poti med vozliscema i in j. Potem
v D�(r−1) pogledamo vD�(r−1)(i, k), tu najdemo vozlisce, ki je na polovici med
vozliscema i in k, in v D�(r−1)(k, j), da najdemo vozlisce na polovici med vozliscema
k in j in tako dalje rekurzivno, dokler ne najdemo celotne poti (odkrivamo sosedna
vozlisca po poti).
5.3. BELLMAN-FORDOV ALGORITEM 41
5.3 Bellman-Fordov algoritem
Bellman-Fordov algoritem resuje problem iskanja minimalnih poti iz enega vo-
zlisca. Recimo, da imamo dan graf G=(V,E), s cenami povezav w in zacetnim
vozliscem s ∈ V . Z Bellman-Fordovim algoritmom dolocimo, ce imamo v grafu pot
z negativnimi cenami povezav na poti, ki vsebuje s,saj v tem primeru ne moremo
najti prave minimalne poti. Ce v grafu nimamo negativnih povezav, algoritem
vrne minimalno razdaljo poti med vozliscem s in vozliscem v za vse v ∈ V in
pripadajoce poti. Isti problem resuje tudi na primer Dijkstrov algoritem, ki ni
ucinkovit za grafe, ki vsebujejo negativne povezave, saj Dijkstra pozresno izbira
povezave z najnizjimi cenami in jih dodaja v drevo minimalnih poti. Bellman-
Fordov algoritem vsakic pregleda vse povezave, zato je pocasnejsi, a uporabnejsi
v primeru grafov z negativnimi povezavami.
Algoritem lahko implementiramo na vec razlicnih nacinov.
5.3.1 Standardna implementacija
Za vsako vozlisce shranimo oceno minimalne razdalje d(v), kjer vzdrzujemo pravilo,
da d(v) >= ∆(s, v), kjer je ∆(s, v) cena poti med vozliscema s in v. Algoritem
ponavlja zaporedje sprostitev vozlisc, po katerih velja d(v) = ∆(s, v). Sprostiti
vozlisce pomeni, da d(v)= min{d(v),d(u)+W(u,v)}. V glavnem algoritem sestavlja
N iteracij, pri katerih sprostimo vsa vozlisca v vsaki iteraciji (v poljubnem vrstnem
redu). V π(x) shranimo starsa (predhodnika) tega vozlisca v drevesu minimalnih
poti. π na koncu lahko uporabimo tudi za restavriranje celotne minimalne poti za
neko vozlisce, ne samo za pridobitev razdalj (cene) posameznih poti.
Algoritem 5.3.16: Standardna implementacija Bellman-Fordovega al-
goritma
f o r each v i z V {d( v)= I n t eg e r .MAX VALUE;
p i ( v)=NIL ;
}
42 POGLAVJE 5. ALGORITMI
d( s )=0;
for k:=1 to N−1 step 1 {f o r each edge (u , v ) i z E{
Relax (u , v ) ;
i f (d( v)>d(u) + W(u , v ) ){d( v)=d(u) + W(u , v ) ;
p i ( v ) =u ;
}}
}f o r each edge (u , v ) i z E{
i f (d( v)>d(u) + W(u , v ) ){vrn i ” o b s t a j a j o negat ivne povezave ”
}}
Kjer je:
• V mnozica vozlisc;
• E mnozica povezav;
• W(u,v) cena povezave med u in v;
• edge(u,v) je povezava med u in v;
• Relax(u,v) funkcija, ki sprosti vozlisce v;
• Integer.MAX VALUE predstavlja ∞.
Na koncu preverjamo, ali negativne povezave obstajajo, in sicer, ce je cena poti do
v strogo vecja od cene poti do u + cena povezave med u do v, potem mora vmes
obstajati negativna povezava, saj v primeru, da ni negativnege povezave d(v), to
ni cena minimalne poti, kot jo je oznacil algoritem, saj je pot skozi d(u) cenejsa.
Razlog za to je torej lahko samo negativna povezava na grafu.
5.3. BELLMAN-FORDOV ALGORITEM 43
W(u
,v)
d(v)
W(u
,v)
d(u)
s
v
u
5.3.2 Implementacija z linearno algebro
Ta implementacija nas bo bolj zanimala.
Algebrska formulacija algoritma temelji na interpretaciji z dinamicnim programi-
ranjem.
Definicija
∆k(u,v) =
{min{w(p) : u→p v}; ce obstaja pot dolga a(≤ k) med u in v
∞; sicer
je minimalna cena poti med u in v z uporabo najvec k vozlisc.
Ce je ∆k(s, v) < ∆N−1(s, v) za katerikoli v, potem obstaja negativni cikel, drugace
velja ∆k(s, v) = ∆N−1(s, v).
Racunanje ∆k(s, v) je logicno enako sprostitvi vseh vozlisc, povezanih z v.
Natancneje: ∆k(s, v) = minu{∆k−1(s, u) + W (u, v)}. Opazimo, da lahko ∆k
izracunamo samo iz ∆k−1, zato lahko vse ostale ∆i zanemarimo.
Za predstavitev algoritma z matricno vektorskimi operacijami uporabimo (redko)
sosedno matriko dimenzije NxN za shranjevanje tez povezav (matrika cen) in 1xN
vektor za shranjevanje minimalnih razdalj poti v a (≤ k) korakih ∆k(s, ∗). Na
diagonali matrike cen imamo nicle (ce smo ze v tocki i, nas ne stane nic, da
pridemo v tocko i).
Formulo za ∆k(s, v) lahko prevedemo v matricni produkt precej direktno.
Imamo dk(v) = minu∈N(dk−1(u) + A(u, v)), kar je ravno produkt v polkolobarju
(min,+).
dk(v) = dk−1min.+ A(:, v)→ dk(v) = dk−1(v)min.+ A.
44 POGLAVJE 5. ALGORITMI
Ceno minimalne poti lahko predstavimo tudi d = d0AN , kjer je d0 vektor, ki ima
na mestu s 0, drugje pa je ∞. Ta izraz nam prinese dva algoritma za izracun
dolzine minimalne poti iz enega vozlisca.
PRVI je algebrska predstavitev Bellman-Fordovega algoritma spodaj.
Algoritem uporabi vektor velikosti reda N in mnozenje redkih matrik, tako da
opravi O(NM) primerjav.
Algoritem 5.3.18: Bellman-Ford (A,s)
d=I n t eg e r .MAX VALUE;
d( s )=0
for k:=1 to N−1 step 1 {d=d min.+A;
}i f (d n i d min.+A){
vrn i ” o b s t a j a j o negat ivne povezave ”
}
Kjer je:
• d vektor, ki pove, za katero vozlisce s nas zanimajo minimalne poti;
• d na koncu resitev, ce ne obstaja negativni cikel;
• A matrika cen.
DRUGI deluje tako, da najprej naracunamo A�N z zaporednim kvadriranjem.
Opazimo, da ta algoritem v bistvu izracuna najprej vse mozne kombinacije mi-
nimalnih poti med vozlisci, potem pa produkt d min.+ A samo izbere vrstico iz
matrike A�N . Algoritem zahteva O(N3 logN) dela. Algebrski (prvi) algoritem
Bellman-Forda ima asimptoticno boljso zmogljivost od zaporednega kvadriranja
v najslabsem primeru, a je pri zaporednem kvadriranju vec moznosti paralelizma
kot pri prvem algoritmu.
5.3. BELLMAN-FORDOV ALGORITEM 45
d’=d min.+A =1
2
3
45
23
1
58
7
V 1 koraku pot iz vozlišča 3 v 1 stane 1 v 4 pa 5, v ostala vozlišča ne moremo
1
0 5
1
2
3
45
1
7
5
2
V NAJVEČ 2 korakih lahko iz vozlišča 3 pridemo v 1 in 4 po isti ceni, 2 po 7 v 5 pa po 12
V vse ostale najkrajše poti iz vozlišča 3 ostanejo iste, razen v 5, ki sedaj stane 10
1
2
3
45
15
23
T
d’‘=d’ min.+A =
1
0 5
T
7
12
d’‘’=d’’ min.+A =
1
0 5
T
7
10
Slika 5.7: Primer izracuna po Bellman-Fordovem algoritmu
Algoritem 5.3.20: Bellman-Ford (A,s)
d=I n t eg e r .MAX VALUE;
d( s )=0;
B=A;
mnozenje=c e i l ( l og ( do l z i na A)/ log ( 2 ) ) ;
for i :=1 to mnozenje s tep 1{temp=B min.+B;
B=temp ;
}
46 POGLAVJE 5. ALGORITMI
d=d min.+B;
i f (d n i d min.+B){vrn i ” obs ta ja negat ivna povezava”
}
Opazimo, da je iskanje minimalne poti po Bellman-Fordu podobno iskanju te poti
po algoritmu minimalne poti, le da tu iscemo minimalno pot in ceno te poti samo za
vozlisce, doloceno z vektorjem d. Pri prvem nacinu res racunamo samo en vektor,
pri drugem nacinu je izracun matrike isti kot pri algoritmu minimalne poti, zadnji
korak pa je v bistvu prvi korak prvega nacina (izberemo vrstico, ki prikazuje cene
poti za zeleno vozlisce).
5.3.3 Racunanje drevesa minimalnih poti
Kot dodatek k racunanju cen minimalnih poti Bellman- Fordov algoritem najde
tudi minimalno pot. Te poti tipicno shranjujemo s pomocjo π, preko katerega po-
tem lahko izracunamo drevo minimalnih poti. Algoritem lahko torej tudi razsirimo,
tako da nam ze sam vrne drevo minimalnih poti.
Opis in logika iskanja drevesa minimalnih poti, ki bo opisana v nadaljevanju, se
lahko trivialno aplicira tudi na algoritem Floyd-Warshall.
Ce v grafu nimamo ciklov dolzine 0, je racunanje drevesa minimalnih poti precej
enostavno.
Nastavimo π(v) = u, tako da d(u) +W (u, v) = d(v) za vsak v 6= s in ∆(s, v) 6=∞.
Ker d(v) = d(u) + W (u, v) za nekatere u 6= v ∈ V in d(v) ≥ (d(u) + W (u, v)) za
vse u ∈ V , je π(v) = argminu6=v{d(u) +W (u, v)}.Ta izraz lahko algebrsko predstavimo kot:
π = d argmin.+ (A+ diag(∞)),
kjer diag(∞) pomeni, da ima matrika po diagonali vrednosti ∞, s tem izkljucimo
zanke v grafu.
Opazimo, da π(s) nima vrednosti, zato nastavimo π(s) = NIL.
5.3. BELLMAN-FORDOV ALGORITEM 47
Podobno za vsak v z ∆(s, v) = ∞, vrednost π(s) ni pravilna, kar moramo tudi
odpraviti. Ce privzamemo, da je vsako vozlisce na grafu dosegljivo iz s, potem ne
obstaja vozlisce, da bi veljalo ∆(s, v) =∞.
V grafu z zankami uporaba enacbe π = d argmin.+ (A+ diag(∞)) najbrz ne bo
pripomogla k iskanju drevesa minimalnih poti, ker lahko argmin izbere vozlisca,
ki formirajo zanko. Zato zelimo delati na grafu brez zank.
Za izracun kazalcev na starse na grafih brez zank imamo 2 pristopa.
PRVI pristop prilagodi nase operatorje za racunanje na terkah s tremi elementi,
namesto na utezeh realnih vrednosti. Ta pristop sledi standardnemu Bellman-
Fordovemu algoritmu, tako da posodablja kazalce na starse z vecanjem razdalje
med vozlisci.
Prednosti: ves cas se uporablja samo en polkolobar, v katerem racunamo za vse
operacije, tako da je v izracune treba vpeljati le terke in na podlagi tega spremeniti
operacije iz algebrskega Bellman-Fordovega algoritma.
DRUGI pristop uporablja idejo iz enacbe π = d argmin. + (A + diag(∞)), in
sicer tako, da sledi izracunu drevesa minimalnih poti do konca.
Prednosti: uporablja enostavnejse terke z dvema elementoma, ampak je treba
racunati v razlicnih polkolobarjih. Pristop vkljucuje dodatne popravke za odpravo
nepravilnih elementov v π.
5.3.4 Racunanje kazalcev na starse vozlisc
Racunanje kazalcev na starse vozlisc je glavna razlika med osnovnim Bellman-
Fordovim algoritmom in racunanjem drevesa minimalnih poti.
V originalnem Bellman-Fordovem algoritmu so kazalci na starse vozlisc posodo-
bljeni le, ko sprostimo povezavo in je nova razdalja strogo krajsa, kot ze prej
znana.
Naj bo Πk ena od moznih vrednosti, ki jo lahko dodelimo kazalcu na starsa vozlisca
v k-ti iteraciji Bellman-Fordovega algoritma.
48 POGLAVJE 5. ALGORITMI
Potem je
Πk(s, v) =
NIL; k = 0 & v = s
0; k=0 & v 6= s
Πk−1(s, v); k ≥ 1 & ∆k(s, v) = ∆k−1(s, v)
{u : ∆k(s, v) = ∆k−1(s, v) +W (u, v)}; sicer
Po premisleku nam to pravilo da naslednjo lemo, ki pove, da je stars, ki ga algo-
ritem izbere, res stars na minimalni poti, v najvec k korakih, ki je najcenejsa.
Lema 5.3.1 Recimo, da imamo graf z dolocenim vozliscem, ki je zacetek poti in
brez zank.
Potem u 6= NIL ∈ Πk(s, v), ce in samo ce obstaja a in pot p =(s,...u,v) taka, da
w(p) = ∆k(s, v) in ne obstaja s→p′ v, da bi veljalo w(p′) = ∆k(s, v) in | p′ |<| p |.Nadalje Πk(s, s) = NIL.
Dokaz Lemo bomo dokazali z indukcijo.
Lema trivialno drzi pri k=0.
Ce ∆k(s, v) = ∆k−1(s, v), potem minimalna pot v najvec k korakih iz vozlisca s v
vozlisce v stane najvec toliko, kolikor je v k-1 korakih in lema velja pri Πk(s, v) =
Πk−1(s, v) .
Ce ∆k(s, v) < ∆k−1(s, v), potem vsebujejo vse poti v najvec k korakih iz vozlisca
s v vozlisce v natanko k korakov in lema velja po definiciji Πk .
Iz ∆k(s, s) = 0 sledi da Πk(s, s) = NIL.
Lema 5.3.1 je uporabna za oba pristopa izracuna drevesa minimalnih poti.
RACUNANJE KAZALCEV NA STARSE S 3-TERKAMI
Glede na to, da je originalen Bellman-Fordov algoritem pravilen, ce sproscamo
povezave v poljubnem vrstnem redu, lema pove, da lahko posodabljamo kazalec
na starsa vozlisca tako, da je kazalec predzadnje vozlisce na katerikoli minimalni
poti, saj so vse zadnje povezave na enako dolgi poti sproscene v isti iteraciji. Torej,
ce upostevamo dolzino poti in ceno poti, ko opravljamo posodobitev kazalcev, ne
potrebujemo stroge neenakosti v enacbi za izracun kazalca starsa.
5.3. BELLMAN-FORDOV ALGORITEM 49
Cilj je, da povezemo razdaljo in kazalce na starse vozisc s spreminjanjem nasih
operacij tako, da delujejo na 3-terkah. Te 3-terke so sestavljene iz naslednjih
komponent: celotna cena poti, dolzina poti in predzadnje vozlisce. S pametno
posodobitvijo operatorjev lahko se vedno uporabimo iste algoritme, ki temeljijo
na ze prej obrazlozeni algebri.
Definirajmo nase skalarje kot 3-terke v obliki (w, h, π) ∈ S = (R∞ × N × V ) ∪{(∞,∞,∞), (0, 0, NIL)}, kjer R∞ = R∪{∞} in N =1,2,3,.... Vrednost (∞,∞,∞)
pomeni, da pot ne obstaja, in vrednost (0,0,NIL) pomeni pot od vozlisca do samega
sebe. Prva vrednost w ∈ R∞ je cena poti, h ∈ N je dolzina poti oziroma stevilo
iteracij, π ∈ V je predzadnje vozlisce na poti.
Glede na definicijo teh 3 vrednosti je polnjenje sosedne matrike naslednje:
A(u, v) =
(0, 0, NIL); u = v
(W (u, v), 1, u); u 6= v & (u, v) ∈ E(∞,∞,∞); (u, v) /∈ E
Opazimo, da je polje v matriki v bistvu doloceno s ceno povezave. Tudi osnovni
algoritem ze shranjuje u v neki strukturi, torej pri implementiranju te razlicice
algoritma ni nujno, da se nam poveca kolicina prostora, ki ga potrebujemo za
sosedno matriko.
Za nastavljanje osnovnega vektorja razdalje d0, ki nam pove, za katero vozlisce nas
zanimajo minimalne poti, velja:
d0(v) =
{(0, 0, NIL); v = s
(∞,∞,∞); sicer
Za dodatno operacijo, o kateri smo ze govorili, uporabimo operator lmin, ki je
definiran kot leksikografski minimum in primerja prvo vrednost 3-terke takole:
lmin(w1, h1, π1), (w2, h2, π2)) =
(w1, h1, π1); w1 < w2 ∨ (w1 = w2 ∧ h1 < h2)∨
(w1 = w2 ∧ h1 = h2 ∧ u1 < u2)
(w2, h2, π2); sicer
Brez izgube za splosnost lahko predpostavimo, da so vozlisca stevila 1,2,...N in
NIL manjse od ∞ za vse v ∈ V .
Za vse operacije z mnozenjem definiramo novo binarno funkcijo +rhs. Ta funkcija
doda prvi dve vrednosti terke in ohrani tretjo vrednost terke argumenta, ki je na
desni strani operanda.
50 POGLAVJE 5. ALGORITMI
(w1, h1, π1) +rhs (w2, h2, π2) =
{(w1 + w2, h1 + h2, π2); π1 6=∞ & π2 6= NIL
(w1 + w2, h1 + h2, π1); sicer
Izjemo za π1 = ∞ potrebujemo, da imamo identiteto za mnozenje, kadar je ta
operator uporabljen pri mnozenju v konjunkciji v lmin za sestevanje. Izjema za
π2 = NIL je popravek.
Opazimo, da v nasprotju z obicajnim +, +rhs ni komutativna.
Lema 5.3.2 S=(R∞×N×V )∧{(∞,∞,∞), (0, 0, NIL)} nad operatorjem lmin.+rhs
je polkolobar.
Pravilnost algoritma, ki bazira na terkah, dokazuje naslednja lema. Spomnimo
se, da je bil cilj transformacije na 3-terke ohraniti zvezo dn = dA�N , kjer sta
sestevanje in mnozenje definirana z lmin in +rhs.
Lema 5.3.3 Recimo, da imamo graf z dolocenim vozliscem s. Naj bosta matrika
sosednosti A in zacetni vektor d0 dolocena po zgornjih enacbah za A in d0 in naj
bo dk = dk−1lmin. +rhs A; k ≥ 1. Ce je h ≤ k ∈ N minimalno stevilo iteracij
(dolzina poti) minimalne poti (v najvec k korakih) iz vozlisca s v vozlisce v, potem
∃u ∈ V tako da dk(v) = (∆k(s, v), h, u)∧ u = min{v : v ∈ Πk(s, v)} in obstaja pot
dolzine h; p=(s,...u,v) z w(p) = ∆k(s, v).
Ce ne obstaja pot z najvec k koraki, potem dk(v) = (∞,∞,∞). Za zacetno vozlisce
velja dk(s) = (0, 0, NIL).
RACUNANJE KAZALCEV NA STARSE NA KONCU
Pri tem pristopu sledimo enaki ideji; spremenimo le skalarje, tako da delujejo na
zankah. Ta pristop se vedno uporablja terke, ampak enostavnejse.
Uporabimo 2-terke (w, h) ∈ N∞ × (N ∪ {0,∞}). Vrednosti imajo isti pomen kot
pri 3-terkah, samo da tu v terki nimamo kazalca na starsa. Nastavljanje A in d0
je ocitno.
Bellman-Fordov algoritem za 2-terke ostaja enak kot za 3-terke, le da zdaj upo-
rabimo funkcijo lmin namesto navadnega sestevanja in enostavnejso + namesto
mnozenja. Z drugimi besedami: dk = dk−1 lmin. + A. Pravilnost sledi iz leme
5.3.3 kot pri prvem nacinu, ker so operatorji povsem enaki kot pri 3-terkah, le da
tu ignoriramo tretji element.
5.4. FLOYD-WARSHALLOW ALGORITEM 51
Za izracun kazalcev na starse vozlisc nastavimo: π = dn argmin.+ (A+diag((∞,∞))).
Naslednja lema trdi, da so vse vrednosti v π(v) pravilne za vsa vozlisca v 6= s, ki
so dosegljiva iz vozlisca s.
Lema 5.3.4 Recimo, da imamo graf z dolocenim zacetnim vozliscem s in brez
zank. Naj bo dn(v) = (∆k(s, v), hv), kjer je hv najmanjsa cena najcenejse poti iz
vozlisca s v vozlisce v. Naj bo π = dn argmin. + (A + diag((∞,∞))). Potem za
vse v ∈ V –s, za katere velja ∆k(s, v) <∞, imamo π(v) in Πn(s, v).
Dokaz Recimo, da so vsa vozlisca v ∈ V –s dosegljiva iz vozlisca s. Produkt π =
dn argmin.+(A+diag((∞,∞))) da π(v) = argminu/∈v{(∆(s, u)+W (u, v), hu+1)}.Po lemi 5.3.1 imamo u ∈ Πn(s, v), ce in samo ce ∆(s, u) + W (u, v) = ∆(s, v), in
hu = hv − 1.
Torej π(v) = argminu∈πn(s,v){(∆(s, v), hv)}, ki nam da rezultat π(v) = Πn(s, v).
Za vsa vozlisca, ki niso dosegljiva iz vozlisca s, ta pristop ne vraca pravega rezul-
tata, prav tako ne za vozlisce s samo, tako da moramo uvesti dodatne popravke,
da dosezemo, da π vsebuje pravilne vrednosti. Alternativno lahko spremenimo ar-
gmin, da vzame vrednost∞, ce so vsi operandi (∞,∞) in potem je edini popravek,
ki ga moramo upostevati, da nastavimo π(s) = NIL.
5.4 Floyd-Warshallow algoritem
Algoritem resuje problem iskanja najcenejsih poti za vse mozne dvojice vozlisc.
Recimo, da imamo graf G = (V,E) z utezmi na povezavah w in brez zank, potem
ta algoritem vrne cene minimalnih poti ∆(u, v) za vse u, v ∈ V . Tako kot Bellman-
Fordov je Floyd-Warshallow algoritem resitev z dinamicnim programiranjem. Brez
izgube za splosnost lahko oznacimo vozlisca z 1,2,...N.
Algoritem uporabi Dk(u, v) za predstavitev minimalne poti iz vozlisca u do vozlisca
v z uporabo samo vmesnih vozlisc v ∈ 1, 2, ...N ⊆ V .
Torej
Dk(u, v) =
{W (u, v); k = 0
min{Dk−1(u, v), Dk−1(u, k) +Dk−1(k, v)}; k ≥ 1
52 POGLAVJE 5. ALGORITMI
Cas za izvajanje je O(N3) zaradi trojne for zanke. V algoritmu, katerega psevdo-
koda je zapisana spodaj, shranjujemo vse Dk, ceprav bi lahko shranjevali samo Dk
in Dk−1 v vsakem koraku, torej je poraba prostora O(N2)
5.4.1 Standardna implementacija Floyd-Warshallovega al-
goritma
Algoritem 5.4.22: Standardni Floyd-Warshallov algoritem
for u:=1 to N step 1{for v:=1 to N step 1{
D 0 (u , v)=W(u , v ) ;
i f (u==v){Pi 0 (u , v)=NIL ;
}i f (u != v AND W(u , v)< I n t e g e r .MAX VALUE){
Pi 0 (u , v)=u ;
} else {Pi 0 (u , v)= n e d e f i n i r a n ;
}}
}for k:=1 to N step 1{
for u:=1 to N step 1{for v:=1 to N step 1{
i f (D (k−1)(u , k)+D (k−1)(k , v ) <= D (k−1)(u , v ) ){D k (u , v)=D (k−1)(u , k)+D (k−1)(k , v ) ;
Pi k (u , v)=Pi (k−1)(k , v ) ;
} else {D k (u , v)=D (k−1)(u , v ) ;
Pi k (u , v)=Pi (k−1)(u , v ) ;
}
5.4. FLOYD-WARSHALLOW ALGORITEM 53
}}
}
Kjer je
• Pi k je predzadnje vozlisce na najcenejsi poti, kjer lahko uporabimo le vo-
zlisca od 1 do k.
Element Pi k ni enak tistemu pri Bellman-Fordovem algoritmu, kjer je element
mnozica predzadnjih vozlisc na vsaki minimalni poti, ki ima dolzino najvec k od
vozlisca u do vozlisca v.
Ce definiramo πk(v) = Πk(s, v), potem πk vkljucuje drevo minimalnih poti iz
vozlisca s. Celotna mnozica, zajeta v πk, pa ne formira nujno drevesa.
5.4.2 Algebrska implementacija Floyd-Warshallovega algo-
ritma
Pri implementaciji algoritma z matricnimi in vektorskimi operacijami uporabimo
matriko Dn dimenzije N×N za shranjevanje cen poti (matriko cen). Inicializiramo
D0 = A oziroma D0(u, v) = W (u, v); D0(u, u) = 0
Rekurzivna definicijaD0 uposteva 2 moznosti, in sicer, ali minimalna pot iz vozlisca
u do vozlisca v, ki lahko vsebuje vozlisca od 1 do k, vsebuje vozlisce k ali ne.
Algoritem deluje tako, da izracuna teze minimalnih poti, ki vsebujejo vozlisce k
za vse pare vozlisc (u,v) naenkrat. Natancneje: k-ti stolpec Dk oziroma Dk(k, :)
vsebuje cene minimalnih poti, ki gredo skozi vozlisce k. Podobno k-ta vrstica
Dk(k, :) vsebuje cene minimalnih poti iz vozlisca k v katerokoli vozlisce u. Torej
je vse, kar moramo narediti, da dodamo vsak par teh vrednosti, tako dobimo cene
minimalnih poti, ki gredo skozi vozlisce k, in to storimo tako, da racunamo:
Dk = Dk−1min.+ (Dk−1(:, k)min.+Dk−1(k, :))
Algoritem izvede N mnozenj vektorjev, zato je njegova kompleksnost O(N3).
54 POGLAVJE 5. ALGORITMI
Algoritem 5.4.24: Algebrski Floyd-Warshallov algoritem
D=A;
for k:=1 to N step 1{D=D min.+ (D( : , k ) min.+D(k , : ) ) ;
}
Kjer je :
• A matrika cen;
• min.+ je mnozenje v polkolobarju (min,+), opisan pri Bellman-Fordovem
algoritmu;
• D(:,k) matrika, ki vsebuje vse vrstice in k-ti stolpec;
• D(k,:) matrika, ki vsebuje vse stolpce in k-to vrstico.
5.4.3 Rekonstrukcija minimalne poti
Poenostavljeno minimalno pot rekonstruiramo tako, da si vzporedno z matriko cen
D shranjujemo matriko PATH, ki je z D povezana tako:
• D(i,j)=cena poti med i in j;
• PATH(i,j)=predhodno vozlisce k vozlisca j, preko katerega smo prisli iz vo-
zlisca i do vozlisca j po minimalni poti;
• ce PATH(i,j)=0 in D(i,j)= ∞ to pomeni, da od vozlisca i do vozlisca j ne
obstaja nobena pot;
• ce PATH(i,j)=0 in D(i,j) 6= ∞ to pomeni, da na minimalni poti med vo-
zliscema i in j ni vmesnega vozlisca, minimalna pot je kar povezava med
vozliscema.
5.4. FLOYD-WARSHALLOW ALGORITEM 55
Vzporedno vodenje matrike PATH implementiramo tako, da se vsakic, ko se spre-
meni minimalna pot v polju D(i,j) spremeni tudi polje PATH(i,j), in sicer vstavimo
vozlisce, skozi katerega ravnokar ugotavljamo minimalno pot.
Algoritem 5.4.26: Vzdrzevanje vozlisc na minimalni poti
for m:=1 to N−1 step 1{for k:=1 to N step 1 {
for i :=1 to N step 1 {for j :=1 to N step 1{
i f (A[ i ] [ k]+A[ k ] [ j ]<A[ i ] [ j ] ){A[ i ] [ j ]=A[ i ] [ k]+A[ k ] [ j ] ;
path [ i ] [ j ]=k ;
}}
}}
}
Kjer je:
• A matrika cen;
• path matrika predhodnih vozlisc na minimalni poti.
Algoritem 5.4.28: Rekonstrukcija minimalne poti med i in j (Dobi-
Pot(i,j)
vmesnoVozl isce=path [ i ] [ j ] ;
i f ( vmesnoVozl isce =0 & A[ i ] [ j ] = I n t e g e r .MAX VALUE){Ni−pot i ;
}i f ( vmesnoVozl isce =0 & A[ i ] [ j ] n i I n t e g e r .MAX VALUE){
vrni−praznoPol j e ;
56 POGLAVJE 5. ALGORITMI
} else {vrni− DobiPot ( i , vmesnoVozl isce)+vmesnoVozl isce
+DobiPot ( vmesnoVozl isce , j ) ;
}
A =1
2
3
45
23
1
58
7
0 8 1 6 1111 0 12 2 3 1 7 0 5 10
13 2 14 0 5 8 3 9 5 0
PATH =
0 4 0 3 4 5 0 5 0 0 0 4 0 0 4 5 0 5 0 2 0 0 1 2 0
- DobiPot(1,2)=4- DobiPot(1,4)=3- DobiPot(1,3)=’ ‘- DobiPot(3,4)=’ ‘
Pot=1 3 4 2
Slika 5.8: Primer rekonstrukcije poti po Floyd-Warshallovem algoritmu
5.5 Primov algoritem
5.5.1 Minimalno vpeto drevo
Definicija DREVO je v teoriji grafov graf, v katerem sta poljubni dve tocki po-
vezani z natanko eno enostavno potjo. Drevo je v bistvu vsak povezan graf brez
ciklov. Gozd je nepovezana unija dreves [9].
Definicija VPETO DREVO T povezanega neusmerjenega grafa G je drevo, ki
ga sestavljajo vse tocke in nekatere (ali pa morda vse) povezave grafa G. Vpeto
5.5. PRIMOV ALGORITEM 57
drevo je izbira povezav, ki tvorijo drevo preko vseh tock. Zato velja, da je stevilo
povezav vpetega drevesa enako V-1, kjer je V stevilo oglisc grafa G. To pomeni,
da vsaka tocka lezi na drevesu, pri tem pa ne nastane noben cikel. Vpeto drevo
povezanega grafa G lahko definiramo tudi kot maksimalno mnozico povezav G,
ki ne vsebuje ciklov, ali pa kot minimalno mnozico vseh povezav, ki povezuje vse
tocke. [9]
Teza vpetega drevesa je vsota tez (cen) povezav, ki jih drevo vsebuje. Defini-
ramo jo takole:
w(T ) =∑e∈T
w(e)
Minimalno vpeto drevo je vpeto drevo, ki ima med vsemi vpetimi drevesi grafa
najmanjso tezo (ceno). Veljati mora w(T ) ≤ w(T ′) za vsako vpeto drevo T’.
Pri problemu minimalnega vpetega drevesa imamo dan neusmerjen graf G(E,V)
s cenam povezav w: E → R∞, kjer W (u, v) = ∞, ce med vozliscema u in v ni
povezave. Zaradi poenostavitve je W(v,v)=0 za vse v ∈ V .
Podoben problem kot je iskanje minimalnega vpetega drevesa, je iskanje minimal-
nega vpetega gozda v nepovezanem grafu, ki ga lahko resimo direktno s pomocjo
problema iskanja minimalnega vpetega drevesa v vsaki nepovezani komponenti
grafa. Za poenostavitev problema bomo predpostavljali, da je graf povezan.
Primov algoritem je eden od algoritmov, ki resujejo problem minimalnega vpe-
tega drevesa. Algebrska razlicica v splosnem nima tako dobrih zmogljivosti kot
standardna razlicica.
5.5.2 Standardna implementacija algoritma
Primov algoritem resuje problem minimalnega vpetega drevesa z ustvarjanjem
mnozice S, ki vsebuje povezave, vsebovane v vpetem drevesu. V vsaki iteraciji
v S dodamo “najblizjo” povezavo, ki se ni v S. Recemo, da je povezava (u,v)
“najcenejsa” povezava, ki ni v S, ce u ∈ S ∧ v /∈ S ∧W (u, v) = min{(u′, v′) : u′ ∈S ∧ v′ /∈ S}. Recimo, da je povezava (u,v) najcenejsa povezava, ki je se nimamo
v S in u ∈ S. Potem Primov algoritem posodobi S = S U {v} in T=T U {(u,v)}.
58 POGLAVJE 5. ALGORITMI
To ponovimo N-1 krat, na koncu je T nase vpeto drevo, S pa mnozica vozlisc, ki
so vsebovana v vpetem drevesu.
1
34
6
trenutno minimalnovpeto drevo
ostali graf
T G
2
34
6
trenutno minimalnovpeto drevo
ostali graf
T G
8
V vsaki iteraciji dodamo v minimalno vpeto drevo najcenejšo povezavo z grafom
Slika 5.9: Skica delovanja Primovega algoritma
Primov algoritem je v osnovi implementiran z uporabo prioritetne vrste. Prio-
ritetna vrsta je podatkovna struktura, ki dinamicno vzdrzuje zaporedje mnozice
objektov s kljuci in podpira naslednje operacije:
• INSERT(Q,x) : vstavi objekt s kljucem x v vrsto (Q=Q U {x})
• Q=BUILD-QUEUE(x1, x2, ..., xn): naredi vstavljanje objektov x1, x2, ..., xn
v prazno vrsto Q (Q={x1, x2, ..., xn}).
• EXTRACT-MIN(Q): izbrise in vrne element v Q z najmanjsim kljucem. Ce
predpostavimo, da imamo enolicne kljuce: ce kljuc(x) = miny∈Q, potem
Q=Q-{x}.
5.5. PRIMOV ALGORITEM 59
• DECREASE-KEY(Q,x,k): zmanjsa vrednost kljuca elementa x na vrednost
k, pri predpostavki, da k ≤ key(x). Tukaj je x kazalec na objekt, kateremu
manjsamo kljuc.
Naivna implementacija prioritetne vrste je neurejen seznam. Tukaj sta INSERT
in DECREASE-KEY trivialna in potrebujeta cas O(1). EXTRACT-MIN je O(V)
(kjer je V stevilo vozlisc v grafu), saj moramo v najslabsem primeru preiskati ce-
loten seznam vozlisc. Pri uporabi Fibonaccijeve kopice ima casovno kompleksnost
O(M + NlogN) (kjer je M stevilo povezav in N stevilo vozlisc na grafu).
Algoritem 5.5.30: Standardna implementacija Primovega algoritma
f o r each v i z V {key ( v)= I n t e g e r .MAX VALUE;
p i ( v)=NIL ;
}
cena =0;
s=Random( s i z V) ;
key ( s )=0;
Q=BUILD−QUEUE(V) ;
while (Q ni 0){u=EXTRACT−MIN(Q) ;
cena=cena + W( pi (u ) , u ) ;
f o r each u ; (u , v ) i z E {i f ( v i z Q & W(u , v ) < key ( v ) ){
DECREASE−KEY(Q, v ,W(u , v ) ) ;
p i ( v)=u ;
}}
}
Kjer je:
60 POGLAVJE 5. ALGORITMI
• random funkcija, ki nakljucno izbere vozlisce s iz V;
• pi shranjuje starse vozlisca.
5.5.3 Algebrska implementacija Primovega algoritma
Uporabimo redko matriko dimenzije N ×N A za shranjevanje cen povezav, vektor
s dimenzije 1×N za navajanje vsebnosti v mnozici S in vektor d dimenzije 1×Nza shranjevanje cen povezav, ki niso v S.
s in d vzdrzujemo takole:
s(v) =
{∞; v ∈ S0; sicer
d(v)=minu∈SW (u, v).
Ce v /∈ S, potem d(v) poda najcenejso povezavo, ki povezuje vozlisce v z S. Ce
v ∈ S, potem d(v) = 0. Algoritem najprej najde vozlisce, ki je najblizje S (kar
pomeni, da je povezava vmes najcenejsa). Ta korak izvede argmin cez celoten
vektor, zato potrebuje O(N) casa za vsako iteracijo. Sestevanje vektorja zmanjsa
kljuce vseh sosedov vozlisca u. Ta korak lahko traja O(N) casa za vsako iteracijo,
ampak v skupnem vsako povezavo posodobimo le enkrat, zato je iteracij v bistvu
O(M). Skupno ima torej algoritem kompleksnost O(N2).
Algoritem 5.5.32: Algebrska implementacija Primovega algoritma
s =0;
cena =0;
s=Random( s i z V) ;
s (1)= In t eg e r .MAX VALUE;
d=A( 1 , : ) ;
while s n i I n t eg e r .MAX VALUE{u=argmin{ s+v } ;
s (u)= I n t e g e r .MAX VALUE;
cena=cena+d(u ) ;
d=min{d ,A(u , : ) } ;
}
5.5. PRIMOV ALGORITEM 61
Kjer je:
• A matrika cen;
• d in s vektorja, opisana zgoraj;
• argmin funkcija, ki vrne indeks elementa, ki ima minimalno ceno sestevka
vektorjev s in v;
• min funkcija, ki sestavi vektorja v1 in v2 v v tako, da velja v[i] = min{v1[i], v2[i]}.
1
2
3
45
231
58
7
Cena minimalnegavpetega drevesa: 11
Slika 5.10: Racunanje cene minimalnega vpetega drevesa
5.5.4 Racunanje drevesa
Do zdaj smo zanemarili povezave minimalnega vpetega drevesa, racunali smo le
ceno minimalnega vpetega drevesa. Zapomniti si povezave je pri Primovem algo-
ritmu relativno enostavno z uporabo pristopa z 2-terkami. Vsak vnos v matriki
sosednosti A (in vektorju d) je 2-terka A(u, v) = (W (u, v), u). Edina sprememba
pri algoritmu je, da moramo shranjevati se vektor dimenzije 1 × N π, v katerega
shranimo vpeto drevo za vsa vozlisca v S.
Algoritem 5.5.34: Algebrska implementacija Primovega algoritma z racunanjem
drevesa
s =0;
cena =0;
s=Random( s i z V) ;
62 POGLAVJE 5. ALGORITMI
s (1)= In t eg e r .MAX VALUE;
d=A( 1 , : ) ;
p i= NIL ;
while s n i I n t eg e r .MAX VALUE{u=argmin{ s+v } ;
s (u)= I n t e g e r .MAX VALUE;
cena=cena+d(u ) ;
p i (u)=p
d=d min.+A(u , : ) ;
}
Ker elementi v vektorju d in matriki A natanko ustrezajo posameznim povezavam,
je ocitno, da ta razlicica algoritma pravilno vrne povezave vpetega drevesa in
skupno ceno teh povezav, ki je pravzaprav cena vpetega drevesa. Opazimo, da je
shranjevanje povezav enostavnejse kot shranjevanje minimalnih poti pri prejsnjih
algoritmih. Razlog je v tem, da vektor d hrani le povezave, medtem ko pri prejsnjih
algoritmih shranjujemo cele poti. Drugi razlog je struktura algoritma, tukaj ne
operiramo cez kak poseben polkolobar, zato ne potrebujemo kompleksne logike.
Poglavje 6
Testiranje algoritmov
6.1 Uvod v testiranje
V tem poglavju bomo testirali vse zgoraj opisane algebrske implementacije algo-
ritmov. Vsakega od teh algoritmov smo v programskem jeziku Java sprogramirali
na dva nacina. Prvi nacin je algebrska implementacija algoritma, ki pri zapisu
matrike uporablja standarni nacin zapisa matrike s poljem (tabelo), drugi pa je al-
gebrska implementacija algoritma, ki pri zapisu matrike uporablja enega od zgoraj
opisanih nacinov zapisa redke matrike. Pri vsakem od sprogramiranih metod bo
zraven tudi napisano, kateri nacin zapisa matrike uporablja. Vsi algoritmi so bili
napisani rocno, brez uporabe knjiznic za racunanje z matrikami ali pa za racunanje
z redkimi matrikami. Edini uporabljeni knjiznici sta bili java.util.LinkedList zaradi
uporabe LinkedListov pri nekaterih metodah ter java.io.* zaradi branja matrik iz
datoteke.
Sprogramirane metode so prilozene na zgoscenki.
Namen nasih testiranj algoritmov bo primerjava med standardnim zapisom matrike
in zapisom matrike v enem od nacinov zapisov redkih matrik. Nas cilj bo: za vsak
algoritem ugotoviti, kateri zapis matrike in pri kateri testni matriki bi se nam
bolj splacal uporabiti, to pomeni, da bi bil hitrejsi. Glede na to, da pricakujemo,
da se bo v vecini primerov cas pri standardnih zapisih in zapisih redkih matrik
spreminjal razlicno (pri standardnem zapisu se cas povecuje z dimenzijo matrike,
63
64 POGLAVJE 6. TESTIRANJE ALGORITMOV
pri zapisu redkih matrik pa bi se moral s stevilom nenicelnih elementov), bomo
verjetno lahko dolocili stevilo nenicelnih elementov pri neki dimenziji matrike, kjer
bo zapis z redko matriko se uporaben, pri vecjem stevilu nenicelnih elementov pa
ne vec, saj bo standardni zapis hitrejsi.
Vse testne matrike so v datotekah zapisane po vrsticah, ena vrstica v datoteki
pomeni eno vrstico v matriki. Pri vseh metodah smo matriko najprej prebrali v
pomnilnik, potem pa izvajali nadaljnje izracune na njej, saj smo tako prihranili
cas pri dostopu do elementov matrike.
Testni vektorji so v datotekah zapisani v eni vrstici, vrstica v datoteki je v bistvu
kar vektor sam. Tudi vektor smo pri vseh metodah, ki racunajo z vektorji, najprej
prebrali v pomnilnik in nato do elementov vektorja dostopali iz pomnilnika in ne
iz datoteke.
6.2 Mnozenje matrike z vektorjem
OPIS TESTA
Preverjali bomo zmogljivost mnozenja matrike z vektorjem, z razlicnimi zapisi
redkih matrik in s standardnim zapisom matrike s poljem. Mnozenje matrike z
vektorjem nas zanima, saj vsi nadaljni algoritmi v svojih izracunih uporabljajo
predvsem mnozeje matrike z vektorjem, zato bo to kljucna operacija, ki bo mocno
vplivala na ucinkovitost ostalih metod.
OPIS UPORABLJENIH METOD
• Standardni zapis s poljem (AR) - metoda Matrix.mnozenjeVektor
• CSR zapis redke matrike (CSR) - metoda Sparse.mnozenjeMatVecCSR
• MSR zapis redke matrike (MSR) - metoda Sparse.mnozenjeMatVecMSR
• Zapis redke matrike s terkami (TUP) - metoda Sparse.mnozenjeMatVecTER
Vsako metodo bomo pograli 300000-krat in izracunali povprecni cas trajanja vsake
metode, ki je zapisan v tabeli 6.1.
6.2. MNOZENJE MATRIKE Z VEKTORJEM 65
Cas je sicer odvisen od vec dejavnikov (zmogljivosti racunalnika...), ker pa bomo
vse te metode merili na istem racunalniku in pri enakih pogojih, lahko ta podatek
vzamemo kot pokazatelj zmogljivosti metode, ne moremo pa trditi, da bi katerakoli
od teh metod vsepovsod in v vseh pogojih delala toliko casa, kot je zapisano v tabeli
6.1.
Matrix.mnozenjeVektor(int[][] matrika1, int[] vektor)
Metoda opravi mnozenje matrike matrika1 z vektorjem vektor
(matrika1 x vektor). Mnozenje je implementirano po opisu mnozenja matrike z
vektorjem v podpoglavju 4.2.
Vhodni podatki:
• 2D matrika1 in 1D vektor, s katerim zelimo mnoziti.
Izhodni podatki:
• vektor v, za katerega velja v= matrika1 x vektor.
Sparse.mnozenjeMatVecCSR(int[] data, int[] ind, int[] poin, int[] x)
Metoda opravi mnozenje matrike A in vektorja x, ko je matrika v CSR zapisu
(Ax). Mnozenje je implementirano po algoritmu 3.4.1.
Vhodni podatki:
• data...polje z nenicelnimi vrednostmi matrike po vrsti po vrsticah;
• ind...polje z indeksi stolpcev teh vrednosti ind[i] je vrstica za podatek
data[i];
• poin...polje, ki pove s katerimi od vrednosti v data se zacne vrstica;
• x je vektor s katerim zelimo mnoziti matriko.
Izhodni podatki:
• vektor y, za katerega velja y = Ax,
Sparse.mnozenjeMatVecMSR(int[] data, int[] ind, int[] x)
Metoda opravi mnozenje matrike A in vektorja x, ko je matrika v MSR zapisu
(Ax). Mnozenje je implementirano po algoritmu 3.4.5.
Vhodni podatki:
66 POGLAVJE 6. TESTIRANJE ALGORITMOV
• data, ind so podatki o matriki A, predstavljeni v MSR nacinu;
• x vektor, s katerim mnozimo matriko.
Izhodni podatki
• vektor y, za katerega velja y = Ax.
Sparse.mnozenjeMatVecTER(int[] data, int[] col, int[] row, int[] x)
Metoda opravi mnozenje matrike A in vektorja x, ko je matrika v zapisu s terkami
(Ax). Mnozenje je implementirano po algoritmu 3.4.7.
Vhodni podatki:
• data, col, row so podatki o matriki A, predstavljeni v nacinu s terkami;
• x vektor, s katerim mnozimo matriko.
Izhodni podatki:
• vektor y, za katerega velja y = Ax.
TESTNE MATRIKE IN VEKTORJI
Pri testiranju bomo uporabili spodaj zapisane matrike in vektorje; matrike imajo
imena testX, kjer je X stevilo, vektorji pa vectorY, kjer je Y stevilo.
• test1 je matrika dimenzije 200 x 200, s 3776 nenicelnimi vrednostmi od 1
do 5.
• test2 je matrika dimenzije 200 x 200, z 10068 nenicelnimi vrednostmi od 1
do 5.
• test3 je matrika dimenzije 100 x 100, z 2100 nenicelnimi vrednostmi od 1
do 5.
• test4 je matrika dimenzije 100 x 100, s 763 nenicelnimi vrednostmi od 1 do
5.
• test5 je matrika dimenzije 300 x 300, s 17413 nenicelnimi vrednostmi od 1
do 5.
6.2. MNOZENJE MATRIKE Z VEKTORJEM 67
• test6 je matrika dimenzije 300 x 300, z 2365 nenicelnimi vrednostmi od 1
do 5.
• vector1 je vektor dimenzije 1 x 100, z 18 nenicelnimi vrednostmi od 1 do 5.
• vector2 je vektor dimenzije 1 x 200, s 30 nenicelnimi vrednostmi od 1 do 5.
• vector3 je vektor dimenzije 1 x 300, z 69 nenicelnimi vrednostmi od 1 do 5.
REZULTATI
MATRIKA test1 test2 test3 test4 test5 test6
V EKTOR vector2 vector2 vector1 vector1 vector3 vector3
AR 44864 44930 16900 16917 99463 99500
CSR 14980 38566 8819 5282 65960 13080
MSR 18585 49008 10719 4760 84116 13466
TUP 18105 47948 10316 4362 66060 13255
Tabela 6.1: Rezultati testiranj algoritmov za mnozenje matrike z vektorjem
*Opomba: Casi v tabeli so zapisani v nanosekundah.
Tabelo moramo brati navpicno, primer: pri matriki test1 in vektorju vector2 je
metoda AR delovala 44864 ns, metoda CSR 14980 ns in tako dalje.
OPAZANJA
Kot pricakovano, je pri metodi s standardnim zapisom matrike cas delovanja od-
visen od dimenzije matrike, ne pa od tega, koliko imamo nenicelnih elementov, saj
metoda vedno preracuna vsa polja, ne glede na vrednost. Vsem ostalim metodam
se cas delovanja povecuje s stevilom nenicelnih elementov, kar se je v nasem pri-
meru izkazalo za bolje, saj smo imeli za testne matrike redke matrike, ki imajo ve-
liko nicel. Med algoritmi, ki pri izracunih upostevajo stevilo nenicelnih elementov,
se je najbolje odrezal zapis v CSR obliki. Pri zelo majhnem stevilu nenicelnih ele-
mentov sta bila MSR in nacin s terkami malenkost hitrejsa, a nas bodo v splosnem
bolj zanimale vecje matrike. MSR nacin sicer ne zaostaja prav dosti za CSR
nacinom zapisa matrike, a v nasih algoritmih MSR zapis ne bo prisel v postev, saj
MSR nacin predvideva nenicelno diagonalo, kar pa pri matriki cen ni res. Najbolj
68 POGLAVJE 6. TESTIRANJE ALGORITMOV
ucinkovit pri mnozenju matrike z vektorjem je pri nasih testnih matrikah torej
nacin zapisa matrike s CSR zapisom.
Ker se je zapis redke matrike v CSR obliki najbolj obnesel ze pri mnozenju matrike
z vektorjem (kar je osnovna operacija za vse nadaljnje algoritme), bomo pri ostalih
algoritmih primerjali samo ta zapis z osnovnim zapisom matrike s poljem. Ce bomo
pri katerem algoritmu ugotovili, da bi bil lahko kateri od zapisov redkih matrik
zaradi nacina pregledovanja nenicelnih elementov boljsi, bomo v test vkljucili se
ta nacin zapisa.
Pricakujemo lahko, da bo pri nekaterih algoritmih vseeno hitrejsi algoritem s stan-
dardnim zapisom matrike s poljem, ne glede na to, da je osnovno mnozenje matrike
z vektorjem v tem zapisu pocasnejse, saj pri nekaterih algoritmih za zapis s CSR-
jem potrebujemo veliko dodatnih primerjav in pretvorb, ki jih pri navadnem zapisu
ne potrebujemo. To lahko ponekod poslabsa zmogljivost algoritma.
6.3 Iskanje v sirino (BFS algoritem)
OPIS TESTA
Preverjali bomo zmogljivost algoritma BFS, ki je teoreticno opisan v podpoglavju
5.1. Algoritem bomo implementirali s tremi razlicnimi zapisi redkih matrik, kar
pomeni, da bomo sprogramirali tri razlicne metode, ki prikazujejo delovanje algo-
ritma in vsaka uporablja drug zapis matrike.
Algoritem 6.3.36: BFS algoritem
B=A;
for i :=1 to s t s topen j s tep 1 {B=B OR.AND A;
}
• Standardni zapis s poljem (AR) - metoda Matrix.BFS
• CSR zapis redke matrike (CSR) - metoda Sparse.BFS_CSR_matrix
6.3. ISKANJE V SIRINO (BFS ALGORITEM) 69
• Zapis redke matrike s terkami (TUP)- metoda Sparse.BFS_TER
Algoritem bo iskal sosede v N-1 korakih, kjer je N stevilo vozlisc v grafu. Vsako
metodo bomo pognali 1000-krat in izracunali povprecni cas, ta cas je zapisan v
tabeli 6.2.
OPIS UPORABLJENIH METOD
Matrix.BFS(int[][] matrika,int k)
Metoda simulira algoritem za iskanje v sirino (BFS), implementirana je po algo-
ritmu 6.3.35. Pri delovanju uporablja mnozenje matrik v polkolobarju (AND,
OR), kjer so matrike zapisane v standardnem zapisu s poljem.
Vhodni podatki:
• sosedna matrika matrika;
• k je stevilo stopenj, do koder zelimo preiskovati sosede v sirino.
Izhodni podatki
• 2D matrika C, za katero velja: ce C[i][j] =1, potem iz vozlisca i v j lahko
pridemo v k. korakih
Pomozne metode:
1. Matrix.mnozenjeBinOR_AND(int[][] matrika2, int[][] matrika1)
Metoda izvede mnozenje 2 matrik, ki so zapisane v standardnem zapisu matrike s
poljem v kolobarju (OR,AND). Primer takega mnozenja je prikazan na sliki 5.2.
Vhodni podatki:
• matrika1 in matrika2 enakih dimenzij sta 2D matriki, ki ju zelimo zmnoziti
Izhodni podatki
• Rezultat je 2D matrika iste dimenzije kot matrika1 ali matrika2, taka, da
velja rezultat=matrika1 OR.AND matrika2.
Sparse.BFS_CSR_matrix(int[]data, int[] ind, int[] poin, int k)
70 POGLAVJE 6. TESTIRANJE ALGORITMOV
Metoda simulira algoritem za iskanje v sirino (BFS), implementirana je po algo-
ritmu, opisanem zgoraj. Pri delovanju uporablja mnozenje matrik v polkolobarju
(AND, OR), kjer so matrike zapisane v CSR zapisu redkih matrik.
Vhodni podatki:
• data, ind in poin so podatki o matriki A v CSR nacinu zapisa;
• k je stevilo stopenj, do koder nas zanimajo sosedi.
Izhodni podatki:
• matrika 2D C, ki nam pove, do katerih vozlisc pridemo v k korakih. Ce je v
C[i][j]=1, lahko iz i v j pridemo v k korakih.
Pomozne metode:
1. Sparse.mnozenjeMatCSR_OR_AND(int[] data1, int[] ind1,
int[] poin1, int[] data2, int[] ind2, int[] poin2)
Metoda izvede mnozenje 2 matrik, ki so zapisane v CSR zapisu v kolobarju
(OR,AND). Primer takega mnozenja je prikazan na sliki 5.2.
Vhodni podatki:
• data1, ind1, poin1 so podatki o matriki A, predstavljeni v nacinu CSR;
• data2, ind2, poin2 so podatki o matriki B, predstavljeni v nacinu CSR.
Izhodni podatki:
• matrika C dimenzije A ali B, za katero velja C=A OR.AND B.
2. Sparse.fromNormalToCSR(int[][] matrika)
Metoda izvede pretvorbo iz standardnega zapisa matrike v CSR zapis redke ma-
trike.
Vhodni podatki:
• Standardno zapisana matrika z 2D poljem matrika.
Izhodni podatki:
6.3. ISKANJE V SIRINO (BFS ALGORITEM) 71
• LinkedList, ki po vrsti vsebuje polja data, ind in poin za vhodno matriko.
Sparse.BFS_TER(int[]data, int[] row, int[] col, int k,int dim)
Metoda simulira algoritem za iskanje v sirino (BFS), implementirana je po algo-
ritmu, opisanem zgoraj. Pri delovanju uporablja mnozenje matrik v polkolobarju
(AND, OR),kjer so matrike zapisane v zapisu redkih matrik s terkami.
Vhodni podatki:
• data row in col so podatki o matriki A v nacinu zapisa s terkami;
• k je stevilo “stopenj”, do koder nas zanimajo sosedi;
• dim je stevilo vozlisc v osnovnem grafu.
Izhodni podatki:
• matrika 2D C, ki nam pove, do katerih vozlisc pridemo v k korakih. Ce je v
C[i][j]=1, lahko iz i v j pridemo v k korakih.
Pomozne metode:
mnozenjeMatTER_OR_AND(int[] data, int[] row, int[] col, int data1[],
int[] row1, int[] col1,int dim)
Metoda izvede mnozenje 2 matrik, ki so zapisane v zapisu s terkami v kolobarju
(OR,AND).
Vhodni podatki:
• data, col, row so podatki o matriki A, predstavljeni v nacinu s terkami;
• data1, col1, row1 so podatki o matriki B, predstavljeni v nacinu s terkami;
• dimenzija je stevilo vozlisc v osnovnem grafu.
Izhodni podatki:
• matrika C, za katero velja C=A OR.AND B.
TESTNE MATRIKE
• test7 je matrika dimenzije 200 x 200, z 2378 enicami.
72 POGLAVJE 6. TESTIRANJE ALGORITMOV
• test8 je matrika dimenzije 200 x 200, s 6218 enicami.
• test9 je matrika dimenzije 100 x 100, s 1632 enicami.
• test10 je matrika dimenzije 100 x 100, s 687 enicami.
• test11 je matrika dimenzije 100 x 100, z 49 enicami.
REZULTATI
MATRIKA test7 test8 test9 test10 test11
AR 4,77 4,58 0,23 0,23 4,87
CSR 6,05 6,47 0,41 3,84 0,11
TUP 21,75 60,24 2,04 0,89 0,04
Tabela 6.2: Rezultati testiranj algoritma BFS
*Opomba: Casi v tabeli so zapisani v 109ns.
Tabelo moramo brati navpicno, primer: pri matriki test7 je metoda AR delovala
4,77 109 ns in tako dalje.
OPAZANJA
Opazimo, da se vedno drzi, da se pri standardnem zapisu matrike cas izvajanja
povecuje z dimenzijo matrike in ne s stevilom nenicelnih elementov, kot pri zapisu
matrik z zapisi za redke matrike. Zaradi kompleksnosti zapisa redke matrike in
posledicno kompleksnosti izracunov s tem zapisom matrike, se ta zapis izkaze za
slabsega. V zadnjem primeru, ko je nenicelnih elementov res malo v primerjavi
s celotnim stevilom elementov, sta oba nacina zapisa matrike z redkimi matri-
kami boljsa, saj morata pregledati res malo elementov v primerjavi s standardnim
zapisom matrike, ki vedno pregleda vse mozne. Zapis redke matrike v nacinu s
terkami je boljsi od standardnega zapisa in CSR nacina zapisa, razen v zadnjih
dveh primerih (test10 in test11), ko je pri testu 10 boljsi od CSR nacina zapisa in
pri testu11 boljsi od obeh. Zapis s terkami se v teh primerih izkaze za boljsega,
ker je dostop do elementov pri tem zapisu enostavnejsi kot zapis CSR, pri katerem
direktno dostopamo le do stolpca elementa, vrstico pa je treba iskati. Pri zapisu s
terkami imamo podatka o vrstici in stolpcu vedno znana.
6.4. ISKANJE MINIMALNIH POTI 73
Opazimo, da obstajajo testne matrike, za katere je boljsi standardni zapis matrike,
in da obstajajo tudi testne matrike, za katere je boljsi zapis CSR. Glede na to, da
na zmogljivost metode s standardnim zapisom matrike vpliva le dimenzija matrike,
na zmogljivost metode z zapisom CSR pa vpliva stevilo nenicelnih elementov, na
nobeno od teh metod pa ne vpliva lega (vrstica in stolpec) nenicelnih elementov,
moramo najti matriko z dolocenim stevilom nenicelnih elementom, pri kateri je se
boljsi zapis matrike CSR; ko pa dodamo nekaj nenicelnih elementov, pa je ze boljsi
standardni zapis matrike. Glede na to, da tudi pri 1000 ponovitvah ne dobimo
vsakic identicnega casa izvajanja metode, ne bomo mogli dolociti te meje na razliko
enega nenicelnega elementa, zato smo tudi rekli, da bomo vzeli priblizno mejo z
moznimi odstopanji v nekaj vec ali manj nenicelnih elementov.
Zelimo torej najti pribizno mejo v stevilu nenicelnih elementov pri matriki di-
menzije 200 x 200, kjer je metoda z zapisom redke matrike CSR se boljsa kot pa
metoda, ki uporablja standardni zapis matrike.
Testa smo se lotili tako, da smo zgenerirali testno matriko dimenzije 200 x 200 z
200 nenicelnimi elementi, za katero smo ugotovili, da je metoda s CSR zapisom
matrike boljsa, nato smo dodajali nenicelne elemente na poljubna mesta (kot smo
ugotovili, mesto elementov ni pomembno), dokler nismo prisli do stevila nenicelnih
elementov v matriki, ko je metoda s standardnim zapisom matrike postala hitrejsa
od tiste s CSR zapisom. Ta meja je pri matriki dimenzije 200 x 200 priblizno pri
205 nenicelnih elementih (matrika, ki je med testiranjem nastala in je na koncu
pokazala priblizno mejo, ko je metoda s CSR nacinom zapisa se hitrejsa od metode
s standardnim zapisom, je test adj).
6.4 Iskanje minimalnih poti
OPIS TESTA
Preverjali bomo zmogljivost algoritma iskanje minimalnih poti, ki je teoreticno
opisan v podpoglavju 5.2. Algoritem bomo implementirali z dvema metodama,
ki bosta uporabljali razlicna zapisa matrik. Spodnji metodi sta sprogramirani po
metodi 5.2.13:
74 POGLAVJE 6. TESTIRANJE ALGORITMOV
• Standardni zapis s poljem (AR) - metoda Matrix.iskanjeNajkrajsihPoti
• CSR zapis redke matrike (CSR) - metoda Sparse.iskanjeNajkrajsihPotiCSR
Vsako metodo bomo pognali 1000-krat in izracunali povprecni cas, ki je zapisan v
tabeli 6.3.
OPIS UPORABLJENIH METOD
Matrix.iskanjeNajkrajsihPoti(int[][] matrika)
Z metodo iscemo cene minimalnih poti za vse mozne pare vozlisc grafa, matrike,
s katerimi se opravijo izracuni, so zapisane s standardnim zapisom s poljem. Al-
goritem je implementiran po psevdokodi 5.2.13.
Vhodni podatki:
• matrika cene matrika.
Izhodni podatki:
• matrika, ki vsebuje cene minimalnih poti za vse pare vozlisc grafa.
Pomozne metode
1. Matrix.mnozenjeMinPlus(int[][] matrika)
Metoda izvede kvadriranje matrike v polkolobarju (min,+), pri cemer je matrika
v standardnem zapisu s poljem. Primer racunanja v polkolobarju (min,+) in
algoritem, po katerem je implementirana metoda je v podpoglavju 5.2.
Vhodni podatki:
• 2-dimenzionalna matrika matrika.
Izhodni podatki:
• 2-dimenzionalna matrika C, za katero velja C=matrika x matrika v kolo-
barju (min,+).
Sparse.iskanjeNajkrajsihPotiCSR(int[]data, int[] ind, int[] poin)
Metoda simulira delovanje algoritma minimalne poti, pri cemer so matrike, ki so
uporabljene za izracune zapisane v CSR zapisu. Algoritem je implementiran po
psevdokodi 5.2.13.
Vhodni podatki:
6.4. ISKANJE MINIMALNIH POTI 75
• data, ind, poin so podatki o matriki cen A podani v CSR nacinu zapisa.
Izhodni podatki:
• LinkedList s podatki data, ind, poin v tem vrstnem redu matrike C, za
katero velja, da je v C[i][j] minimalna cena poti med vozliscema i in j .
Pomozne metode
1. Sparse.fromNormaltoCSR_nesk(int[][] matrika)
Metoda izvede pretvorbo iz normalne matrike v CSR; kjer neskoncne vrednosti
obravnavamo kot 0 (shranjujemo vrednosti razlicne od ∞).
Vhodni podatki:
• standardno zapisana matrika z 2-dimenzionalnim poljem.
Izhodni podatki:
• LinkedList, ki po vrsti vsebuje polja data, ind, poin za vhodno matriko.
2. Sparse.mnozenjeMatMinPlus_CSR(int[]data,int[] ind, int[] poin)
Metoda izvede mnozenje 2 matrik (enakih dimenzij) v kolobarju (min,+), pri cemer
je matrika zapisana s CSR zapisom. Primer racunanja v polkolobarju (min,+) in
algoritem, po katerem je implementirana metoda, je v podpoglavju 5.2.
Vhodni podatki:
• data, ind, poin so podatki o matriki A v CSR nacinu zapisa, kjer je CSR
nacin prilagojen tako, da hrani podatke razlicne od neskoncno.
Izhodni podatki:
• matrika C, za katero velja C = A min.+ A.
TESTNE MATRIKE
• test13 je matrika dimenzije 200 x 200, s 3766 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test14 je matrika dimenzije 200 x 200, z 10015 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
76 POGLAVJE 6. TESTIRANJE ALGORITMOV
• test15 je matrika dimenzije 100 x 100, z 2043 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test16 je matrika dimenzije 100 x 100, s 1080 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test17 je matrika dimenzije 100 x 100, s 86 vrednostmi od 1 do 5, po dia-
gonali so nicle, drugje pa ∞.
REZULTATI
MATRIKA test13 test14 test15 test16 test17
AR 17,64 16,93 1,58 1,76 18,04
CSR 32,98 32,78 3,74 3,83 5,73
Tabela 6.3: Rezultati testiranj algoritma iskanja minimalnih poti
*Opomba: Casi v tabeli so zapisani v 107ns.
Tabelo moramo brati navpicno, primer: pri matriki test13 je metoda AR delovala
17,64 107 ns in tako dalje.
OPAZANJA
Pri metodi, ki uporablja standardni zapis matrike, se cas izvajanja povecuje z
dimenzijo matrike in ne s stevilom nenicelnih elementov kot pri zapisu CSR. Zapis
s CSR se v vecini primerov izkaze za slabsega, razen v zadnjem primeru, ko je
nenicelnih elementov res malo v primerjavi s celotnim stevilom elementov, ki jih
pregleda algoritem pri standardnem zapisu matrike.
Enako kot pri BFS algoritmu ugotovimo, da ocitno obstajajo testne matrike (tiste,
ki imajo zelo malo stevilo nenicelnih elementov), pri katerih je metoda s CSR
zapisom boljsa od metode s standardnim zapisom matrike. Kot smo ze ugotovili,
lega nenicelnega elementa ne vpliva na zmogljivost metode, pomembno je le stevilo
nenicelnih elementov
Kaksna pa bi tu bila meja, ko je CSR zapis se boljsi kot standardni?
Zaceli bomo z matriko dimenzije 200 x 200, ki ima 200 nenicelnih (in razlicnih
od ∞ ) elementov. Opazimo, da je tu metoda, ki uporablja CSR zapis matrike,
6.5. BELLMAN-FORDOV ALGORITEM 77
boljsa. Matriki na poljubna mesta (ki niso pomembna) dodajamo nenicelne (in
razlicne od ∞ ) elemente, dokler ni metoda s standardnim zapisom boljsa.
Pri matriki dimenzije 200 x 200 je meja priblizno pri 230 elementih, razlicnih od
∞ (mejo smo dosegli z nastankom matrike test cost).
6.5 Bellman-Fordov algoritem
OPIS TESTA
Preverjali bomo zmogljivost Bellman-Fordovega algoritma. Implementirali bomo
algebrsko razlicico algoritma z dvema metodama, ki uporabljata razlicna zapisa
matrik in bomo za vsakega od teh zapisov preverjali 2 nacina implementacije
algoritma, ki sta opisana v podpoglavju 5.3. Oba nacina sta implementirana
po psevdokodi, ki je zapisana v ze prej omenjenem podpoglavju.
V prvem delu testiranja bomo testirali naslednje metode, pri katerih si shranjujemo
samo ceno minimalne poti za poljubno vozlisce, ne pa tudi poti same. Brez izgube
za splosnost bomo v nasem primeru vedno iskali minimalne poti za prvo vozlisce.
Implementirane metode:
• standardni zapis s poljem (AR1) - Matrix.BellmanFord_prvaVerzija_normal
• standardni zapis s poljem (AR2) - Matrix.BellmanFord_drugaVerzija_normal
• CSR zapis redke matrike (CSR1) - Sparse.BellmanFord_prvaVerzija
• CSR zapis redke matrike (CSR2) - Sparse.BellmanFord_drugaVerzija
Vsako metodo bomo pognali 100-krat in izracunali povprecni cas, ki je zapisan v
tabeli 6.4.
OPIS UPORABLJENIH METOD
Matrix.BellmanFord_prvaVerzija_normal(int[][] matrika, int vozlisce)
Metoda simulira Bellman-Fordov algoritem, implementiran tako, da racunamo
samo cene minimalnih poti od zelenega vozlisca do vseh ostalih in ne vseh cen
minimalnih poti za vse mozne pare vozlisc. Implementacija je narejena na prvi
nacin, po algoritmu 5.3.17. Metoda uporablja standardni zapis matrike s poljem.
78 POGLAVJE 6. TESTIRANJE ALGORITMOV
Vhodni podatki:
• 2-dimenzionalna matrika cen matrika;
• indeks vozlisca vozlisce za katerega nas zanimajo minimalne poti (1-N).
Izhodni podatki:
• vektor d, ki vsebuje cene minimalnih poti od zelenega vozlisca do vseh ostalih
d[i]=a pomeni, da je a cena minimalne poti od vozlisca vozlisce do i.
Pomozne metode
1. Matrix.mnozenjeMINPLUSZDesne(int[][] matrika, int[] vektor)
Metoda izvede mnozenje vektorja z matriko (xA) v polkolobarju (min,+), kjer
metoda uporablja standardni nacin zapisa matrike s poljem. Primer racunanja v
polkolobarju (min,+) je v podpoglavju 5.2.
Vhodni podatki:
• 2-dimenzionalna matrika matrika;
• vektor vektor, s katerim zelimo mnoziti.
Izhodni podatki:
• vektor rezultat, za katerega velja rezultat = vektor min.+ matrika.
Matrix.BellmanFord_drugaVerzija_normal(int[][] matrika, int vozlisce)
Metoda simulira Bellman-Fordov algoritem, implementiran tako, da izracuna vna-
prej cene minimalnih poti za vse pare vozlisc grafa in na koncu izbere vrstico, ki
vsebuje minimalne poti za zeleno vozlisce. Ta nacin je v podpoglavju 5.3. opi-
san pod drugo verzijo, implementacija je narejena po algoritmu 5.3.19. Metoda
uporablja zapis matrike v standardnem zapisu s poljem.
Vhodni podatki:
• 2-dimenzionalna matrika cen matrika;
• indeks vozlisca vozlisce za katerega nas zanimajo minimalne poti (1-N).
6.5. BELLMAN-FORDOV ALGORITEM 79
Izhodni podatki:
• vektor d, ki vsebuje cene minimalnih poti od zelenega vozlisca do vseh ostalih
d[i]=a, pomeni, da je a cena minimalne poti od vozlisca vozlisce do i.
Pomozne metode
1. Matrix.iskanjeNajkrajsihPoti(int[][] matrika)
2. Matrix.mnozenjeMINPLUSZDesne(int[][] matrika, int vozlisce)
Sparse.BellmanFord_prvaVerzija(int[]data,int[] ind, int[] poin,
int vozlisce)
Metoda simulira Bellman-Fordov algoritem, implementiran tako, da racunamo
samo cene minimalnih poti od zelenega vozlisca do vseh ostalih in ne vseh cen
minimalnih poti za vse mozne pare vozlisc. Implementacija je narejena po algo-
ritmu 5.3.19, metoda uporablja CSR zapis matrike.
Vhodni podatki:
• data, ind, poin so podatki o matriki cen A podai s CSR zapisom;
• vozlisce je indeks vozlisca (1-N), za katerega nas zanimajo minimalne poti.
Izhodni podatki:
• vektor d, za katerega velja, da je v d[i] cena minimalne poti od vozlisca v
spremenljivki vozlisce do i.
Pomozne metode
1. Sparse.mnozenjeMatvec_MinPlusZDesne(int[]data,int[] ind,
int[] poin, int[] x)
Metoda izvede mnozenje vektorja in matrike xA v kolobarju (min,+), kjer me-
toda uporablja CSR zapis matrike. Primer racunanja v polkolobarju (min,+) je v
podpoglavju 5.2.
Vhodni podatki:
• data, ind, poin so podatki o matriki A, podani v CSR zapisu;
• x je vektor, s katerim zelimo mnoziti.
80 POGLAVJE 6. TESTIRANJE ALGORITMOV
Izhodni podatki:
• vektor y, za katerega velja y = x min.+ A.
Sparse.BellmanFord_drugaVerzija(int[]data,int[] ind, int[] poin,
int vozlisce)
Metoda simulira Bellman-Fordov algoritem, implementiran tako, da izracuna vna-
prej cene minimalnih poti za vse pare vozlisc grafa in na koncu izbere vrstico, ki
vsebuje minimalne poti za zeleno vozlisce. Metoda je implementirana po algoritmu
5.3.19.
Vhodni podatki:
• data, ind, poin so podatki o matriki cen A, podani v CSR zapisu;
• vozlisce je indeks vozlisca (1-N), za katerega nas zanimajo minimalne poti.
Izhodni podatki:
• vektor d, za katerega velja, da je v d[i] cena minimalne poti od vozlisca v
spremenljivki vozlisce do i.
Pomozne metode:
1. Sparse.iskanjeNajkrajsihPotiCSR(int[] data, int[] ind,
int[] poin,int vozlisce)
2. Sparse.mnozenjeMatvec_MinPlusZDesne(int[] data, int[] ind,
int[] poin, int x)
TESTNE MATRIKE
• test13 je matrika dimenzije 200 x 200, s 3766 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test14 je matrika dimenzije 200 x 200, z 10015 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test15 je matrika dimenzije 100 x 100, z 2043 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
6.5. BELLMAN-FORDOV ALGORITEM 81
• test16 je matrika dimenzije 100 x 100, s 1080 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test17 je matrika dimenzije 200 x 200, s 86 vrednostmi od 1 do 5, po dia-
gonali so nicle, drugje pa ∞.
REZULTATI
MATRIKA test13 test14 test15 test16 test17
AR1 28,31 26,91 2,91 3,75 26,28
AR2 178,46 176,20 15,80 17,67 180,36
CSR1 50,82 61,85 7,32 6,71 42,90
CSR2 415,69 411,17 46,86 47,67 57,85
Tabela 6.4: Rezultati testiranj Bellman-Fordovega algoritma brez shranjevanja
poti
*Opomba: Casi v tabeli so zapisani v 106ns.
Tabelo moramo brati navpicno, primer: pri matriki test13 je metoda AR delovala
28,31 106 ns in tako dalje.
OPAZANJA
Prva verzija Bellman-Fordovega algoritma je pocasnejsa, ce matriko shranjujemo
v CSR obliki, saj je mnozenje v x A (vektorja z matriko iz leve strani) pocasnejse
v tej obliki, kot pa v standardnem zapisu matrike. Pri prvi verziji se bolj splaca
uporabiti standardni zapis matrike, tudi, ce je nenicelnih elementov zelo malo, kar
lahko vidimo pri matriki test17. Druga verzija Bellman-Fordovega algoritma je
sicer pri matriki v CSR obliki se vedno pocasnejsa v vecini primerov, a pri test17
vidimo, da se pri malem stevilu nenicelnih elementov vseeno bolj splaca.
Pri prvi verziji stevila elementov, razlicnih od∞, ko se nam bolj splaca CSR zapis
sploh ne bomo iskali meje, ko bi bil CSR zapis boljsi, saj je metoda v vseh primerih
zaostajala za drugo s standardnim zapisom matrike, tudi pri test17, ko je takih
elementov zelo malo.
Pri drugi verziji implementacije algoritma bomo mejno stevilo elementov, razlicnih
od ∞, poiskali na enak nacin, kot smo to storili pri zgornjih primerih. Zacnemo z
82 POGLAVJE 6. TESTIRANJE ALGORITMOV
matriko dimenzije 200 x 200, ki ima 200 elementov, razlicnih od ∞. Opazimo, da
je v tem primeru hitrejsa metoda, ki za zapis matrike uporablja standardni zapis
s poljem. Matriki odvzemamo elemente, razlicne od ∞, tako da jih nadomestimo
z elementom ∞. Mejno stevilo elementov, razlicnih od ∞, ko se nam CSR zapis
matrike pri matriki dimenzije 200 x 200 splaca, dobimo nekje pri 170 elementih,
razlicnih od ∞, (mejo smo dosegli z nastankom matrike matriki test cost1). Taka
matrika nikoli ne more biti sosedna matrika povezanega grafa, saj bi v tem primeru
potrebovali vsaj 199 povezav.
Zgornje testne matrike so bile generirane nakljucno, zato pripadajoci grafi niso
nujno povezani. Pri matrikah, ki jih dobimo iz povezanega grafa, pa druga verzija
metode z zapisom matrike CSR delujejo bolje, a v vecini primerov se vedno slabse,
kot ce zapisemo matriko na standarden nacin. Testiranje za ugotavljanje mejnega
stevila elementov, ko bi se nam bolj splacala uporaba metode s CSR zapisom ma-
trike, sedaj ponovimo na sosedni matriki povezanega grafa. Zacnemo z matriko
dimenzije 200 x 200, z 200 elementi, razlicnimi od ∞, ki je sosedna matrika pove-
zanega grafa, in ugotovimo, da je v tem primeru metoda s CSR zapisom matrike
hitrejsa. Dodajamo elemente, razlicne od ∞, dokler metoda s standardnim zapi-
som matrike ne postane hitrejsa. Mejno stevilo, ko se nam zapis CSR se splaca, je
pri matriki dimenzije 200 x 200 priblizno pri 252 elementih, razlicnih od ∞.
Po ugotovitvi, da rezultati, dobljeni pri zgornjih testnih matrikah, ki niso bile
nujno sosedne matrike povezanih grafov, morda niso pokazatelji prave slike, smo
ponovili testiranja na naslednjih matrikah, ki so sosedne matrike povezanih grafov
• test18 je matrika dimenzije 200 x 200, s 4860 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test19 je matrika dimenzije 100 x 100, s 1863 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test20 je matrika dimenzije 300 x 300, z 9750 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
Vsako metodo smo pognali 100-krat in izracunali povprecni cas, ki je zapisan v
tabeli 6.5.
6.5. BELLMAN-FORDOV ALGORITEM 83
MATRIKA test18 test19 test20
AR1 40,12 5,25 156,12
AR2 179,88 17,06 1099,89
CSR1 68,03 7,45 174,33
CSR2 414,89 47,64 1553,40
Tabela 6.5: Rezultati testiranj Bellman-Fordovega algoritma na povezanih grafih
*Opomba: Casi v tabeli so zapisani v 106ns.
OPAZANJA
Slika tudi na povezanih grafih ni bistveno drugacna, se vedno se nam v vecini
primerov bolj splaca uporabiti standardni zapis matrike. Prva verzija je pri stan-
dardnem zapisu matrike hitrejsa kot druga, pri CSR zapisu pa je druga verzija
algoritma hitrejsa kot prva.
DRUGI DEL TESTA
V drugem delu testiranja bomo za ilustracijo testirali prvo verzijo Bellman-Fordovega
algoritma s standardnim zapisom matrike, ki vraca ceno minimalnih poti do dru-
gih vozlisc iz enega vozlisca, in tudi polje, iz katerega rekonstruiramo pot samo.
Prvo verzijo bomo prikazali, ker se je v prejsnjem testiranju izkazalo, da je hi-
trejsa od druge. Glede na to, da shranjevanje poti lahko le upocasni metodo,
ne pricakujemo, da bi lahko s shranjevanjem poti postala druga verzija boljsa od
prve. Prav tako smo ze v prvem testiranju ugotovili, da je metoda z zapisom
CSR veliko slabsa, zato ne pricakujemo, da bi se s shranjevanjem poti sedaj slika
obrnila. Zaradi tega implementacije z izracunavanjem poti sploh ne bomo delali
z zapisom matrike CSR. Brez izgube za splosnost bomo v nasem primeru vedno
iskali minimalne poti za prvo vozlisce.
• Standardni zapis s poljem (AR) - Matrix.BellmanFord_prvaVerzija_normal_path
Metodo bomo pognali 100-krat in izracunali povprecni cas, ki je zapisan v tabeli
6.6. Teste bomo opravili na sosednih matrikah povezanih grafov (test18, test19 in
test20).
OPIS UPORABLJENIH METOD
84 POGLAVJE 6. TESTIRANJE ALGORITMOV
Matrix.BellmanFord_prvaVerzija_normal_path(int[][] matrika,
int vozlisce)
Metoda simulira Bellman-Fordov algoritem, implementiran po prvi verziji, ki vraca
tudi pot in ne samo ceno minimalnih poti. Metoda pri zapisu matrik uporablja
standardni zapis matrike s poljem.
Vhodni podatki:
• 2-dimenzionalna matrika cen matrika;
• indeks vozlisca, za katerega nas zanimajo minimalne poti.
Izhodni podatki:
• LinkedList, ki vsebuje vektor minimalnih poti za doloceno vozlisce in vektor
predhodnih vozlisc, preko katerih smo prisli do minimalne cene poti.
Pomozne metode
1. Matrix.mnozenjeMINPLUSZDesne(int[][] matrika, int[] x)
MATRIKA test18 test19 test20
AR 44,11 5,45 158,12
Tabela 6.6: Rezultati testiranj Bellman-Fordovega algoritma, ki vraca tudi mini-
malno pot
*Opomba: Casi v tabeli so zapisani v 106ns.
OPAZANJA
V primerjavi z zgornjo verzijo algoritma, ki ne vraca tudi minimalne poti, ampak
samo ceno le-te, opazimo, da dodatno shranjevanje predhodnih vozlisc ne porabi
opazno veliko casa, saj je predhodnik direktno dostopen, zato shranjevanje le-tega
predstavlja le eno operacijo shranjevanja elementa v polje.
6.6 Floyd-Warshallov algoritem
OPIS TESTA
6.6. FLOYD-WARSHALLOV ALGORITEM 85
Preverjali bomo zmogljivost Floyd-Warshallovega algoritma, implementirali bomo
algebrsko razlicico Floyd-Warshallovega algoritma z dvema razlicnima zapisoma
matrik. V ta namen bomo preizkusali dve metodi, obe vrneta cene minimalnih
poti med vsemi pari vozlisc v grafu in indekse predhodnikov na tej poti, le da ena
za zapis matrike uporablja standardni zapis, druga pa CSR zapis. Obe metodi sta
implementirani po psevdokodi 5.4.23. Tudi pot v obeh metodah se izracunava,
kot je opisano v podpoglavju 5.4. V primeru, da je indeks predhodnika 0, to
pomeni, da je povezava direktna ze v osnovnem grafu.
Implementirani metodi:
• standardni zapis s poljem (AR) - metoda Matrix.FloydWarshall_normal
• CSR zapis redke matrike (CSR) - metoda Sparse.FloydWarshall
Metodi bomo pognali 10000-krat in izracunali povprecni cas, ki je zapisan v tabeli
6.7.
OPIS UPORABLJENIH METOD
Matrix.FloydWarshall_normal(int[][] ma)
Metoda simulira delovanje algoritma Floyd Warshall. Uporablja standardni zapis
matrike s poljem. Implementirana je po algoritmu 5.4.23.
Vhodni podatki:
• 2-dimenzionalna matrika ma, ki je matrika cen grafa, za katerega nas zani-
majo minimalne poti med vozlisci.
Izhodni podatki:
• 3-dimenzonalna matrika - rezultat, ki vsebuje cene minimalnih poti v
rezultat[][][1] in indekse predhodnih vozlisc, preko katerih smo prisli
do minimalne cene poti v rezultat[][][0].
Sparse.FloydWarshall(int[] data, int[] ind, int[] poin)
Metoda simulira delovanje Floyd-Warshallovega algoritma. Metoda uporablja
CSR zapis matrike, implementirana je po algoritmu 5.4.23.
Vhodni podatki:
86 POGLAVJE 6. TESTIRANJE ALGORITMOV
• data, ind, poin so podatki o matriki cen A, podani v CSR zapisu.
Izhodni podatki:
• 3-dimenzionalna matrika - rezultat, ki vsebuje cene minimalnih poti med
vsemi pari vozlisc in predhodnike na tej minimalni poti.
Pomozne metode:
1. Sparse.mnozenjeMatMinPLus_CSR_postop
(int[]data,int[] ind, int[] poin, int stop,int[] pred)
Metoda izvaja ”kvadriranje”dela matrike v kolobarju (min,+) ((D(:, stop) min.+
D(stop, :)).
Vhodni podatki:
• data, ind, poin so podatki o matriki A, podani v CSR zapisu;
• stop je stevilo, do katerega zelimo mnoziti stolpce in vrstice matrike;
• pred je tabela trenutnih predhodnikov, preko katerih smo prisli do trenutnih
minimalnih poti.
Izhodni podatki:
• 3D matrika - rezultat, ki vsebuje cene minimalnih poti med vsemi pari
vozlisc in predhodnike na tej minimalni poti.
2. fromNormaltoCSR_nesk3D(int[][][] matrix)
Metoda, ki iz standardne oblike zapisa matrike v 3D tabeli z dodanimi predniki
pretvori v CSR zapis (kjer se vrednosti ∞ obravnavajo kot 0).
Vhodni podatki:
• 3-dimenzionalna matrika matrix.
Izhodni podatki:
• data, int, poin so podatki o matriki v CSR obliki zapisa;
• pred so podatki, vsebovani v A[][][0].
6.6. FLOYD-WARSHALLOV ALGORITEM 87
3. Sparse.FromCSRToNormal(int[] data, int[] ind, int[] poin,int[] pred)
Metoda pretvori matriko, podano v CSR nacinu, v standardni zapis matrike s
3-dimenzionalnim poljem.
Vhodni podatki:
• data, int, poin so podatki o matriki, podani v CSR nacinu;
• pred so podatki o prednikih, ki jih moramo vkljuciti v matriko.
Izhodni podatki:
• 3-dimenzionalna matrika C, ki v C[][][1] vsebuje elemente matrike, v C[][][0]
pa pripadajoce elemente iz tabele pred.
TESTNE MATRIKE
• test18 je matrika dimenzije 200 x 200, s 4860 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test19 je matrika dimenzije 100 x 100, s 1863 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test20 je matrika dimenzije 300 x 300, z 9750 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test21 je matrika dimenzije 200 x 200, z 2128 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test22 je matrika dimenzije 100 x 100, s 177 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
Vse matrike so sosedne matrike povezanih grafov.
REZULTATI
*Opomba: Casi v tabeli so zapisani v 106ns.
Tabelo moramo brati navpicno, primer: pri matriki test18 je metoda AR delovala
36,90 106 ns in tako dalje.
OPAZANJA
88 POGLAVJE 6. TESTIRANJE ALGORITMOV
MATRIKA test18 test19 test20 test21 test22
AR 36,90 5,12 119,54 37,43 5,06
CSR 176,90 21,75 638,28 170,54 16,00
Tabela 6.7: Rezultati testiranj Floyd-Warshallovega algoritma
Metoda, ki uporablja za zapis matrike CSR zapis, je veliko slabsi v vecini primerov.
Definitivno se nam bolj splaca uporabiti standardni nacin zapisa matrike. Problem
zapisa CSR je, da pri mnozenju 2 matrik potrebujemo direktni dostop do indeksov
elementov, ki pa jih pri tem zapisu nimamo na voljo. Zaradi tega je potrebno
veliko pretvorb iz enega zapisa v drugega, da ugotovimo indekse elementov matrike
in izvedemo mnozenje dveh matrik. Vse to pa seveda traja veliko dlje kot pri
standardnem zapisu matrike, ko imamo te podatke vedno neposredno na voljo.
6.7 Primov algoritem
OPIS TESTA
Preverjali bomo zmogljivost Primovega algoritma. Implemetirali bomo algebrski
Primov algoritem, in sicer z dvema metodama, od katerih vsaka uporablja drug
nacin zapisa matrike. Za vsakega od teh zapisov smo implementirali metodo, ki
po Primovem algoritmu vrne ceno minimalnega vpetega drevesa, ter metodo, ki
po Primovem algoritmu vrne minimalno vpeto drevo samo. Torej imamo skupaj
4 metode, dve po dve uporabljata enak zapis matrike in dve po dve racunata ceno
drevesa ali pa drevo samo:
• standardni zapis s poljem (ARc) - metoda Matrix.Primov_normal
• standardni zapis s poljem (ARp) - metoda Matrix.PrimovTree_normal_path
• CSR zapis redke matrike (CSRc) - metoda Sparse.Primov_CSR
• CSR zapis redke matrike (CSRp) - metoda Sparse.Primov_CSR_path
Metode bomo pognali 10000-krat in izracunali povprecni cas, ki je zapisan v tabeli.
6.8.
6.7. PRIMOV ALGORITEM 89
OPIS UPORABLJENIH METOD
Matrix.Primov_normal(int[][] matrika)
Metoda simulira Primov algoritem, ki vrne ceno minimalnega vpetega drevesa, ne
pa tudi minimalnega vpetega drevesa. Metoda je implementirana algoritmu 5.5.31
in uporablja standardni zapis matrike s poljem.
Vhodni podatki:
• matrika cene grafa matrika, za katerega nas zanima cena minimalnega vpe-
tega drevesa.
Izhodni podatki:
• cena minimalnega vpetega drevesa.
Pomozne metode:
1. Matrix.SestejVector(int[] v1,int[] v2)
Metoda sesteje 2 vektorja. Metoda je implementirana po opisu sestevanja dveh
vektorjev v poglavju 4.
Vhodni podatki:
• vektor v1 dolzine n;
• vektor v2 dolzine n.
Izhodni podatki:
• vektor v dolzine n, za katerega velja v=v1+v2.
2. Matrix.argMin(int[] v)
Metoda ugotavlja, do katerega vozlisca gre trenutno minimalna povezava od dre-
vesa do vseh ostalih vozlisc, ki se niso v drevesu.
Vhodni podatki:
• vektor v dolzine n.
Izhodni podatki:
• vrednost minimalnega elementa v vektorju;
90 POGLAVJE 6. TESTIRANJE ALGORITMOV
• indeks tega elementa v vektorju.
3. Matrix.MinVector(int[] v1, int[] v2)
Metoda zdruzi vektorja v1 in v2 v skupni minimalni vektor v, za katerega velja
v[i]=min{v1[i],v2[i]}.
Vhodni podatki:
• vektor v1 dolzine n;
• vektor v2 dolzine n.
Izhodni podatki:
• vektor v dolzine n, za katerega velja: v[i]=min{v1[i],v2[i]}.
Matrix.PrimovTree_normal_path(int[][] matrika)
Metoda simulira Primov algoritem, ki vrne minimalno vpeto drevo (v bistvu vrne
katere povezave so v minimalnem vpetem drevesu). Metoda je implementirana po
algoritmu 5.5.33 in uporablja standarni zapis matrike s poljem.
Vhodni podatki:
• matrika cene grafa matrika, za katerega nas zanima kaksno je minimalno
vpeto drevo.
Izhodni podatki:
• vektor, ki vsebuje zacetke in konce povezav, ki so vsebovane v minimalnem
vpetem drevesu.
Pomozne metode:
1. Matrix.SestejVector(int[] v1,int[] v2)
2. Matrix.argMin(int[] v)
3. Matrix.MinVector_path(int[] v1, int[] v2,int[] v1p, int[] v2p)
Metoda vrne vsoto dveh vektorjev v1 in v2 tako, da na vsakem mestu vzame
tistega, ki je manjsi (tako da velja rez[i]=min{v1[i],v2[i]}), in pripadajocega
prednika tega manjsega elementa.
Vhodni podatki:
6.7. PRIMOV ALGORITEM 91
• v1 je prvi vektor, v1p so predhodniki povezav, katerih cene vsebuje ta vektor;
• v2 je drugi vektor, v2p so predhodniki povezav, katerih cene vsebuje ta
vektor.
Izhodni podatki:
• LinkedList, ki vsebuje: vektor rez, za katerega velja rez[i]=min{v1[i],v2[i]},
in vektor pred, ki vsebuje predhodnike povezav, ki so v rez.
Sparse.Primov_CSR(int[]data,int[] ind, int[] poin)
Metoda simulira Primov algoritem, ki vrne ceno minimalnega vpetega drevesa.
Metoda je implementirana po algoritmu 5.5.31 in uporablja CSR zapis matrike.
Vhodni podatki:
• data, ind, poin so podatki o matriki, v CSR zapisu, ki je matrika cene
grafa, za katerega nas zanima cena minimalnega vpetega drevesa.
Izhodni podatki:
• cena minimalnega vpetega drevesa grafa.
Pomozne metode
1. Sparse.getVector(int[]data,int[] ind, int[] poin,int vrstica)
Metoda vrne vektor, ki je podana vrstica matrike.
Vhodni podatki:
• data, ind, poin so podatki o matriki, podani v CSR nacinu zapisa;
• vrstica je indeks vrstice, katero zelimo “izlociti” iz matrike.
Izhodni podatki:
• vektor, ki je vrstica (indeksa vrstica) matrike.
2. Matrix.argMin(int[] v)
3. Matrix.MinVector(int[] v1, int[] v2)
Sparse.Primov_CSR_path(int[]data,int[] ind, int[] poin)
92 POGLAVJE 6. TESTIRANJE ALGORITMOV
Metoda simulira Primov algoritem, ki vrne minimalno vpeto drevo (v bistvu vrne
katere povezave so v minimalnem vpetem drevesu). Metoda je implementirana po
algoritmu 5.5.33 in uporablja CSR zapis matrike.
Vhodni podatki:
• data, ind, poin so podatki o matriki, v CSR zapisu, ki je matrika cene
grafa, za katerega nas zanima cena minimalnega vpetega drevesa.
Izhodni podatki:
• vektor, ki vsebuje zacetke in konce povezav, ki so vsebovane v minimalnem
vpetem. drevesu
Pomozne metode:
1. Sparse.getVector(int[]data,int[] ind, int[] poin,int vrstica)
2. Matrix.argMin(int[] v)
3. Matrix.MinVector_path(int[] v1, int[] v2,int[] v1p, int[] v2p)
TESTNE MATRIKE
• test18 je matrika dimenzije 200 x 200, s 4860 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test19 je matrika dimenzije 100 x 100, s 1863 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test20 je matrika dimenzije 300 x 300, z 9750 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test21 je matrika dimenzije 200 x 200, z 2128 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
• test22 je matrika dimenzije 100 x 100, s 177 vrednostmi od 1 do 5, po
diagonali so nicle, drugje pa ∞.
Vse matrike so sosedne matrike povezanih grafov.
REZULTATI
6.7. PRIMOV ALGORITEM 93
MATRIKA test18 test19 test20 test21 test22
ARc 22,94 5,95 53,27 22,58 5,76
ARp 51,86 13,06 140,41 51,40 12,63
CSRc 45,14 10,88 103,56 44,98 10,93
CSRp 69,51 16,91 178,29 69,60 16,67
Tabela 6.8: Rezultati testiranj Primovega algoritma
*Opomba: Casi v tabeli so zapisani v 104ns.
Tabelo moramo brati navpicno, primer: pri matriki test18 je metoda ARc delovala
22,94 104 ns in tako dalje.
OPAZANJA
Kot je bilo pricakovate: metodi, ki racunata tudi pot in ne samo cene, potrebujeta
vec casa. Zmogljivost tako metode, ki uporablja standarden zapis matrike in tiste
s CSR zapisom matrike, je odvisna samo od stevila vozlisc. Kot vidimo pa je
implementacija s standardnim zapisom manj kompleksna, ker imamo neposreden
dostop do vrstice matrike, zato je tudi hitrejsa. Opazimo, da nam pri tem algo-
ritmu ne pomaga zapis redke matrike v nacinu CSR, ker ne preiskujemo povezav,
ampak vozlisca. Lastnosti vozlisc (lega v matriki) in njihovih povezav pa so hitreje
dostopne s standardnim zapisom matrike, zato je tudi ta zapis bolj primeren za
uporabo pri Primovem algoritmu.
Poglavje 7
Zakljucek
Skozi delo smo prisli do zakljucka, da je CSR zapis redke matrike precej neprimeren
za algoritme, kjer se stevilo nenicelnih elementov ves cas spreminja, saj nimamo
neposrednega dostopa do vrstice elementa v matriki, zato je potrebno veliko pre-
tvorb iz standardnega nacina zapisa v CSR zapis, da ugotovimo pravo zaporedje
podatkov v data. Prav tako je CSR zapis precej slabsi od standardnega zapisa
matrike, kadar moramo mnoziti dve matriki, saj tudi tu potrebujemo podatke o
vrstici, v kateri je element; ta podatek pa je iz CSR zapisa potrebno preracunati,
medtem ko je v standardnem zapisu neposredno dostopen, to pa nam jemlje cas.
CSR zapis je predvsem neprimeren, kadar je iz matrike, zapisane v CSR zapisu,
potrebno dobiti vse elemente kateregakoli stolpca, saj ti podatki niso direktno do-
stopni in je potrebno pregledati vse podatke, da ugotovimo, kateri so ti elementi za
vsak stolpec. Problem sprehoda bi se seveda dalo resiti tako, da bi uporabili CSC
zapis, kjer elemente po vrsti shranjujemo po stolpcih, a tu bi imeli podobne tezave,
ko bi potrebovali elemente vrstice. V vecini nasih algoritmov potrebujemo oboje
(stolpce in vrstice) zaradi mnozenja 2 matrik, zato zapis CSC ne bi dal bistveno
drugacnih rezultatov kot CSR.
CSR zapis je primeren, kadar mnozimo matriko z vektorjem, in v redkih primerih,
ko potrebujemo mnozenje matrik v kolobarju (+,* ); takoj ko kolobar spremenimo,
naletimo na tezave.
Metode bi se dalo se casovno optimizirati na primer s paralelnim programiranjem,
95
96 POGLAVJE 7. ZAKLJUCEK
ampak bi to lahko narediti tako pri metodah, ki uporabljajo zapise redkih matrik,
kot pri metodah, ki uporabljajo standardni zapis matrike z dvodimenzionalno ta-
belo, zato se primerjava v zmogljivostih ne bi bistveno spremenila.
Nadaljnje delo
V delu smo preucili moznosti implementacije nekaj algoritmov na grafu z ma-
trikami, ki smo jih zapisali na standarden nacin s poljem in z nekaj razlicnimi
enostavnimi zapisi redkih matrik. Ugotovili smo, da ti enostavni zapisi redkih
matrik v vecini primerov, ki smo jih mi preucili, ne morejo konkurirati s standar-
dnim zapisom matrike. Verjamemo, da bi s kompleksnejsimi zapisi redkih matrik
(npr. v delu smo omenili tudi Ellpack-Itpackov zapis, obstaja pa se veliko drugih)
lahko dosegli boljse case in bi v vec primerih presegli case metod, ki uporabljajo
standardni zapis matrik.
Drugi pogled, ki bi ga na to delo lahko navezali, je primerjava standardne imple-
mentacije opisanih algoritmov na grafih z algebrsko implementacijo, ki uporablja
izracune na sosednih matrikah. Tudi to je zelo zanimiva tema, katere se je ze lo-
tilo kar nekaj raziskovalnih skupin,ki so tudi dokazale, da so izracuni na sosednih
matrikah lahko hitrejsi kot izracuni na grafih, ravno zato so ze sedaj na primer
v MATLABU matrike postale najpogosteje uporabljena struktura za resevanje
problemov na grafih.
Literatura
[1] Jack J. Dongarra and others, “Graph Algorithms in the Language of Linear
Algebra”, str 1-58, 2011.
[2] Seymour Lipschutz, Ph.D., Marc Lipson, Ph.D, “Linear algebra (Third Edi-
tion)”, str 1-41, 2001.
[3] Ivan Vidav, “Algebra”, str 84-92, 123-137, 2003.
[4] Tomaz Dobravec,“Algoritmi nad grafi v jeziku linearne algebre”, LALGinar,
FRI 2012.
[5] Yousef Saad, “Iterative Methods for Sparse Linear Systems”, str 68-95, 2000.
[6] Metode za redke matrike , dosegljivo na
http://netlib.org/utk/papers/templates/node90.html
[7] MSR format za redke matrike, dosegljivo na
http://www.iue.tuwien.ac.at/phd/wagner/ node83.html
[8] Teorija grafov, dosegljivo na http://164.8.132.54/GIS/sesto.html
[9] Definicije, dosegljivo na http://sl.wikipedia.org/wiki
[10] Redke matrike, dosegljivo na http://www.answers.com/topic/sparse-matrix
[11] Algoritmi, dosegljivo na http://wiki.fmf.uni-lj.si/wiki
[12] Utezeni graf (omrezje), dosegljivo na http://www.nauk.si/materials/5603/out/#state=1
97
98 LITERATURA
[13] Zapisi redkih matrik, dosegljivo na http://netlib.org/utk/papers/templates/node98.html
[14] Graf in algoritmi na grafu, dosegljivo na http://rtk.ijs.si/misc/Grafi.ppt
Slike
3.1 Primer dualnosti med grafom in matriko . . . . . . . . . . . . . . . 13
3.2 Primer matrike sosednosti za 4 tocke . . . . . . . . . . . . . . . . . 13
3.3 Primer matrike sosednosti za vec tock . . . . . . . . . . . . . . . . . 14
3.4 Primer CSR zapisa na matriki A . . . . . . . . . . . . . . . . . . . 17
3.5 Primer CSC zapisa na matriki A . . . . . . . . . . . . . . . . . . . 17
3.6 Primer zapisa s terkami na matriki A . . . . . . . . . . . . . . . . . 18
3.7 Primer MSR zapisa na matriki A . . . . . . . . . . . . . . . . . . . 19
3.8 Primer shranjevanja diagonalne matrike na matriki B . . . . . . . . 20
3.9 Primer shranjevanja diagonalne matrike z Ellpach-Itpackovim zapi-
som na matriki B . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.1 Slika nivojev pri preiskovanju v sirino . . . . . . . . . . . . . . . . . 32
5.2 Primer racunanja v kolobarju (ALI,IN) . . . . . . . . . . . . . . . . 32
5.3 Simulacija BFS algoritma . . . . . . . . . . . . . . . . . . . . . . . 33
5.4 Simulacija BFS algoritma na primeru . . . . . . . . . . . . . . . . . 33
5.5 Primer mnozenja v kolobarju (min,+) . . . . . . . . . . . . . . . . . 36
5.6 Primer iskanja minimalnih poti . . . . . . . . . . . . . . . . . . . . 38
5.7 Primer izracuna po Bellman-Fordovem algoritmu . . . . . . . . . . 45
5.8 Primer rekonstrukcije poti po Floyd-Warshallovem algoritmu . . . . 56
5.9 Skica delovanja Primovega algoritma . . . . . . . . . . . . . . . . . 58
5.10 Racunanje cene minimalnega vpetega drevesa . . . . . . . . . . . . 61
99
Tabele
2.1 Tabela algebrskih struktur in zapisov . . . . . . . . . . . . . . . . . 9
6.1 Rezultati testiranj algoritmov za mnozenje matrike z vektorjem . . 67
6.2 Rezultati testiranj algoritma BFS . . . . . . . . . . . . . . . . . . . 72
6.3 Rezultati testiranj algoritma iskanja minimalnih poti . . . . . . . . 76
6.4 Rezultati testiranj Bellman-Fordovega algoritma brez shranjevanja
poti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.5 Rezultati testiranj Bellman-Fordovega algoritma na povezanih grafih 83
6.6 Rezultati testiranj Bellman-Fordovega algoritma, ki vraca tudi mi-
nimalno pot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
6.7 Rezultati testiranj Floyd-Warshallovega algoritma . . . . . . . . . . 88
6.8 Rezultati testiranj Primovega algoritma . . . . . . . . . . . . . . . . 93
101