import platform
platform.platform()
platform.python_version()
import networkx as nx
nx.__version__
from pylab import *
%matplotlib inline
from IPython.core.display import Image
import DSTG
nx.draw(nx.balanced_tree(3,2),with_labels=True,node_color='y',edgecolors='k')
nx.draw(nx.balanced_tree(2,3),with_labels=True,node_color='y',edgecolors='k')
figure(figsize=(10,5))
gr=nx.balanced_tree(3,2)
nx.draw(gr,pos=DSTG.RootedEmbedding(gr,0),with_labels=True,node_color='y',edgecolors='k')
figure(figsize=(10,5))
nx.draw(gr,pos=DSTG.RootedEmbedding(gr,8),with_labels=True,node_color='y',edgecolors='k')
figure(figsize=(10,5))
gr2=nx.balanced_tree(2,3)
nx.draw(gr2,pos=DSTG.RootedEmbedding(gr2,0),with_labels=True,node_color='y',edgecolors='k')
figure(figsize=(10,5))
nx.draw(gr2,pos=DSTG.RootedEmbedding(gr2,4),with_labels=True,node_color='y',edgecolors='k')
figure(figsize=(6,4))
nx.draw(nx.path_graph(8),with_labels=True,node_color='y',edgecolors='k')
figure(figsize=(8,6))
nx.draw(nx.path_graph(20),with_labels=True,node_color='y',edgecolors='k')
nx.draw(nx.star_graph(7),with_labels=True,node_color='y',edgecolors='k')
figure(figsize=(8,6))
nx.draw(nx.star_graph(19),with_labels=True,node_color='y',edgecolors='k')
nx.draw(nx.degree_sequence_tree([2,1,2,3,1,1,1,2,1,4]),with_labels=True,node_color='y',edgecolors='k')
nx.draw(nx.degree_sequence_tree([3,1,3,3,1,1,1,2,1]),with_labels=True,node_color='y',edgecolors='k')
Pazite, u stablu vrijedi $\varepsilon=\nu-1\ $ pa zbog $\sum\limits_{v\in V(G)}{d(v)}=2\varepsilon$ mora biti $\ \nu-\frac{1}{2}\sum\limits_{v\in V(G)}{d(v)}=1$
stablo1=nx.path_graph(5)
stablo2=nx.star_graph(7)
graf=nx.disjoint_union(stablo1,stablo2)
figure(figsize=(6,4))
nx.draw(graf,with_labels=True,node_color='y',edgecolors='k')
graf1=nx.Graph({1:[2,4],2:[3,4],3:[4]})
poz1={1:[0,0],2:[1,0],3:[1,1],4:[0,1]}
nx.draw(graf1,pos=poz1,with_labels=True,node_color='y',edgecolors='k')
ukupni broj razapinjućih stabala grafa
DSTG.BrojRazapinjucihStabala(graf1)
neko razapinjuće stablo grafa
bridovi1=list(nx.bfs_edges(graf1,2))
raz_stablo1=nx.Graph(bridovi1)
nx.draw(raz_stablo1,pos=poz1,with_labels=True,node_color='y',edgecolors='k')
graf2=nx.complete_bipartite_graph(2,3)
poz2={0:[0,1.5],1:[0,0.5],2:[2,2],3:[2,1],4:[2,0]}
nx.draw(graf2,pos=poz2,with_labels=True,node_color='y',edgecolors='k')
ukupni broj razapinjućih stabala grafa
DSTG.BrojRazapinjucihStabala(graf2)
neko razapinjuće stablo grafa
bridovi2=list(nx.dfs_edges(graf2,1))
raz_stablo2=nx.Graph(bridovi2)
nx.draw(raz_stablo2,pos=poz2,with_labels=True,node_color='y',edgecolors='k')
graf3=nx.Graph({1:[2,4,5],2:[3,5],3:[4],4:[5]})
poz3={1:[0,0],2:[2,0],3:[2,2],4:[0,2],5:[1,1]}
nx.draw(graf3,pos=poz3,with_labels=True,node_color='y',edgecolors='k')
ukupni broj razapinjućih stabala grafa
DSTG.BrojRazapinjucihStabala(graf3)
neko razapinjuće stablo grafa
bridovi3=list(nx.bfs_edges(graf3,5))
raz_stablo3=nx.Graph(bridovi3)
nx.draw(raz_stablo3,pos=poz3,with_labels=True,node_color='y',edgecolors='k')
graf4=nx.Graph({1:[2,4],2:[3,5],3:[6],4:[5,7],5:[6,7],6:[7]})
poz4={1:[0,0],2:[1,0],3:[2,0],4:[0,1],5:[1,1],6:[2,1],7:[1,2]}
nx.draw(graf4,pos=poz4,with_labels=True,node_color='y',edgecolors='k')
ukupni broj razapinjućih stabala grafa
DSTG.BrojRazapinjucihStabala(graf4)
neka razapinjuća stabla grafa
bridovi41=list(nx.dfs_edges(graf4,4))
raz_stablo41=nx.Graph(bridovi41)
nx.draw(raz_stablo41,pos=poz4,with_labels=True,node_color='y',edgecolors='k')
bridovi42=list(nx.bfs_edges(graf4,5))
raz_stablo42=nx.Graph(bridovi42)
nx.draw(raz_stablo42,pos=poz4,with_labels=True,node_color='y',edgecolors='k')
graf5=nx.MultiGraph({1:[2,2,2,4,4,4],2:[3,3,3],3:[4,4,4],4:[5,5,5]})
poz5={1:[1,-1],2:[0,0],3:[1,1],4:[2,0],5:[3,0]}
graf5vz=nx.nx_agraph.to_agraph(graf5)
graf5vz.draw("graf5.png",prog='circo')
Image(filename="graf5.png")
ukupni broj razapinjućih stabala grafa
DSTG.BrojRazapinjucihStabala(graf5)
neko razapinjuće stablo grafa
bridovi5=list(nx.dfs_edges(graf5,4))
raz_stablo5=nx.Graph(bridovi5)
nx.draw(raz_stablo5,pos=poz5,with_labels=True,node_color='y',edgecolors='k')
graf6=nx.MultiGraph({1:[1,2,2,2],2:[3,4],3:[3,3,4,4]})
graf6vz=nx.nx_agraph.to_agraph(graf6)
graf6vz.draw('graf6.png',prog='circo')
Image(filename='graf6.png')
ukupni broj razapinjućih stabala grafa
DSTG.BrojRazapinjucihStabala(graf6)
neko razapinjuće stablo grafa
bridovi6=list(nx.bfs_edges(graf6,2))
raz_stablo6=nx.Graph(bridovi6)
nx.draw(raz_stablo6,with_labels=True,node_color='y',edgecolors='k')
graf7=nx.complete_graph(6)
nx.draw_circular(graf7,with_labels=True,node_color='y',edgecolors='k')
ukupni broj razapinjućih stabala grafa
DSTG.BrojRazapinjucihStabala(graf7)
neka razapinjuća stabla potpunog grafa $K_6$
figure(figsize=(15,4))
subplot(131)
bridovi71=list(nx.bfs_edges(graf7,4))
raz_stablo71=nx.Graph(bridovi71)
nx.draw_circular(raz_stablo71,with_labels=True,node_color='y',edgecolors='k')
subplot(132)
bridovi72=list(nx.dfs_edges(graf7,4))
raz_stablo72=nx.Graph(bridovi72)
nx.draw_circular(raz_stablo72,with_labels=True,node_color='y',edgecolors='k')
subplot(133)
bridovi73=list(nx.dfs_edges(graf7,0))
raz_stablo73=nx.Graph(bridovi73)
nx.draw_circular(raz_stablo73,with_labels=True,node_color='y',edgecolors='k')
gr=nx.Graph({1:[3,5],2:[5],3:[4,6],4:[5,7],5:[8],6:[7],7:[8]})
pozicije={1:[1,0],2:[2,0],3:[0,1],4:[1,1],5:[2,1],6:[0,2],7:[1,2],8:[2,2]}
figure(figsize=(5,5))
nx.draw(gr,pos=pozicije,node_size=500,with_labels=True,node_color='y',edgecolors='k')
DFS algoritam daje preorder redoslijed posjećivanja vrhova počevši s vrhom "1"
list(nx.dfs_preorder_nodes(gr,1))
DFS algoritam daje preorder redoslijed posjećivanja vrhova počevši s vrhom "4"
list(nx.dfs_preorder_nodes(gr,4))
DFS algoritam daje postorder redoslijed posjećivanja vrhova počevši s vrhom "1"
list(nx.dfs_postorder_nodes(gr,1))
DFS algoritam daje postorder redoslijed posjećivanja vrhova počevši s vrhom "4"
list(nx.dfs_postorder_nodes(gr,4))
DFS stablo s korijenom "1"
nx.nx_agraph.to_agraph(nx.dfs_tree(gr,1)).draw('dfs1.png',prog='dot')
Image(filename="dfs1.png")
DFS stablo s korijenom "4"
nx.nx_agraph.to_agraph(nx.dfs_tree(gr,4)).draw('dfs4.png',prog='dot')
Image(filename="dfs4.png")
bridovi DFS stabla s početnim vrhom "1"
list(nx.dfs_edges(gr,1))
bridovi DFS stabla s početnim vrhom "4"
list(nx.dfs_edges(gr,4))
prethodnik pojedinog vrha u DFS stablu s početnim vrhom "1"
nx.dfs_predecessors(gr,1)
prethodnik pojedinog vrha u DFS stablu s početnim vrhom "4"
nx.dfs_predecessors(gr,4)
sljedbenici pojedinog vrha u DFS stablu s početnim vrhom "1"
nx.dfs_successors(gr,1)
sljedbenici pojedinog vrha u DFS stablu s početnim vrhom "4"
nx.dfs_successors(gr,4)
DFS stablo s početkom u vrhu "1" istaknuto na grafu
figure(figsize=(5,5))
DSTG.DFSstablo(gr,pozicije,1,velicinaVrha=500,rubVrha='k')
DFS stablo s početkom u vrhu "4" istaknuto na grafu
figure(figsize=(5,5))
DSTG.DFSstablo(gr,pozicije,4,velicinaVrha=500,rubVrha='k')
DFS stablo s početkom u vrhu "1" kao korijensko stablo
figure(figsize=(5,5))
DSTG.DFSkorijenskoStablo(gr,1,velicinaVrha=500,rubVrha='k')
DFS stablo s početkom u vrhu "4" kao korijensko stablo
figure(figsize=(5,5))
DSTG.DFSkorijenskoStablo(gr,4,velicinaVrha=500,rubVrha='k')
prethodnik pojedinog vrha u BFS stablu s početnim vrhom "1"
dict(nx.bfs_predecessors(gr,1))
prethodnik pojedinog vrha u BFS stablu s početnim vrhom "4"
dict(nx.bfs_predecessors(gr,4))
sljedbenici pojedinog vrha u BFS stablu s početnim vrhom "1"
dict(nx.bfs_successors(gr,1))
sljedbenici pojedinog vrha u BFS stablu s početnim vrhom "4"
dict(nx.bfs_successors(gr,4))
bridovi u BFS stablu s početnim vrhom "1"
list(nx.bfs_edges(gr,1))
bridovi u BFS stablu s početnim vrhom "4"
list(nx.bfs_edges(gr,4))
BFS stablo s korijenom "1"
nx.nx_agraph.to_agraph(nx.bfs_tree(gr,1)).draw('bfs1.png',prog='dot')
Image(filename="bfs1.png")
BFS stablo s korijenom "4"
nx.nx_agraph.to_agraph(nx.bfs_tree(gr,4)).draw('bfs4.png',prog='dot')
Image(filename="bfs4.png")
BFS stablo s početkom u vrhu "1" istaknuto na grafu
figure(figsize=(5,5))
DSTG.BFSstablo(gr,pozicije,1,velicinaVrha=500,rubVrha='k')
BFS stablo s početkom u vrhu "4" istaknuto na grafu
figure(figsize=(5,5))
DSTG.BFSstablo(gr,pozicije,4,velicinaVrha=500,rubVrha='k')
BFS stablo s početkom u vrhu "1" kao korijensko stablo
DSTG.BFSkorijenskoStablo(gr,1,velicinaVrha=500,rubVrha='k')
BFS stablo s početkom u vrhu "4" kao korijensko stablo
DSTG.BFSkorijenskoStablo(gr,4,velicinaVrha=500,rubVrha='k')
Brid u grafu $G$ je rezni ako i samo ako pripada svakom razapinjućem stablu grafa $G$. Na toj činjenici se temelji implementacija funkcije rezni_bridovi za traženje reznih bridova. Na zadani graf, tj. na njegove komponente povezanosti se primijeni DFS algoritam koji će za svaku njegovu komponentu povezanosti pronaći neko razapinjuće stablo. Svi rezni bridovi grafa $G$ pripadaju nekom od tih stabala. Stoga je dovoljno samo ispitati bridove koji pripadaju tim razapinjućim stablima jesu li neki od njih rezni.
donji graf ima samo jedan rezni brid
figure(figsize=(4,4))
nx.draw(gr,pos=pozicije,node_color='y',node_size=500,with_labels=True,edgecolors='k')
DSTG.rezni_bridovi(gr)
postoji i gotova naredba u networkx-u, ali ona radi samo na jednostavnim grafovima
list(nx.bridges(gr))
donji graf nema reznih bridova
figure(figsize=(4,4))
nx.draw(graf1,pos=poz1,node_color='y',node_size=500,with_labels=True,edgecolors='k')
DSTG.rezni_bridovi(graf1)
list(nx.bridges(graf1))
donji graf ima četiri rezna brida
figure(figsize=(7,4))
G=nx.Graph({0:[3],1:[4],2:[4,5,7,8,9],4:[5],5:[7],6:[]})
nx.draw(G,node_color='y',with_labels=True,edgecolors='k')
DSTG.rezni_bridovi(G)
list(nx.bridges(G))
Implementacija algoritam za ispitivanje acikličnosti grafa se temelji na BFS algoritmu, a zapravo je samo mala modifikacija ranije implementiranog algoritma za računanje struka grafa. Formalno, možemo primijeniti algoritam za računanje struka grafa. Ako je struk grafa manji od $\infty$, tada je graf ciklički, a u protivnom je aciklički. Kako nas kod ispitivanja cikličnosti ne zanima duljina najkraćeg ciklusa, možemo taj algoritam i ranije prekinuti ukoliko dođemo do informacije da postoji u grafu neki ciklus koji možda nije najmanje duljine.
DSTG.is_acyclic(gr)
DSTG.is_acyclic(G)
DSTG.is_acyclic(nx.path_graph(8))
Postoji gotova naredba za pronalaženje nekog ciklusa u grafu koja na izlazu daje listu bridova pronađenog ciklusa.
nx.find_cycle(gr)
nx.find_cycle(G)
Implementacija funkcije random_cycle za traženje nekog ciklusa u grafu temelji se na DFS algoritmu. Algoritam je randomiziran tako da višestrukim pokretanjem na istom grafu daje općenito različite cikluse.
Također, dana je implementacija DFS algoritma pomoću stoga. Funkcija dfs_graf na izlazu daje uređenu šestorku: listu redom posjećivanih vrhova, rječnik trenutaka u kojima su pojedini vrhovi prvi put posjećeni, rječnik trenutaka u kojima je završeno istraživanje pojedinih vrhova, rječnik neposrednih prethodnika svakog vrha, listu bridova koji pripadaju pronađenom razapinjućem stablu i listu preostalih bridova grafa koji nisu u pronađenom razapinjućem stablu.
Uočite kako se višestrukim pokretanjem funkcije find_cycle na donjem grafu dobivaju na izlazu općenito različiti ciklusi u tom grafu.
for k in range(20):
print(DSTG.random_cycle(gr))
DSTG.dfs_graf(gr,3)
DSTG.dfs_graf(gr,1)
Ako želimo pronađeni ciklus istaknuti na grafu
figure(figsize=(5,5))
DSTG.random_cycle_graph(gr,pozicije,velicinaVrha=500,rubVrha='k')
figure(figsize=(5,5))
DSTG.random_cycle_graph(gr,pozicije,velicinaVrha=500,rubVrha='k')
graf=nx.Graph()
graf.add_weighted_edges_from([("A","B",6),("A","D",2),("A","E",9),("A","S",7),
("B","C",2),("B","E",3),("B","S",9), ("C","E",2),("C","F",6),("C","S",1),
("D","E",5),("D","T",3),("E","F",7),("E","T",9),("F","T",6)])
pozicijeGraf={"A":[2,4],"B":[2,2],"C":[2,0],"D":[4,4],"E":[4,2],"F":[4,0],"S":[0,2],"T":[6,2]}
figure(figsize=(8,5))
DSTG.CrtajTezinskiGraf(graf,pozicijeGraf,velicinaVrha=500,rubVrha='k')
minimalno stablo dobiveno Kruskalovim algoritmom
nx.draw(nx.minimum_spanning_tree(graf),with_labels=True,node_color='y',edgecolors='k')
bridovi minimalnog stabla dobivenog Kruskalovim algoritmom
list(nx.minimum_spanning_edges(graf))
Minimalno Kruskal stablo istaknuto na grafu
DSTG.KruskalStablo(graf,pozicijeGraf,velicinaVrha=500,rubVrha='k')
Maksimalno Kruskal stablo istaknuto na grafu
DSTG.KruskalStablo(graf,pozicijeGraf,opcija='max',velicinaVrha=500,rubVrha='k')
list(nx.maximum_spanning_edges(graf))
Minimalno Kruskal stablo kao korijensko stablo s korijenom "A"
figure(figsize=(5,6))
DSTG.KruskalKorijenskoStablo(graf,"A",velicinaVrha=500,rubVrha='k')
Minimalno Kruskal stablo kao korijensko stablo s korijenom "B"
figure(figsize=(5,6))
DSTG.KruskalKorijenskoStablo(graf,"B",velicinaVrha=500,rubVrha='k')
Maksimalno Kruskal stablo kao korijensko stablo s korijenom "A"
figure(figsize=(7,5))
DSTG.KruskalKorijenskoStablo(graf,"A",opcija='max',velicinaVrha=500,rubVrha='k')
Maksimalno Kruskal stablo kao korijensko stablo s korijenom "B"
figure(figsize=(7,7))
DSTG.KruskalKorijenskoStablo(graf,"B",opcija='max',velicinaVrha=500,rubVrha='k')
minimalno stablo dobiveno Primovim algoritmom
figure(figsize=(7,5))
nx.draw(nx.minimum_spanning_tree(graf,algorithm='prim'),with_labels=True,node_color='y',edgecolors='k')
bridovi minimalnog stabla dobivenog Primovim algoritmom
list(nx.minimum_spanning_edges(graf,algorithm='prim'))
DSTG.prim_alg_min(graf,"A")
DSTG.prim_alg_min(graf,"B")
DSTG.PrimStablo(graf,"A",pozicijeGraf,velicinaVrha=500,rubVrha='k')
DSTG.PrimStablo(graf,"B",pozicijeGraf,velicinaVrha=500,rubVrha='k')
DSTG.prim_alg_max(graf,"A")
DSTG.PrimStablo(graf,"A",pozicijeGraf,opcija='max',velicinaVrha=500,rubVrha='k')
DSTG.PrimKorijenskoStablo(graf,"A",opcija='max',velicinaVrha=500,rubVrha='k')
DSTG.rucni_Kruskal(graf)
DSTG.rucni_Kruskal(graf,'max')
DSTG.rucni_Prim(graf,"B")
DSTG.rucni_Prim(graf,"B",'max')