Ishodi učenja:

  • Razlikovati strukturnu i regularnu ekvivalenciju te uloge u mreži.

  • Primijeniti pozicijsku analizu (značajke + grupiranje/blokovi).

  • Analizirati hijerarhiju i objasniti uloge (gatekeeper, broker, autoritet).

  • Kritički raspraviti dualnost čvor–veza i što se gubi/uzima modeliranjem.

library(igraph)
library(tidygraph)
library(ggraph)
library(sna)

Zašto centralnost nije dovoljna?

Mjere centralnosti odgovaraju na pitanje tko je važan u mreži, ali ne i na pitanje koju funkciju čvor obavlja niti u koju strukturnu poziciju pripada. U teoriji mreža i primjenama SNA, “važnost” je uvijek uvjetovana fenomenom koji graf modelira: isti stupanj, blizina ili posredništvo mogu značiti utjecaj u društvenoj mreži, ali opterećenje ili kapacitet u komunikacijskoj mreži; stoga se centralnosti moraju interpretirati “s oprezom”, jer jedna mjera ne mora detektirati ono što je relevantno za konkretan proces (npr. popularnost ne mora biti isto što i sposobnost širenja informacija). Na primjer, recimo da se promatra jedna mreža učenika u razredu - čvor s najvišom blizinom (closeness) nije nužno ključan za protok informacija: uklanjanje takvog čvora može imati mali učinak, dok čvorovi s visokim posredništvom (betweenness) mogu biti presudni za spajanje podskupina i održavanje povezanosti. To jasno sugerira da centralnosti prvenstveno mjere individualnu poziciju u prostoru putova, ali slabije zahvaćaju mezorazinske obrasce (npr. granice grupa, strukturne rupe) i makro-arhitekturu (npr. jezgra–periferija, hijerarhija).

Osim toga, centralnost ne zahvaća koncept “zamjenjivosti” aktera. Dva čvora mogu imati slične vrijednosti stupnja ili centralnosti, a ipak pripadati različitim strukturnim ulogama; obrnuto, akteri koji obavljaju istu ulogu mogu biti povezani s različitim osobama. Zato se uvodi ideja ekvivalencije i pozicija: strukturna ekvivalencija zahtijeva identične susjede (što je u empirijskim mrežama rijetko), pa se u praksi prelazi na mjerenje strukturne sličnosti preko udaljenosti između redaka/stupaca matrice susjedstva. Upravo taj korak označava prijelaz s “važnosti pojedinca” na “pozicije u sustavu”, što je temelj za uloge poput brokera, gatekeepera ili autoriteta/huba: centralnost može sugerirati tko je istaknut, ali tek pozicijska analiza (ekvivalencije, blokmodeli) objašnjava zašto i u kojoj strukturi je taj istaknuti položaj nastao.

U usmjerenim i ponderiranim mrežama važno je razlikovati “centralnost” od “prestiža” (i općenito od asimetričnih relacija): centralnost tipično polazi od udaljenosti “od čvora prema drugima”, dok prestiž prirodno naglašava tok “prema čvoru” (npr. indegree kao stupanj prestiža, odnosno influence domain kao širi doseg utjecaja prema čvoru). To je važan uvod u hijerarhijske interpretacije i uloge u usmjerenim sustavima (npr. autoriteti i hubovi), gdje ista vrijednost klasične centralnosti ne mora razlikovati “dobar izvor” od “dobrog posrednika”. U tom smislu, centralnosti su nužan početni alat, ali nisu dovoljne za analizu uloga: za uloge su potrebni koncepti ekvivalencije, blokmodeliranja i hijerarhije, jer oni pomiču fokus s individualnog rangiranja na strukturne klase i odnose među klasama.




Podaci, priprema i prvi uvidi

Osim pripreme, ovdje će se prikazati uvidi u podatke kakve bismo stekli kroz ranije naučene korake u analizi. Za potrebe prikaza, koristit će se dvije mreže.

Prva je Enron mreža, koja nam je osobito prikladna za ovu analizu jer sadrži podatke o poslovnoj funkciji. Drugu mrežu ćemo kreirati temeljem web scrape-a stranica Unipu kako bismo kreirali mrežu izvođača na kolegijima.



Enron

Enron e-mail korpus nastao je kao posljedica regulatorne i sudske obrade slučaja Enron: velik dio interne e-mail komunikacije zaposlenika postao je javno dostupan u sklopu istraga i kasnijih objava, pa je dataset široko korišten u istraživanjima organizacijske komunikacije, forenzike, detekcije obrazaca (npr. zajednice, posrednici) te kao standardni “benchmark” u analizi društvenih mreža i rudarstvu teksta.

U ovom prikazu Enron se promatra kao usmjerena mreža komunikacije (pošiljatelj → primatelj), što je prirodno za modele gdje relacija nije nužno simetrična (tko šalje i tko prima). U usmjerenim grafovima zato tipično razlikujemo in/out susjedstva i oslanjamo se na slabo i jako povezane komponente pri analizi povezanosti.

U nastavku je uvodna provjera i osnovna topološka analiza Enron e-mail mreže. U prvom koraku provjeravaju se osnovna svojstva grafa, dostupni atributi čvorova i bridova te osnovni pokazatelji (broj čvorova, bridova, petlje, multi-bridovi). Povezanost i komponente u usmjerenim mrežama tipično se promatraju kroz slabo povezane (weak) i jako povezane (strong) komponente.

library(igraphdata)
data("enron")
g_enron <- igraph::upgrade_graph(enron)
vcount(g_enron)
## [1] 184
ecount(g_enron)
## [1] 125409
igraph::is_directed(g_enron)
## [1] TRUE
any_loop(g_enron)
## [1] TRUE
any_multiple(g_enron)
## [1] TRUE
list(
  vertex_attributes = vertex_attr_names(g_enron),
  edge_attributes   = edge_attr_names(g_enron)
)
## $vertex_attributes
## [1] "Email" "Name"  "Note" 
## 
## $edge_attributes
## [1] "Time"      "Reciptype" "Topic"     "LDC_topic"
unique(V(g_enron)$Note)
##  [1] "Employee, Specialist"                                      
##  [2] "Vice President"                                            
##  [3] "NA"                                                        
##  [4] "Director"                                                  
##  [5] "Vice President, Enron Online"                              
##  [6] "President, Enron Global Mkts"                              
##  [7] "Employee, Associate"                                       
##  [8] "Employee"                                                  
##  [9] "Vice President, Enron WholeSale Services"                  
## [10] "Employee, Senior Analyst Cash"                             
## [11] "Manager"                                                   
## [12] "Trader"                                                    
## [13] "Vice President, Term"                                      
## [14] "Manager, Logistics Manager"                                
## [15] "CEO, Enron North America and Enron Enery Services"         
## [16] "Vice President, Government Affairs"                        
## [17] "Managing Director, Legal Department"                       
## [18] "Employee, Senior Specialist"                               
## [19] "Employee, Analyst"                                         
## [20] "President"                                                 
## [21] "Employee, Cash Analyst"                                    
## [22] "In House Lawyer"                                           
## [23] "Employee, Government Relation Executive"                   
## [24] "Managing Director"                                         
## [25] "CEO"                                                       
## [26] "Manager, Risk Management Head"                             
## [27] "Vice President, Vice President & Chief of Staff"           
## [28] "Vice President, Enery marketting and trading Florida"      
## [29] "Manager, Real time Trading Desk"                           
## [30] "CEO, Enron America"                                        
## [31] "Employee, Senior Specialist Logistics"                     
## [32] "Director, Pipeline Business"                               
## [33] "President, Enron Online"                                   
## [34] "Employee, Administrative Asisstant"                        
## [35] "Employee, Analyst Risk Management"                         
## [36] "Employee, Sr.Specialist"                                   
## [37] "Vice President, Regulatory Affairs"                        
## [38] "Manager, Chief Risk Management Officer"                    
## [39] "Vice President, Also Chief Financial Officer and Treasurer"
## [40] "Employee, Chief Operating Officer"                         
## [41] "President, Enron Gas Pipeline"                             
## [42] "Manager, Regulatory Affairs"
g_enron <- igraph::simplify(
  g_enron,
  remove.loops = TRUE,          # po želji (možete staviti FALSE)
  remove.multiple = TRUE,       # spaja multi-bridove
  edge.attr.comb = list(
    weight    = "sum",          # broj poruka po paru (i -> j)
    Time      = toString,       # sačuva sve vremenske oznake kao string
    Reciptype = toString,       # sačuva sve tipove primatelja kao string
    Topic     = toString,       # sačuva sve topic kodove kao string
    LDC_topic = toString        # sačuva sve LDC_topic kao string
  )
)

vcount(g_enron)
## [1] 184
ecount(g_enron)
## [1] 3010
g_enron
## IGRAPH 567507f D--- 184 3010 -- Enron email network
## + attr: LDC_names (g/c), LDC_desc (g/c), name (g/c), Citation (g/c),
## | Email (v/c), Name (v/c), Note (v/c), Time (e/c), Reciptype (e/c),
## | Topic (e/c), LDC_topic (e/c)
## + edges from 567507f:
##  [1] 1-> 10 1-> 21 1-> 49 1-> 92 1->105 1->153 2-> 16 2-> 40 2-> 44 2-> 69
## [11] 2-> 71 2-> 76 2-> 83 2-> 89 2->108 2->158 2->160 3-> 11 3-> 18 3-> 44
## [21] 3-> 51 3-> 89 3->140 3->145 3->155 3->157 3->158 3->167 4-> 57 4->119
## [31] 4->141 5->  2 5->  6 5->  7 5-> 11 5-> 22 5-> 27 5-> 42 5-> 46 5-> 52
## [41] 5-> 54 5-> 71 5-> 79 5-> 81 5-> 83 5-> 85 5-> 86 5-> 90 5-> 97 5->102
## [51] 5->106 5->108 5->115 5->128 5->154 5->158 5->160 5->170 5->180 5->182
## + ... omitted several edges

Enron e-mail mreža u startu dolazi kao “sirova” mreža poruka: isti par osoba može imati jako puno poruka, mogu postojati petlje (netko šalje sam sebi) i višestruki bridovi (više poruka između istog pošiljatelja i primatelja). Zato smo mrežu pojednostavnili (simplify) tako da za svaki par (u → v) ostaje jedan brid, a atribut weight predstavlja ukupan broj poruka poslanih s u na v. Time prelazimo s logova poruka na pregledniju mrežu komunikacijskih odnosa.

Kod usmjerenih mreža razlikuju se slabo povezane i jako povezane komponente. U praksi se za mnoge globalne mjere (npr. prosječna duljina puta, dijametar) analizira najveća slabo povezana komponenta (giant weak component), jer su te mjere inače nedefinirane ili trivijalne u nepovezanim grafovima. Dakle, odatle krećemo.

# Slabo povezane komponente (weak)
comp_w <- igraph::components(g_enron, "weak")
comp_w$no
## [1] 3
summary(comp_w$csize)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1.00    1.00    1.00   61.33   91.50  182.00
# Najveća slabo povezana komponenta
giant_id <- which.max(comp_w$csize)
V_giant  <- V(g_enron)[comp_w$membership == giant_id]
g_giant  <- induced_subgraph(g_enron, vids = V_giant)

vcount(g_giant)
## [1] 182
ecount(g_giant)
## [1] 3010
# Jako povezane komponente (strong) – često ih ima mnogo u e-mail mrežama
comp_s <- igraph::components(g_enron, "strong")
comp_s$no
## [1] 11
summary(comp_s$csize)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1.00    1.00    1.00   16.73    1.00  174.00

Kod komponenti vidimo 3 slabo povezane komponente, pri čemu najveća (giant weak component) sadrži 182 od 184 čvora. To znači da gotovo svi zaposlenici pripadaju jednoj velikoj komunikacijskoj “cjelini” ako zanemarimo smjer (tj. ako postoji put u bilo kojem smjeru). Preostala dva čvora su izolirani u smislu globalne povezanosti (ili su u vrlo malim, odvojenim dijelovima mreže). S druge strane, imamo 11 jako povezanih komponenti, a najveća ima 174 čvora: to sugerira da unutar najvećeg dijela mreže postoji mnogo uzajamne komunikacije (postoji put u oba smjera između velikog broja parova), ali ipak nisu svi međusobno dosežni po smjeru, što je tipično za e-mail (npr. neki šalju svima, ali ne dobivaju odgovor; ili postoje hijerarhijske komunikacije).

Gustoća opisuje udio ostvarenih veza u odnosu na maksimalno moguće veze za zadani broj čvorova; u velikim komunikacijskim mrežama očekivano je da je mreža rijetka (sparse). Nakon simplifikacije mreža ima 184 čvora (osobe) i 3010 usmjerenih bridova (različitih komunikacijskih parova). U odnosu na maksimalno mogućih 184⋅183=33672 usmjerenih veza (bez petlji), ovih 3010 veza znači da je mreža rijetka (gustoća oko 0.089). To je očekivano za organizacijsku komunikaciju: većina ljudi ne komunicira izravno sa svima, nego unutar manjih radnih krugova, uz nekoliko “povezivača” koji spajaju grupe.

# Gustoća na originalnoj mreži i na najvećoj komponenti
dens_all   <- edge_density(g_enron, loops = FALSE)
dens_giant <- edge_density(g_giant, loops = FALSE)

# Osnovne globalne mjere na najvećoj komponenti (geodezije računamo na usmjerenom grafu)
# Napomena: dijametar/prosječna duljina puta mogu se računati i na nedirigiranoj projekciji
diam_dir <- diameter(g_giant, directed = TRUE, unconnected = FALSE)
apl_dir  <- mean_distance(g_giant, directed = TRUE, unconnected = FALSE)

diam_und <- diameter(as.undirected(g_giant, mode = "collapse"), directed = FALSE)
apl_und  <- mean_distance(as.undirected(g_giant, mode = "collapse"), directed = FALSE)

list(
  density_all = dens_all,
  density_giant = dens_giant,
  diameter_directed = diam_dir,
  apl_directed = apl_dir,
  diameter_undirected = diam_und,
  apl_undirected = apl_und
)
## $density_all
## [1] 0.08939178
## 
## $density_giant
## [1] 0.09137272
## 
## $diameter_directed
## [1] Inf
## 
## $apl_directed
## [1] Inf
## 
## $diameter_undirected
## [1] 4
## 
## $apl_undirected
## [1] 2.085787

Kod globalnih mjera udaljenosti uočavamo da su usmjereni dijametar i prosječna duljina puta “Inf”. To nije greška: to samo znači da u usmjerenom smislu postoje parovi čvorova između kojih ne postoji usmjereni put (npr. A može doći do B, ali B ne može doći do A; ili uopće nema puta u zadanom smjeru). Zato za dojam koliko je mreža kompaktna često gledamo i neusmjereni prikaz: tamo je dijametar 4, a prosječna duljina puta oko 2.09. Drugim riječima, u prosjeku su zaposlenici udaljeni otprilike “dva koraka” komunikacije, a najudaljeniji su četiri koraka — što upućuje na relativno “mali svijet” u organizacijskom smislu (informacija može brzo proći kroz nekoliko posrednika).

Detekcija zajednica - provest ćemo jednu varijantu s usmjerenom i jednu s neusmjerenom mrežom. Nakon detekcije zajednica, broje se bridovi koji su unutar zajednica i između zajednica, što daje jednostavnu sliku modularne strukture.

gU <- as.undirected(g_giant, mode = "collapse")

set.seed(1)
comm <- cluster_louvain(gU)  # brza i često dobra početna opcija
comm
## IGRAPH clustering multi level, groups: 6, mod: 0.34
## + groups:
##   $`1`
##    [1]   1  10  14  21  31  49  56  79  91 104 118 128 130 141 147 151
##   
##   $`2`
##    [1]   2   3  11  12  15  16  18  23  25  30  37  40  44  46  47  50  51  55
##   [19]  57  61  66  69  71  75  78  80  81  82  84  88  92  97  99 101 106 110
##   [37] 114 116 126 129 136 138 153 154 155 156 158 159 161 164 165 167 168 171
##   [55] 172 174 178 179 181
##   
##   $`3`
##   + ... omitted several groups/vertices
membership <- membership(comm)
V(g_giant)$louvain <- membership(comm)
table(membership) |> sort(decreasing = TRUE) |> head(10)
## membership
##  2  4  3  5  6  1 
## 59 36 30 24 17 16
# Bridovi unutar / između zajednica (na nedirigiranoj mreži)
endsU <- ends(gU, E(gU), names = FALSE)
m1 <- membership[endsU[,1]]
m2 <- membership[endsU[,2]]

within_edges  <- sum(m1 == m2)
between_edges <- sum(m1 != m2)

list(
  n_communities = length(unique(membership)),
  within_edges = within_edges,
  between_edges = between_edges,
  within_share = within_edges / ecount(gU),
  between_share = between_edges / ecount(gU),
  modularity = modularity(comm)
)
## $n_communities
## [1] 6
## 
## $within_edges
## [1] 1194
## 
## $between_edges
## [1] 903
## 
## $within_share
## [1] 0.5693848
## 
## $between_share
## [1] 0.4306152
## 
## $modularity
## [1] 0.3407308

Detekcija zajednica na neusmjerenoj projekciji (Louvain) daje 6 zajednica uz modularnost oko 0.34. To je umjerena modularnost: mreža ima prepoznatljive grupe, ali one nisu potpuno odvojene. U istom smjeru govori i udio bridova: oko 57% veza je unutar zajednica, a oko 43% između zajednica. To znači da većina komunikacije ide “unutar svojih” zajednica, ali značajan dio prelazi granice zajednica — što je realno za firmu gdje postoje timovi/odjeli, ali i koordinacija između njih.

set.seed(1)
comm <- cluster_walktrap(g_giant)  # brza i često dobra početna opcija
comm
## IGRAPH clustering walktrap, groups: 8, mod: 0.34
## + groups:
##   $`1`
##    [1]  19  33  36  41  45  65  77  86 100 120 124 137
##   
##   $`2`
##    [1]   2   3   4   7  11  15  16  17  18  20  23  25  27  30  37  40  42  44
##   [19]  46  48  50  55  57  60  61  62  63  69  71  75  78  80  81  84  88  89
##   [37]  90  93  97  99 101 102 106 115 116 117 118 119 125 126 128 129 131 133
##   [55] 134 135 136 138 139 140 142 147 153 155 156 158 163 165 167 170 172 173
##   [73] 174 175 178 179 181
##   
##   + ... omitted several groups/vertices
membership <- membership(comm)
V(g_giant)$walktrap <- membership(comm)
table(membership) |> sort(decreasing = TRUE) |> head(10)
## membership
##  2  3  5  4  1  6  7  8 
## 77 60 17 13 12  1  1  1
# Bridovi unutar / između zajednica (na nedirigiranoj mreži)
endsU <- ends(g_giant, E(g_giant), names = FALSE)
m1 <- membership[endsU[,1]]
m2 <- membership[endsU[,2]]

within_edges  <- sum(m1 == m2)
between_edges <- sum(m1 != m2)

list(
  n_communities = length(unique(membership)),
  within_edges = within_edges,
  between_edges = between_edges,
  within_share = within_edges / ecount(g_giant),
  between_share = between_edges / ecount(g_giant),
  modularity = modularity(comm)
)
## $n_communities
## [1] 8
## 
## $within_edges
## [1] 2134
## 
## $between_edges
## [1] 876
## 
## $within_share
## [1] 0.7089701
## 
## $between_share
## [1] 0.2910299
## 
## $modularity
## [1] 0.3378866

Kod Walktrap algoritma dobivamo 8 zajednica uz modularnost 0.338 (\(≈0.34\)), što je vrlo blizu Louvainu: mreža ima jasnu, ali ne ekstremno krutu modularnu strukturu (postoje grupe, ali imaju i dosta međusobnih veza).

Oko 71% komunikacijskih veza (agregiranih parova pošiljatelj→primatelj) ostaje unutar iste zajednice, dok oko 29% ide preko granica zajednica. To je tipičan obrazac za organizaciju: većina komunikacije je “intra-tim / intra-odjel”, ali gotovo trećina odnosa ipak povezuje različite grupe, što upućuje na koordinaciju, hijerarhiju, podršku ili posrednike koji povezuju dijelove firme.

Što se tiče veličina zajednica (membership tablica): jedna zajednica je vrlo velika (77 čvorova), druga također velika (60), a zatim slijede manje (17, 13, 12) i tri “mini” zajednice od po 1 čvor. To obično znači jedno od sljedećeg (ili kombinaciju):

  • u mreži postoje glavni komunikacijski “blokovi” (npr. veći odjeli ili funkcionalne cjeline),

  • uz njih postoje specijalizirane ili slabije povezane skupine,

  • pojedinačni čvorovi mogu biti izolirani u smislu strukture zajednica (npr. komuniciraju vrlo specifično ili imaju veze koje ih ne “uvlače” u klaster).

Isto možemo uočiti kroz detaljniji presjek:

# Matrica broja bridova između zajednica
mix_mat <- matrix(0, nrow = length(unique(membership)), ncol = length(unique(membership))) #walktrap
for(i in seq_len(nrow(endsU))) {
  a <- membership[endsU[i,1]]
  b <- membership[endsU[i,2]]
  mix_mat[a,b] <- mix_mat[a,b] + 1
  mix_mat[b,a] <- mix_mat[b,a] + 1
}
diag(mix_mat) <- diag(mix_mat) / 2  # jer smo brojali simetrično

mix_mat[1:min(10,nrow(mix_mat)), 1:min(10,ncol(mix_mat))]
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,]   45    7   74    5    7    0    0    0
## [2,]    7  857  589   19    9    0    0    1
## [3,]   74  589  967   24  139    1    1    0
## [4,]    5   19   24   83    0    0    0    0
## [5,]    7    9  139    0  182    0    0    0
## [6,]    0    0    1    0    0    0    0    0
## [7,]    0    0    1    0    0    0    0    0
## [8,]    0    1    0    0    0    0    0    0

Za komunikacijske mreže smisleno je izračunati barem: in/out-degree, betweenness (posredovanje), closeness, eigenvector / PageRank (utjecaj/prestiž). U praksi je korisno usporediti top-liste prema više mjera jer hvataju različite uloge čvorova.

# Centralnosti računamo na najvećoj komponenti
# (a) stupnjevi (usmjereno)
deg_in  <- igraph::degree(g_giant, mode = "in", normalized = TRUE)
deg_out <- igraph::degree(g_giant, mode = "out", normalized = TRUE)

# (b) betweenness
bet <- igraph::betweenness(gU, normalized = TRUE)

# (c) closeness
clo <- igraph::closeness(gU, normalized = TRUE)

# (d) eigenvector i PageRank
eig <- igraph::eigen_centrality(gU, directed = FALSE, scale = TRUE)$vector
pr  <- igraph::page_rank(g_giant, directed = TRUE)$vector

cent <- data.frame(
  indegree = as.numeric(deg_in),
  outdegree = as.numeric(deg_out),
  betweenness = as.numeric(bet),
  closeness = as.numeric(clo),
  eigen = as.numeric(eig),
  pagerank = as.numeric(pr)
)


# Top 10 po različitim mjerama
top_n <- function(df, col, n = 10) df[order(df[[col]], decreasing = TRUE), ][1:n, ]

list(
  top_indegree = top_n(cent, "indegree", 10),
  top_outdegree = top_n(cent, "outdegree", 10),
  top_betweenness = top_n(cent, "betweenness", 10),
  top_closeness = top_n(cent, "closeness", 10),
  top_eigen = top_n(cent, "eigen", 10),
  top_pagerank = top_n(cent, "pagerank", 10)
)
## $top_indegree
##      indegree outdegree betweenness closeness     eigen    pagerank
## 82  0.3314917 0.5524862 0.123418305 0.7098039 1.0000000 0.019499337
## 107 0.3149171 0.4033149 0.040072742 0.6284722 0.8414783 0.017867863
## 125 0.2651934 0.2596685 0.017726153 0.5857605 0.5672020 0.016988577
## 156 0.2486188 0.2375691 0.021486735 0.5819936 0.6104714 0.013002370
## 52  0.2320442 0.1270718 0.005054067 0.5535168 0.5727606 0.011731762
## 78  0.1988950 0.2099448 0.011122947 0.5656250 0.5785657 0.011014652
## 28  0.1933702 0.1988950 0.009411082 0.5621118 0.5743921 0.008925100
## 7   0.1878453 0.1657459 0.015235219 0.5603715 0.5091306 0.009453853
## 139 0.1878453 0.1878453 0.012614311 0.5535168 0.4944151 0.009595810
## 5   0.1657459 0.1602210 0.006188785 0.5501520 0.5326117 0.008531714
## 
## $top_outdegree
##      indegree outdegree betweenness closeness     eigen    pagerank
## 82  0.3314917 0.5524862  0.12341831 0.7098039 1.0000000 0.019499337
## 152 0.1602210 0.4696133  0.10788023 0.6630037 0.8378317 0.007751664
## 105 0.1049724 0.4640884  0.09578141 0.6557971 0.8460215 0.005367017
## 107 0.3149171 0.4033149  0.04007274 0.6284722 0.8414783 0.017867863
## 94  0.1325967 0.3038674  0.04463799 0.6033333 0.6713991 0.006639500
## 125 0.2651934 0.2596685  0.01772615 0.5857605 0.5672020 0.016988577
## 64  0.1104972 0.2541436  0.02396730 0.5586420 0.4874609 0.006666727
## 156 0.2486188 0.2375691  0.02148674 0.5819936 0.6104714 0.013002370
## 166 0.1602210 0.2320442  0.04816564 0.5586420 0.3899419 0.008328763
## 90  0.1270718 0.2265193  0.01707497 0.5339233 0.3680846 0.007235625
## 
## $top_betweenness
##      indegree outdegree betweenness closeness     eigen    pagerank
## 82  0.3314917 0.5524862  0.12341831 0.7098039 1.0000000 0.019499337
## 152 0.1602210 0.4696133  0.10788023 0.6630037 0.8378317 0.007751664
## 105 0.1049724 0.4640884  0.09578141 0.6557971 0.8460215 0.005367017
## 166 0.1602210 0.2320442  0.04816564 0.5586420 0.3899419 0.008328763
## 94  0.1325967 0.3038674  0.04463799 0.6033333 0.6713991 0.006639500
## 107 0.3149171 0.4033149  0.04007274 0.6284722 0.8414783 0.017867863
## 64  0.1104972 0.2541436  0.02396730 0.5586420 0.4874609 0.006666727
## 156 0.2486188 0.2375691  0.02148674 0.5819936 0.6104714 0.013002370
## 125 0.2651934 0.2596685  0.01772615 0.5857605 0.5672020 0.016988577
## 90  0.1270718 0.2265193  0.01707497 0.5339233 0.3680846 0.007235625
## 
## $top_closeness
##      indegree outdegree betweenness closeness     eigen    pagerank
## 82  0.3314917 0.5524862 0.123418305 0.7098039 1.0000000 0.019499337
## 152 0.1602210 0.4696133 0.107880232 0.6630037 0.8378317 0.007751664
## 105 0.1049724 0.4640884 0.095781408 0.6557971 0.8460215 0.005367017
## 107 0.3149171 0.4033149 0.040072742 0.6284722 0.8414783 0.017867863
## 94  0.1325967 0.3038674 0.044637994 0.6033333 0.6713991 0.006639500
## 125 0.2651934 0.2596685 0.017726153 0.5857605 0.5672020 0.016988577
## 156 0.2486188 0.2375691 0.021486735 0.5819936 0.6104714 0.013002370
## 78  0.1988950 0.2099448 0.011122947 0.5656250 0.5785657 0.011014652
## 28  0.1933702 0.1988950 0.009411082 0.5621118 0.5743921 0.008925100
## 7   0.1878453 0.1657459 0.015235219 0.5603715 0.5091306 0.009453853
## 
## $top_eigen
##      indegree outdegree betweenness closeness     eigen    pagerank
## 82  0.3314917 0.5524862 0.123418305 0.7098039 1.0000000 0.019499337
## 105 0.1049724 0.4640884 0.095781408 0.6557971 0.8460215 0.005367017
## 107 0.3149171 0.4033149 0.040072742 0.6284722 0.8414783 0.017867863
## 152 0.1602210 0.4696133 0.107880232 0.6630037 0.8378317 0.007751664
## 94  0.1325967 0.3038674 0.044637994 0.6033333 0.6713991 0.006639500
## 156 0.2486188 0.2375691 0.021486735 0.5819936 0.6104714 0.013002370
## 78  0.1988950 0.2099448 0.011122947 0.5656250 0.5785657 0.011014652
## 28  0.1933702 0.1988950 0.009411082 0.5621118 0.5743921 0.008925100
## 52  0.2320442 0.1270718 0.005054067 0.5535168 0.5727606 0.011731762
## 125 0.2651934 0.2596685 0.017726153 0.5857605 0.5672020 0.016988577
## 
## $top_pagerank
##      indegree  outdegree betweenness closeness     eigen    pagerank
## 82  0.3314917 0.55248619 0.123418305 0.7098039 1.0000000 0.019499337
## 107 0.3149171 0.40331492 0.040072742 0.6284722 0.8414783 0.017867863
## 125 0.2651934 0.25966851 0.017726153 0.5857605 0.5672020 0.016988577
## 156 0.2486188 0.23756906 0.021486735 0.5819936 0.6104714 0.013002370
## 96  0.1381215 0.11049724 0.007830343 0.5402985 0.3925672 0.012152026
## 52  0.2320442 0.12707182 0.005054067 0.5535168 0.5727606 0.011731762
## 78  0.1988950 0.20994475 0.011122947 0.5656250 0.5785657 0.011014652
## 132 0.1602210 0.18232044 0.009060741 0.5586420 0.4676761 0.010243417
## 50  0.1546961 0.03867403 0.003816161 0.5142045 0.3319927 0.009890089
## 66  0.1657459 0.09944751 0.005077675 0.5142045 0.3861329 0.009856169

Mjere centralnosti pokazuju da se isti čvor (u našem ispisu to je indeks 82) pojavljuje na vrhu u više mjera (in-degree, out-degree, betweenness, closeness, eigenvector, PageRank). To je tipičan znak hub-a / ključnog posrednika: osoba ima mnogo dolaznih i odlaznih kontakata (stupnjevi), nalazi se na mnogim najkraćim putevima (betweenness), relativno je blizu svima (closeness), povezana je s drugim dobro povezanim čvorovima (eigenvector) i ima visok “prestiž” u usmjerenom smislu (PageRank). Čvorovi koji su visoko po out-degree, ali ne nužno po in-degree, često odgovaraju ulogama “broadcasta” (npr. netko tko šalje obavijesti), dok visoki in-degree može značiti da se osoba često kontaktira (npr. koordinacija, podrška, administracija ili menadžment).

set.seed(3)
lay_enron <- layout_with_fr(g_giant) 

par(mfrow=c(3,2))

V(g_giant)$indegree <- cent$indegree
V(g_giant)$outdegree <- cent$outdegree
V(g_giant)$close <- cent$closeness
V(g_giant)$betwe <- cent$betweenness
V(g_giant)$eigen <- cent$eigen
V(g_giant)$pagerank <- cent$pagerank


plot(
  g_giant,
  layout = lay_enron,
  vertex.size = V(g_giant)$indegree*20,
  vertex.label = NA,
  vertex.color = V(g_giant)$walktrap,
  edge.arrow.size = 0.25,
  edge.width = E(g_giant)$weight,
  main = "Enron mreža (giant weak component) \n veličina čvora = indegree"
)

plot(
  g_giant,
  layout = lay_enron,
  vertex.size = V(g_giant)$outdegree*20,
  vertex.label = NA,
  vertex.color = V(g_giant)$walktrap,
  edge.arrow.size = 0.25,
  edge.width = E(g_giant)$weight,
  main = "Enron mreža (giant weak component) \n veličina čvora = outdegree"
)

plot(
  g_giant,
  layout = lay_enron,
  vertex.size = V(g_giant)$close*20,
  vertex.label = NA,
  vertex.color = V(g_giant)$walktrap,
  edge.arrow.size = 0.25,
  edge.width = E(g_giant)$weight,
  main = "Enron mreža (giant weak component) \n veličina čvora = closeness"
)

plot(
  g_giant,
  layout = lay_enron,
  vertex.size = V(g_giant)$betwe*200,
  vertex.label = NA,
  vertex.color = V(g_giant)$walktrap,
  edge.arrow.size = 0.25,
  edge.width = E(g_giant)$weight,
  main = "Enron mreža (giant weak component) \n veličina čvora = betweenness"
)

plot(
  g_giant,
  layout = lay_enron,
  vertex.size = V(g_giant)$eigen*20,
  vertex.label = NA,
  vertex.color = V(g_giant)$walktrap,
  edge.arrow.size = 0.25,
  edge.width = E(g_giant)$weight,
  main = "Enron mreža (giant weak component) \n veličina čvora = eigenvector"
)

plot(
  g_giant,
  layout = lay_enron,
  vertex.size = V(g_giant)$pagerank*500,
  vertex.label = NA,
  vertex.color = V(g_giant)$walktrap,
  edge.arrow.size = 0.25,
  edge.width = E(g_giant)$weight,
  main = "Enron mreža (giant weak component) \n veličina čvora = page rank"
)

Vizualizacije s bojom po zajednici i veličinom čvora po različitim centralnostima pomažu da se ove interpretacije “vide”: velike točke koje su ujedno na granicama boja često su mostovi između zajednica (visok betweenness), dok velike točke duboko unutar jedne boje često označavaju lokalne centre unutar jedne grupe (visok eigenvector/closeness u tom klasteru). U daljnjoj analizi ima smisla povezati top-čvorove s atributom Note (uloga/pozicija) i provjeriti jesu li “centralni” čvorovi doista menadžment/koordinacija ili se radi o operativnim ulogama koje prirodno komuniciraju sa svima (npr. pravna služba, pomoćnici, IT podrška).



Unipu - kolegiji

Za drugi skup podataka, koristit ćemo suradnju nastavnika na kolegijima na našem Sveučilištu. Ovdje ne promatramo “tko s kim prijateljuje”, nego strukturni trag nastavne organizacije: čvorovi su nastavnici, a bridovi nastaju jer se osobe pojavljuju na istom kolegiju (kao nositelji ili izvođači). Time mreža istodobno hvata suradničku dimenziju (N–N i I–I su simetrične veze) i dimenziju odgovornosti (I→N je usmjereni odnos prema nositelju).

Podatke ćemo preuzeti s web stranica. Organizacija je sljedeća.

Ovdje je popis sastavnica: https://www.unipu.hr/sastavnice

Onda su popisi zaposlenika po sastavnici dostupni na:

https://fipu.unipu.hr/fipu/o_fakultetu/nastavnici

https://fpz.unipu.hr/fpz/o_fakultetu/nastavnici

https://fooz.unipu.hr/fooz/o_fakultetu/nastavnici

https://ffpu.unipu.hr/ffpu/o_fakultetu/nastavnici

https://mfpu.unipu.hr/mfpu/o_fakultetu/nastavnici

https://mapu.unipu.hr/mapu/o_akademiji/nastavnici

https://tfpu.unipu.hr/tfpu/o_fakultetu/nastavnici

https://fet.unipu.hr/fet/o_fakultetu/nastavnici

Svako ime je ujedno i poveznica, poveznica vodi npr na stranicu nastavnika i tu je popis kolegija, organiziran u sekciji nastava i podijeljen na prijediplomski i diplomski. Svaki kolegij je poveznica na informacije o kolegiju, koji na početku ima popis nositelja i izvođača.

U nastavku je skup funkcija u R-u za scrapeanje opisane UNIPU strukture:

  1. s popisa nastavnika po sastavnici uzima URL-ove profila,
  2. s profila uzima URL-ove predmeta i ulogu nastavnika na predmetu,
  3. sa stranice predmeta uzima Nositelje i Izvođače.

Napomena: koristimo polite radi “pristojnog” dohvaćanja (robots, rate limit), a parsiranje radimo s rvest. Funkcije vraćaju uredne tablice (tibble) prikladne za kasniju gradnju bipartitnog grafa u igraph.

library(polite)
library(rvest)
library(dplyr)
library(stringr)
library(purrr)
library(tidyr)


# Primjer koda generiranog uz pomoć ChatGPT-a 5.2.
#------------------------------------------------------------
# Pomoćne funkcije
#------------------------------------------------------------

txt2 <- function(x) x |> html_text2() |> str_squish()

safe_bow <- function(url, ua = "SNA-teaching (contact: your_email@unipu.hr)") {
  bow(url, user_agent = ua)
}

safe_scrape <- function(session) {
  tryCatch(scrape(session), error = function(e) NULL)
}

abs_url <- function(href, base) {
  if (is.na(href) || href == "") return(NA_character_)
  xml2::url_absolute(href, base)
}

get_component_from_url <- function(url) {
  str_match(url, "unipu\\.hr/([^/]+)/")[,2]
}

canonical_staff_url <- function(url) {
  comp <- str_match(url, "https?://([^\\.]+)\\.unipu\\.hr/")[,2]
  slug <- str_match(url, "([a-z0-9]+\\.[a-z0-9]+)$")[,2]
  if (is.na(comp) || is.na(slug)) return(NA_character_)
  paste0("https://", comp, ".unipu.hr/", comp, "/", slug)
}

parse_people <- function(lines, role_label) {
  if (length(lines) == 0) return(tibble(osoba = character(), detalj = character(), uloga = character()))

  tibble(raw = str_squish(lines)) |>
    filter(raw != ":", raw != "", !str_detect(raw, "^(Nositelji|Izvođači)\\s*:??$")) |>
    transmute(
      osoba  = str_trim(str_remove(raw, "\\s*\\-\\s*.*$")),
      detalj = str_trim(str_extract(raw, "(?<=\\-\\s).*")),
      uloga  = role_label
    ) |>
    mutate(detalj = if_else(is.na(detalj), "", detalj))
}

#------------------------------------------------------------
# (1) Popis nastavnika po sastavnici -> URL-ovi profila
#------------------------------------------------------------

unipu_get_staff_urls <- function(nastavnici_url) {

  component <- get_component_from_url(nastavnici_url)

  ses <- safe_bow(nastavnici_url)
  doc <- safe_scrape(ses)
  if (is.null(doc)) {
    return(tibble(staff_url = character(), staff_name = character(), component = character()))
  }

  base <- ses$url

  a <- doc |> html_elements("a")
  href <- a |> html_attr("href")
  nm   <- a |> txt2()

  tibble(href = href, staff_name = nm) |>
    mutate(url_raw = map_chr(href, abs_url, base = base)) |>
    filter(!is.na(url_raw)) |>
    filter(str_detect(url_raw, "([a-z0-9]+\\.[a-z0-9]+)$")) |>
    mutate(staff_url = map_chr(url_raw, canonical_staff_url)) |>
    filter(!is.na(staff_url)) |>
    distinct(staff_url, .keep_all = TRUE) |>
    mutate(component = component) |>
    select(staff_url, staff_name, component)
}


#------------------------------------------------------------
# (2) Profil nastavnika -> predmeti (URL) + uloga(e) na predmetu
#------------------------------------------------------------

unipu_parse_staff_profile <- function(staff_url, component) {

  ses <- safe_bow(staff_url)
  doc <- safe_scrape(ses)
  if (is.null(doc)) {
    return(tibble(
      staff_url = staff_url,
      predmet_url = character(),
      predmet = character(),
      staff_role = character()
    ))
  }

  base <- ses$url

  a <- doc |> html_elements("a")
  a_txt  <- a |> txt2()
  a_href <- a |> html_attr("href")

  predmet_links <- tibble(a_txt = a_txt, href = a_href) |>
    filter(str_detect(a_txt, "\\(\\d+\\)")) |>
    mutate(predmet_url = map_chr(href, abs_url, base = base)) |>
    mutate(predmet = str_trim(str_remove(a_txt, "\\s*\\(\\d+\\)\\s*$"))) |>
    distinct(predmet_url, .keep_all = TRUE)

  li_txt <- doc |> html_elements("li") |> txt2()
  li_pred <- li_txt |> keep(~ str_detect(.x, "\\(\\d+\\)"))

  staff_roles <- tibble(raw = li_pred) |>
    transmute(
      predmet = str_trim(str_remove(raw, "\\s*\\(\\d+\\).*")),
      staff_role = str_trim(str_extract(raw, "(?<=\\-\\s).*"))
    )

  predmet_links |>
    left_join(staff_roles, by = "predmet") |>
    mutate(staff_url = staff_url) |>
    select(staff_url, predmet_url, predmet, staff_role)
}

unipu_parse_staff_profile_predmeti <- function(staff_url) {

  ses <- safe_bow(staff_url)
  doc <- safe_scrape(ses)
  if (is.null(doc)) {
    return(tibble(
      predmet_url = character(),
      predmet = character(),
      predmet_comp = character()
    ))
  }

  base <- ses$url

  a <- doc |> html_elements("a")
  href <- a |> html_attr("href")
  txt  <- a |> txt2()

  tibble(href = href, predmet = txt) |>
    mutate(predmet_url = map_chr(href, abs_url, base = base)) |>
    filter(!is.na(predmet_url)) |>
    filter(str_detect(predmet_url, "unipu\\.hr/[^/]+/predmet/[a-z0-9]+$")) |>
    mutate(
      predmet = str_squish(predmet),
      predmet_comp = get_component_from_url(predmet_url)
    ) |>
    distinct(predmet_url, .keep_all = TRUE) |>
    select(predmet_comp, predmet_url, predmet)
}

#------------------------------------------------------------
# (3) Stranica predmeta -> Nositelji i Izvođači
#------------------------------------------------------------

unipu_parse_predmet_roles <- function(predmet_url) {

  ses <- safe_bow(predmet_url)
  doc <- safe_scrape(ses)
  comp <- get_component_from_url(predmet_url)

  if (is.null(doc)) {
    return(tibble(predmet_comp = comp, predmet = character(), osoba = character(), uloga = character()))
  }

  predmet <- doc |> html_element("h1") |> txt2()
  page_txt <- doc |> html_text2() |> str_replace_all("\r", "\n")

  extract_block <- function(label) {
    # toleriramo i bez dvotočke
    label2 <- str_remove(label, ":")
    loc <- str_locate(page_txt, regex(paste0(label2, "\\s*:??"), ignore_case = FALSE))[1,]
    if (any(is.na(loc))) return(character())

    after <- str_sub(page_txt, loc[2] + 1)

    # rezanje na idući blok (grubo, ali stabilno)
    stop_loc <- str_locate(after, regex("(Nositelji|Izvođači|DETALJNE INFORMACIJE|Prijava ispita)", ignore_case = FALSE))[1,1]
    if (is.na(stop_loc)) stop_loc <- nchar(after) + 1

    blk <- str_sub(after, 1, stop_loc - 1)

    blk |>
      str_split("\n") |>
      pluck(1) |>
      map_chr(str_squish) |>
      discard(~ .x == "" || str_detect(.x, "^(Nositelji|Izvođači)"))
  }

  nos <- extract_block("Nositelji:")
  izv <- extract_block("Izvođači:")

  parse_people <- function(lines, role_label) {
    if (length(lines) == 0) return(tibble(osoba = character(), uloga = character()))
    tibble(osoba = str_squish(lines), uloga = role_label)
  }

  bind_rows(
    parse_people(nos, "Nositelj"),
    parse_people(izv, "Izvođač")
  ) |>
    mutate(
      predmet_comp = comp,
      predmet = predmet
    ) |>
    select(predmet_comp, predmet, osoba, uloga)
}

#------------------------------------------------------------
# (4) End-to-end: sastavnica -> profili -> predmeti -> nositelji/izvođači
#------------------------------------------------------------

unipu_scrape_component <- function(nastavnici_url) {

  staff <- unipu_get_staff_urls(nastavnici_url)

  staff_predmeti <- staff |>
    mutate(predmeti = map(staff_url, unipu_parse_staff_profile_predmeti)) |>
    select(component, staff_url, staff_name, predmeti) |>
    unnest(predmeti)

  predmeti_unique <- staff_predmeti |>
    distinct(predmet_url)

  list(
    staff_index = staff,
    staff_predmeti = staff_predmeti,
    predmet_roles = predmeti_unique |>
      mutate(roles = map(predmet_url, unipu_parse_predmet_roles)) |>
      unnest(roles) |>
      select(predmet_url, everything())
  )
}


urls <- c(
  "https://fipu.unipu.hr/fipu/o_fakultetu/nastavnici",
  "https://fpz.unipu.hr/fpz/o_fakultetu/nastavnici",
  "https://fooz.unipu.hr/fooz/o_fakultetu/nastavnici",
  "https://ffpu.unipu.hr/ffpu/o_fakultetu/nastavnici",
  "https://mfpu.unipu.hr/mfpu/o_fakultetu/nastavnici", 
  "https://mapu.unipu.hr/mapu/o_akademiji/nastavnici",  
  "https://tfpu.unipu.hr/tfpu/o_fakultetu/nastavnici",  
  "https://fet.unipu.hr/fet/o_fakultetu/nastavnici")

res <- map(urls, unipu_scrape_component)
names(res) <- urls
saveRDS(res, "unipu_kolegiji_nastavnici.rds")
unipu_kolegiji_nastavnici <- readRDS("unipu_kolegiji_nastavnici.rds")

# ovdje se ne prikazuje head() niti str() zato jer ćemo prvo anonimizirati podatke
library(dplyr)
library(stringr)
library(purrr)
library(tidyr)
library(igraph)

# Pomoćne funkcije

clean_person <- function(x) {
  x <- stringr::str_replace_all(x, "\u00A0", " ")
  x <- stringr::str_squish(x)
  x <- stringr::str_remove(x, "\\s*\\-\\s*.*$")
  
  titule_pattern <- stringr::regex(
    "(?<![\\w])(prof|doc|dr|sc|mr|izv|red|art|mag|nasl|pred|v|lekt|ing|oec|inf|comp|educ|bac|dipl|sur|umj|philol|angl|el|techn|med|dent|bibl|croat|oecol|et|prot|nat)\\.\\s*",
    ignore_case = TRUE
  )
  
  repeat {
    x_new <- stringr::str_remove_all(x, titule_pattern)
    x_new <- stringr::str_squish(x_new)
    if (identical(x_new, x)) break
    x <- x_new
  }
  
  x <- stringr::str_remove_all(x, ",")
  x <- stringr::str_squish(x)
  x <- stringi::stri_trans_nfc(x)
  x
}

extract_detail <- function(x) {
  x <- str_squish(x)
  det <- str_extract(x, "(?<=\\-\\s).*")
  if_else(is.na(det), "", str_squish(det))
}

make_ids <- function(x, digits = 3) {
  n <- length(x)
  d <- digits
  while (n > (10^d - 1)) d <- d + 1

  tibble(
    osoba_clean = x,
    osoba_id = str_pad(seq_len(n), width = d, pad = "0")
  )
}

# Pomoćna: svi parovi (bez self-loop), dvosmjerno kao 2 usmjerena brida
all_pairs_bidirectional <- function(ids) {
  ids <- unique(ids)
  if (length(ids) < 2) {
    return(tibble(from = character(), to = character()))
  }
  cmb <- t(combn(ids, 2))
  tibble(from = cmb[,1], to = cmb[,2]) |>
    bind_rows(tibble(from = cmb[,2], to = cmb[,1])) |>
    filter(from != to)
}

get_component_from_staff_url <- function(url) {
  str_match(url, "^https?://[^/]+/([^/]+)/")[, 2]
}

get_component_from_url <- function(url) {
  str_match(url, "^https?://[^/]+/([^/]+)/")[,2]
}

# Učitaj i spljošti predmet_roles

# unipu_kolegiji_nastavnici <- readRDS("unipu_kolegiji_nastavnici.rds")

predmet_roles_all <- imap_dfr(
  unipu_kolegiji_nastavnici,
  ~ .x$predmet_roles |> mutate(source_nastavnici_url = .y)
)

predmet_roles_clean <- predmet_roles_all |>
  filter(!is.na(osoba)) |>
  mutate(osoba = str_squish(osoba)) |>
  filter(osoba != ":", osoba != "") |>
  mutate(
    detalj = extract_detail(osoba),
    osoba_clean = clean_person(osoba)
  ) |>
  filter(osoba_clean != "")

# anonimizacija

osobe_unique <- predmet_roles_clean |>  
  distinct(osoba_clean) |>
  arrange(osoba_clean) |>
  pull(osoba_clean)

id_map <- make_ids(osobe_unique, digits = 3)

predmet_roles_anon <- predmet_roles_clean |>
  left_join(id_map, by = "osoba_clean")

# Očisti osobe (makni ":" i normaliziraj ime) 

staff_comp_map_raw <- imap_dfr(
  unipu_kolegiji_nastavnici,
  ~ .x$staff_index %>% mutate(source_nastavnici_url = .y)
) |>
  mutate(
    sastavnica_nast  = get_component_from_staff_url(staff_url),  
    staff_name_clean = clean_person(staff_name)
  ) |>
  left_join(id_map, by = c("staff_name_clean" = "osoba_clean"))

staff_comp_map <- staff_comp_map_raw |>
  filter(!is.na(osoba_id), !is.na(sastavnica_nast), sastavnica_nast != "") |>
  group_by(osoba_id) |>
  summarise(
    sastavnica_nastavnika = paste(sort(unique(sastavnica_nast)), collapse = " | "),
    n_sastavnica = n_distinct(sastavnica_nast),
    .groups = "drop"
  )

# Vertex tablica (detalji idu u vertex atribute) za ručnu provjeru
# - detalj može biti višestruk: spajamo sve jedinstvene detalje koje osoba ima
vertices <- predmet_roles_anon |>
  group_by(osoba_id) |>
  summarise(
    detalj      = paste(sort(unique(detalj[detalj != ""])), collapse = " | "),
    osoba_clean = first(osoba_clean),
    .groups     = "drop"
  ) |>
  mutate(detalj = if_else(detalj == "", NA_character_, detalj)) |>
  left_join(staff_comp_map, by = "osoba_id") |>  
  rename(name = osoba_id)

# Potpuno anonimiziran izlaz bez imena:
predmet_roles_anon_out <- predmet_roles_anon |>
  select(predmet_url, predmet_comp, predmet, uloga, osoba_id, detalj)

# Veze po predmetu: N<->N, I->N, I<->I

edges <- predmet_roles_anon |>
  select(predmet_url, predmet_comp, predmet, uloga, osoba_id) |>
  distinct() |>
  group_by(predmet_url, predmet_comp, predmet) |>
  summarise(
    nositelji = list(unique(osoba_id[uloga == "Nositelj"])),
    izvodaci  = list(unique(osoba_id[uloga == "Izvođač"])),
    .groups = "drop"
  ) |>
  mutate(
    # (a) Nositelj ↔ Nositelj
    nn = map(nositelji, all_pairs_bidirectional),

    # (b) Izvođač ↔ Izvođač
    ii = map(izvodaci, all_pairs_bidirectional),

    # (c) Izvođač → Nositelj (jednosmjerno)
    in_dir = map2(izvodaci, nositelji, ~ {
      if (length(.x) == 0 || length(.y) == 0) {
        tibble(from = character(), to = character())
      } else {
        tidyr::expand_grid(from = .x, to = .y) |> filter(from != to)
      }
    })
  ) |>
  transmute(
    predmet_url, predmet_comp, predmet,
    edges = pmap(list(nn, ii, in_dir), \(nn, ii, in_dir) bind_rows(
      nn  |> mutate(edge_type = "N-N"),
      ii  |> mutate(edge_type = "I-I"),
      in_dir |> mutate(edge_type = "I->N")
    ))
  ) |>
  unnest(edges) |>
  filter(from != to)

Postupak konstrukcije mreže započinje objedinjavanjem svih zapisa o nositeljima i izvođačima kolegija sa svih sastavnica Sveučilišta. Izvorni zapisi se najprije čiste: uklanjaju se tehnički artefakti (npr. znak “:”), standardiziraju se imena osoba te se izdvaja eventualni dodatni opis (npr. “Seminar”, “Vježbe”). Time se osigurava da svaka osoba bude jednoznačno prepoznata bez obzira na varijacije u zapisu titula ili interpunkcije.

U sljedećem koraku provodi se anonimizacija. Svako jedinstveno ime mapira se na numerički identifikator fiksne duljine, pri čemu se ista osoba u svim zapisima pojavljuje pod istim ID-om. Time se omogućuje analiza strukture mreže bez izlaganja osobnih podataka, uz zadržavanje mogućnosti naknadne interne provjere mapiranja.

Konstrukcija bridova temelji se na logici sudjelovanja na istom kolegiju. Za svaki kolegij generiraju se tri tipa odnosa: (i) dvosmjerne veze između svih nositelja, (ii) dvosmjerne veze između svih izvođača te (iii) jednosmjerne veze od izvođača prema nositeljima. Na taj se način istodobno modelira suradnička dimenzija (simetrične veze unutar iste uloge) i hijerarhijska dimenzija odgovornosti (usmjereni odnos izvođač → nositelj).

Rezultat postupka je usmjereni graf u kojem:

  • čvorovi predstavljaju anonimizirane nastavnike,
  • bridovi predstavljaju zajednički angažman na kolegiju,
  • svaki brid nosi informaciju o sastavnici koja nudi kolegij i vrsti odnosa (N–N, I–I, I→N).

Dodatno, uz pomoć podatkovnog okvira vertices, možemo izvršiti ručnu provjeru kodiranja, kao i ekstrakciju sastavnice nastavnika.

Takva struktura omogućuje paralelnu analizu gustoće, komponenti i zajednica (suradnička dimenzija), ali i analizu hijerarhije, usmjerenih tokova i pozicijske centralnosti (organizacijska dimenzija). Graf time postaje višeslojan prikaz akademske strukture – istodobno mreža suradnje i mreža odgovornosti.

unipu_sna_orig <- graph_from_data_frame(edges[, 4:5],
  directed = TRUE)

# Provjera
vcount(unipu_sna_orig)
## [1] 364
ecount(unipu_sna_orig)
## [1] 8497
unipu_sna_orig
## IGRAPH 64100d3 DN-- 364 8497 -- 
## + attr: name (v/c)
## + edges from 64100d3 (vertex names):
##  [1] 195->215 215->195 099->278 099->362 278->362 278->099 362->099 362->278
##  [9] 099->347 278->347 362->347 247->328 247->174 328->174 328->247 174->247
## [17] 174->328 174->138 138->174 174->247 174->328 138->247 138->328 138->174
## [25] 299->127 159->011 159->005 159->075 159->195 159->347 159->293 159->215
## [33] 159->199 159->165 159->225 159->058 159->328 159->214 159->142 159->114
## [41] 159->052 159->289 159->281 159->181 159->336 159->247 159->064 159->098
## [49] 159->127 159->208 159->354 159->170 159->048 159->065 159->012 159->274
## [57] 011->005 011->075 011->195 011->347 011->293 011->215 011->199 011->165
## + ... omitted several edges
# Dohvatimo imena verteksa iz grafa (u redoslijedu kako ih igraph vidi)
graph_vertex_names <- V(unipu_sna_orig)$name

# Filtriramo i sortiramo vertices da odgovara grafu
vertices_aligned <- vertices |>
  filter(name %in% graph_vertex_names) |>
  arrange(match(name, graph_vertex_names))

vertices_aligned <- vertices_aligned |>
  mutate(sastavnica_nastavnika = replace_na(sastavnica_nastavnika, "vanjski"))


# Dodjela atributa

E(unipu_sna_orig)$sastavnica <- edges$predmet_comp
E(unipu_sna_orig)$predmet <- edges$predmet
E(unipu_sna_orig)$type <- edges$edge_type
V(unipu_sna_orig)$sast_nast <- vertices_aligned$sastavnica_nastavnika
# boje
# definirani redoslijed sastavnica
unique(E(unipu_sna_orig)$sastavnica)
## [1] "fet"  "ffpu" "fipu" "fooz" "mapu" "mfpu" "tfpu" "fpz"
unique(V(unipu_sna_orig)$sast_nast)
##  [1] "fet"         "vanjski"     "fipu"        "tfpu"        "ffpu"       
##  [6] "fooz"        "mfpu"        "fpz"         "fipu | tfpu" "mapu"
comp_levels <- c("fet","ffpu","fipu","fooz","mfpu","tfpu","fpz","mapu", "vanjski")

# prilagođena paleta
comp_cols <- c(
  fet  = "#7D2E1E",   # terakota (crveno-smeđa)
  ffpu = "darkblue",  # tamno plavo
  fipu = "#99CCFF",   # svjetlo plavo (aqua)
  fooz = "#2A9D8F",   # pastelno zeleno / petrolej
  mfpu = "#D62828",   # crveno
  tfpu = "#2E5FA3",   # mornarsko plava
  fpz  = "#3A86FF",   # plava (srednje prema svjetlijem)
  mapu = "#F4A261",    # narančasta
  vanjski = "grey",          # siva za NA
  "fipu | tfpu" = "grey"
)

# dodjela boja bridovima
E(unipu_sna_orig)$col <- unname(comp_cols[E(unipu_sna_orig)$sastavnica])
V(unipu_sna_orig)$col_sast <- unname(comp_cols[V(unipu_sna_orig)$sast_nast])

# provjera
table(E(unipu_sna_orig)$sastavnica)
## 
##  fet ffpu fipu fooz  fpz mapu mfpu tfpu 
## 3129 1683  272 1710   61  475  533  634
table(E(unipu_sna_orig)$col)
## 
##  #2A9D8F  #2E5FA3  #3A86FF  #7D2E1E  #99CCFF  #D62828  #F4A261 darkblue 
##     1710      634       61     3129      272      533      475     1683
table(V(unipu_sna_orig)$sast_nast)
## 
##         fet        ffpu        fipu fipu | tfpu        fooz         fpz 
##          37          48          15           1          23           9 
##        mapu        mfpu        tfpu     vanjski 
##          16          12          10         193
table(V(unipu_sna_orig)$col_sast)
## 
##  #2A9D8F  #2E5FA3  #3A86FF  #7D2E1E  #99CCFF  #D62828  #F4A261 darkblue 
##       23       10        9       37       15       12       16       48 
##     grey 
##      194
set.seed(7)
lay_o <- layout_with_fr(unipu_sna_orig)
plot(unipu_sna_orig,
     layout = lay_o,
     vertex.size = 4,
     vertex.label = NA,
     vertex.color = V(unipu_sna_orig)$col_sast,
     edge.color = E(unipu_sna_orig)$col,
     edge.width = 0.8,
     edge.arrow.size= 0.5,
     edge.curved = 0.05)

E(unipu_sna_orig)$weight <- 1

unipu_sna <- igraph::simplify(
  unipu_sna_orig,
  remove.multiple = TRUE,
  remove.loops = TRUE,
  edge.attr.comb = list(
    weight = "sum",
    sastavnica = "first",
    predmet = "first",
    col = "first",
    type = "first"
  )
)

Nakon simplify() mreža ima 364 čvora i 3177 jedinstvenih usmjerenih bridova, pri čemu weight označava koliko se puta isti par osoba povezao kroz različite kolegije / pojavljivanja (agregirani intenzitet suradnje).

set.seed(5)
lay_u <- layout_with_fr(unipu_sna)

plot(unipu_sna,
     layout = lay_u,
     vertex.size = 4,
     vertex.label = NA,
     vertex.color = V(unipu_sna)$col_sast,
     edge.color = E(unipu_sna)$col,
     edge.weight = E(unipu_sna)$weight,
     edge.arrow.size= 0.5,
     edge.curved = 0.05)

igraph::is_igraph(unipu_sna)
## [1] TRUE
igraph::is.directed(unipu_sna)
## [1] TRUE
# Broj čvorova i bridova
vcount(unipu_sna)
## [1] 364
ecount(unipu_sna)
## [1] 3177
# provjera atribute bridova i čvorova
vertex_attr_names(unipu_sna)
## [1] "name"      "sast_nast" "col_sast"
edge_attr_names(unipu_sna)
## [1] "sastavnica" "predmet"    "type"       "col"        "weight"
# Gustoća (za usmjereni graf: m / (n*(n-1)))
dens_all <- edge_density(unipu_sna, loops = FALSE)

# Komponente: za usmjerene mreže obično gledamo slabe i jake komponente
comp_weak   <- igraph::components(unipu_sna, "weak")
comp_strong <- igraph::components(unipu_sna, "strong")

# Veličine komponenti
sort(comp_weak$csize, decreasing = TRUE)
## [1] 344   4   3   3   2   2   2   2   2
sort(comp_strong$csize, decreasing = TRUE)
##  [1] 296   6   4   3   3   3   2   2   2   2   2   2   2   2   2   1   1   1   1
## [20]   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
## [39]   1   1   1   1   1   1   1   1

Gustoća je 0.024 (\(≈2.4%\)) na cijeloj mreži, a 0.0267 na najvećoj slaboj komponenti. To je očekivano: iako postoji puno potencijalnih parova nastavnika \(n(n−1)\), u praksi suradnje nastaju samo kroz konkretne kolegije, pa mreža ostaje rijetka. Istodobno, gustoća nije zanemariva — ukazuje na to da postoji dovoljno preklapanja angažmana da se mreža “drži zajedno”.

# Promjer (diameter) i prosječna duljina puta imaju smisla samo na povezanim dijelovima.
# Ovdje računamo na najvećoj slaboj komponenti (giant weak component), jer je to standardno za usmjerene mreže u praksi.
giant_weak_id <- which.max(comp_weak$csize)
V_giant <- V(unipu_sna)[comp_weak$membership == giant_weak_id]
g_weak_giant <- induced_subgraph(unipu_sna, vids = V_giant)

diam_giant <- diameter(g_weak_giant, directed = TRUE, unconnected = FALSE, weights = NA)
apl_giant  <- average.path.length(g_weak_giant, directed = TRUE, unconnected = FALSE)
# recipročnost i tranzitivnost
recip_all <- reciprocity(unipu_sna, ignore.loops = TRUE)
trans_all <- transitivity(as.undirected(unipu_sna, mode = "collapse"), type = "global")
# Sažetak (jedno mjesto)
basic_all <- data.frame(
  n = vcount(unipu_sna),
  m = ecount(unipu_sna),
  density = dens_all,
  reciprocity = recip_all,
  transitivity_undirected = trans_all,
  n_components_weak = comp_weak$no,
  n_components_strong = comp_strong$no,
  giant_weak_size = vcount(g_weak_giant),
  giant_weak_share = vcount(g_weak_giant) / vcount(unipu_sna),
  diameter_giant_weak = diam_giant,
  apl_giant_weak = apl_giant
)

basic_all
##     n    m    density reciprocity transitivity_undirected n_components_weak
## 1 364 3177 0.02404414   0.9216242               0.7379423                 9
##   n_components_strong giant_weak_size giant_weak_share diameter_giant_weak
## 1                  46             344        0.9450549                 Inf
##   apl_giant_weak
## 1            Inf

Slabe komponente pokazuju 9 komponenti, ali najveća ima 344 čvora, tj. oko 94.5% svih čvorova. To znači da je većina nastavnika (prema ovoj konstrukciji) posredno povezana preko lanaca zajedničkih kolegija: i ako dvije osobe nisu nikad radile zajedno, često postoji “put” preko drugih kolega i kolegija.

Jake komponente ih je 46, a najveća ima 296 čvorova. To je tipično za usmjerene mreže: da bi čvorovi bili u istoj jako povezanoj komponenti, moraju postojati usmjereni putovi u oba smjera. Budući da smo ugradili usmjereni odnos I→N (odgovornost), dio strukture prirodno postaje “asimetričan”, pa se strong komponente fragmentiraju.

Na najvećoj slaboj komponenti dobivamo diameter \(= 12\) i prosječnu duljinu puta \(≈ 4.30\), ali na “neobrađenoj” verziji izlazi Inf. Razlog je jednostavan: i unutar najveće slabe komponente mreža nije nužno jako povezana u usmjerenom smislu, pa za neke parove čvorova ne postoji usmjereni put (npr. možemo doći od izvođača do nositelja, ali ne nužno i obrnuto). Kad ograničimo analizu na dio i postavke gdje su putovi definirani, dobivamo konačne vrijednosti.

Ove vrijednosti (\(≈4\) koraka u prosjeku, promjer \(12\)) sugeriraju da mreža ima relativno kratke “nastavne udaljenosti”: preko nekoliko posrednih suradnji možemo povezati velik dio sustava.

dens_giant <- edge_density(g_weak_giant, loops = FALSE)
recip_giant <- reciprocity(g_weak_giant, ignore.loops = TRUE)
trans_giant <- transitivity(as.undirected(g_weak_giant, mode = "collapse"), type = "global")

basic_giant <- data.frame(
  n = vcount(g_weak_giant),
  m = ecount(g_weak_giant),
  density = dens_giant,
  reciprocity = recip_giant,
  transitivity_undirected = trans_giant,
  diameter = diameter(g_weak_giant, directed = TRUE),
  apl = average.path.length(g_weak_giant, directed = TRUE)
)

basic_giant
##     n    m    density reciprocity transitivity_undirected diameter      apl
## 1 344 3148 0.02667977   0.9218551               0.7378477       38 8.546502

Recipročnost je vrlo visoka: \(≈0.922\). To je očekivano jer smo eksplicitno generirali velik dio veza kao dvosmjerne (N–N i I–I), a i u praksi su suradnički odnosi na istom kolegiju simetrični. Preostali dio (I→N) uvodi asimetriju, ali ne dominira.

Tranzitivnost (global clustering) na neusmjerenoj projekciji je također visoka: \(≈0.738\). To znači da često vrijedi obrazac: ako A radi s B i B radi s C, onda A često radi i s C. U kontekstu kolegija to je intuitivno: nastavni timovi se ponavljaju, a angažmani se grupiraju oko istih programskih područja.

set.seed(5)
lay_giant <- layout_with_fr(g_weak_giant)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = 4,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component)"
)

# ilustrativno, mreža bez vanjskih suradnika
unipu_sna_interni <- induced_subgraph(
  unipu_sna,
  vids = V(unipu_sna)[V(unipu_sna)$sast_nast != "vanjski"]
)

Na ovoj mreži su vanjski suradnici isključeni, pa se dobiva jasniji uvid u odnose nastavnika.

set.seed(5)
lay_inter <- layout_with_fr(unipu_sna_interni)

plot(
  unipu_sna_interni,
  layout = lay_inter,
  vertex.size = 4,
  vertex.label = NA,
  vertex.color = V(unipu_sna_interni)$col_sast,
  edge.color = E(unipu_sna_interni)$col,
  edge.arrow.size = 0.25,
  edge.width = E(unipu_sna_interni)$weight,
  main = "UNIPU mreža (zaposlenici)"
)

# Napomena: većina algoritama zajednica radi na neusmjerenoj projekciji.
g_giant_u <- as.undirected(g_weak_giant, mode = "collapse", edge.attr.comb = "first")

# Louvain (brz i često dobar za veće mreže)
set.seed(5)
comm_louv <- cluster_louvain(g_giant_u)

# Walktrap (alternativa; može biti sporiji)
set.seed(5)
comm_wt <- cluster_walktrap(g_weak_giant, steps = 4)

# Veličine zajednica
sizes_louv <- sort(sizes(comm_louv), decreasing = TRUE)
sizes_wt   <- sort(sizes(comm_wt), decreasing = TRUE)

# Modularnost (kvaliteta particije)
mod_louv <- modularity(comm_louv)
mod_wt   <- modularity(comm_wt)

community_summary <- tibble(
  method = c("louvain", "walktrap"),
  n_communities = c(length(sizes_louv), length(sizes_wt)),
  modularity = c(mod_louv, mod_wt),
  largest_community_size = c(sizes_louv[1], sizes_wt[1])
)

community_summary
## # A tibble: 2 × 4
##   method   n_communities modularity largest_community_size
##   <chr>            <int>      <dbl>                  <int>
## 1 louvain             11      0.731                     63
## 2 walktrap            22      0.726                     64
# spremimo pripadnost zajednici kao atribut čvora (na giant component grafu)
V(g_weak_giant)$comm_louv <- membership(comm_louv)
V(g_weak_giant)$comm_wt   <- membership(comm_wt)

# Brzi prikaz zajednica (na giant component, ali bojanje čvorova po zajednici)

base_cols <- c('#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99','#e31a1c',
               '#fdbf6f','#ff7f00','#cab2d6','#6a3d9a','#ffff99'
)

# iz https://colorbrewer2.org/#type=qualitative&scheme=Paired&n=9

comm_ids <- sort(unique(V(g_weak_giant)$comm_louv))

V(g_weak_giant)$col_louv <- base_cols[V(g_weak_giant)$comm_louv]


plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = 4,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_louv,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  main = "Zajednice na giant component (Louvain; čvorovi obojani po zajednici)"
)

Na najvećoj komponenti Louvain daje 11 zajednica uz modularnost \(≈0.725\), a Walktrap 22 zajednice uz modularnost \(≈0.706\). Oba rezultata upućuju na snažnu modularnu strukturu: postoje jasne “grupe” koje su gusto povezane iznutra.

U ovom kontekstu te zajednice ne interpretiramo kao neformalnu strukturu, nego kao grupiranje po kompetencijama/ stručnosti i nastavnim područjima (tko tipično zajedno izvodi kolegije istog sadržajnog profila). Razlika u broju zajednica između algoritama je normalna: Walktrap često daje finiju segmentaciju, dok Louvain teži “krupnijim” blokovima.

Koja su preklapanja formalne (sastavnice) i strukovne (zajednice) strukture?

table(sastavnica = V(g_weak_giant)$sast_nast, 
      zajednica  = V(g_weak_giant)$comm_louv) |>
  as.data.frame() |>
  ggplot(aes(x = zajednica, y = sastavnica, fill = Freq)) +
  geom_tile() +
  geom_text(aes(label = Freq)) +
  scale_fill_gradient(low = "white", high = "#1A5276") +
  theme_minimal()

Vizualizacija razlike između formalne (sastavnice) i strukovne (zajednice) strukture:

# Sankey / alluvial dijagram - koja zajednica odgovara kojoj sastavnici
library(ggalluvial)

comp_comm_df <- tibble(
  sastavnica = V(g_weak_giant)$sast_nast,
  zajednica  = as.character(V(g_weak_giant)$comm_louv)
) |>
  count(sastavnica, zajednica)

ggplot(comp_comm_df, aes(axis1 = sastavnica, axis2 = zajednica, y = n)) +
  geom_alluvium(aes(fill = sastavnica)) +
  geom_stratum() +
  geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
  theme_minimal()

Udio veza između i unutar sastavnica:

edges_sast <- igraph::as_data_frame(g_weak_giant, what = "edges") |>
  select(from, to) |>  # uzmi samo from/to, preskoči problematične atribute
  left_join(tibble(from = V(g_weak_giant)$name, sast_from = V(g_weak_giant)$sast_nast), by = "from") |>
  left_join(tibble(to   = V(g_weak_giant)$name, sast_to   = V(g_weak_giant)$sast_nast), by = "to") |>
  mutate(tip = if_else(sast_from == sast_to, "unutar", "između"))

# Ukupni udio
edges_sast |> count(tip) |> mutate(udio = n / sum(n))
##      tip    n      udio
## 1 između 1712 0.5438374
## 2 unutar 1436 0.4561626
# Po sastavnici
edges_sast |>
  group_by(sast_from, tip) |>
  summarise(n = n(), .groups = "drop") |>
  group_by(sast_from) |>
  mutate(udio = n / sum(n)) |>
  pivot_wider(names_from = tip, values_from = c(n, udio), values_fill = 0)
## # A tibble: 10 × 5
## # Groups:   sast_from [10]
##    sast_from   n_između n_unutar udio_između udio_unutar
##    <chr>          <int>    <int>       <dbl>       <dbl>
##  1 fet              294      527       0.358       0.642
##  2 ffpu             208      343       0.377       0.623
##  3 fipu              89       28       0.761       0.239
##  4 fipu | tfpu        4        0       1           0    
##  5 fooz             153      118       0.565       0.435
##  6 fpz               36        9       0.8         0.2  
##  7 mapu              27       19       0.587       0.413
##  8 mfpu              52       35       0.598       0.402
##  9 tfpu              75       31       0.708       0.292
## 10 vanjski          774      326       0.704       0.296

Kad gledamo bridove po sastavnici nastavnika (atribut čvora), dobivamo da je ukupno više veza između sastavnica (\(≈54.4%\)) nego unutar (\(≈45.6%\)). To je uvelike vezano uz angažman vanjskih suradnika, koji kao “vanjski” predstavljaju zasebnu skupinu (sastavnicu). No, vanjski suradnici imaju tendenciju raditi na više sastavnica, kao i mnogi nastavnici i suradnici, što sugerira da se velik dio nastave oslanja na među-sastavničko povezivanje i vanjske suradnike.

Na razini pojedinih sastavnica vidimo različite obrasce. Npr. FET i FFPU imaju veći udio veza unutar (\(≈0.62–0.64\)), dok FIPU, TFPU i FPZ imaju znatno veći udio suradnji između sastavnica (\(≈0.71–0.80\)). To je konzistentno s idejom da neke sastavnice većinu nastave organiziraju interno, dok su druge orijentirane na suradnju i interdisciplinarnost.

Udio veza između i unutar zajednica:

edges_comm <- igraph::as_data_frame(g_weak_giant, what = "edges") |>
  select(from, to) |>
  left_join(tibble(from = V(g_weak_giant)$name, comm_from = as.character(V(g_weak_giant)$comm_louv)), by = "from") |>
  left_join(tibble(to   = V(g_weak_giant)$name, comm_to   = as.character(V(g_weak_giant)$comm_louv)), by = "to") |>
  mutate(tip = if_else(comm_from == comm_to, "unutar", "između"))

# Ukupni udio
edges_comm |> count(tip) |> mutate(udio = n / sum(n))
##      tip    n       udio
## 1 između  226 0.07179161
## 2 unutar 2922 0.92820839
# Po zajednici
edges_comm |>
  group_by(comm_from, tip) |>
  summarise(n = n(), .groups = "drop") |>
  group_by(comm_from) |>
  mutate(udio = n / sum(n)) |>
  pivot_wider(names_from = tip, values_from = c(n, udio), values_fill = 0)
## # A tibble: 11 × 5
## # Groups:   comm_from [11]
##    comm_from n_između n_unutar udio_između udio_unutar
##    <chr>        <int>    <int>       <dbl>       <dbl>
##  1 1               50     1121      0.0427       0.957
##  2 10              12       48      0.2          0.8  
##  3 11               3       34      0.0811       0.919
##  4 2               22       99      0.182        0.818
##  5 3               33      555      0.0561       0.944
##  6 4               12       23      0.343        0.657
##  7 5               14      226      0.0583       0.942
##  8 6               20       55      0.267        0.733
##  9 7               17      215      0.0733       0.927
## 10 8               35      508      0.0645       0.936
## 11 9                8       38      0.174        0.826

Konceptualno, očekujemo da udio unutar-zajednice bude visok (jer modularnost \(≈0.72\)). Napomena: ovdje uistinu vidimo algoritam detekcije zajednica na djelu: nije važno koja je formalna podjela po sastavnicama, promatraju se suradnje na zajedničkim kolegijima.

Prelazimo na centralnost.

cent <- tibble(
  name = V(g_weak_giant)$name,
  osoba_clean = V(g_weak_giant)$osoba_clean,
  sast_nast = V(g_weak_giant)$sast_nast,
  degree      = igraph::degree(g_weak_giant, mode = "all"),
  in_degree   = igraph::degree(g_weak_giant, mode = "in"),
  out_degree  = igraph::degree(g_weak_giant, mode = "out"),
  closeness   = igraph::closeness(g_weak_giant, mode = "all", normalized = TRUE),
  betweenness = igraph::betweenness(g_weak_giant, normalized = TRUE),
  eigenvector = igraph::eigen_centrality(g_weak_giant, directed = TRUE)$vector,
  pagerank    = igraph::page_rank(g_weak_giant)$vector,
  hits_auth   = igraph::authority_score(g_weak_giant)$vector,
  hits_hub    = igraph::hub_score(g_weak_giant)$vector
)

cent |> arrange(desc(eigenvector))
## # A tibble: 344 × 11
##    name  sast_nast degree in_degree out_degree closeness betweenness eigenvector
##    <chr> <chr>      <dbl>     <dbl>      <dbl>     <dbl>       <dbl>       <dbl>
##  1 274   fet           66        33         33     0.184    0.000208       1    
##  2 181   vanjski       66        33         33     0.184    0.000216       0.919
##  3 165   fet           66        33         33     0.184    0.000216       0.911
##  4 208   fet           72        37         35     0.180    0.00390        0.800
##  5 114   vanjski       68        34         34     0.179    0.00323        0.763
##  6 011   fet           66        33         33     0.185    0.00561        0.759
##  7 170   fet           66        33         33     0.183    0.00286        0.711
##  8 159   vanjski       66        33         33     0.178    0.000581       0.686
##  9 064   fet           69        35         34     0.186    0.0119         0.651
## 10 293   vanjski       66        33         33     0.183    0.000879       0.649
## # ℹ 334 more rows
## # ℹ 3 more variables: pagerank <dbl>, hits_auth <dbl>, hits_hub <dbl>

U ovoj mreži “važnost” može značiti različite stvari, pa je smisleno gledati više mjera:

  • Degree / in-degree / out-degree: osobe koje sudjeluju u puno kolegija ili u puno timova. U ovom modelu in/out može djelomično reflektirati uloge (izvođač→nositelj uvodi usmjerenost), ali zbog simetričnih veza i agregacije treba tumačiti oprezno.

  • Betweenness: osobe koje povezuju različite nastavne skupine — “mostovi” između područja ili između sastavnica. U praksi su to često osobe koje sudjeluju na kolegijima koji spajaju programe (interdisciplinarno područje), ili imaju angažmane na više mjesta.

  • Closeness: osobe koje su “blizu svima” u smislu prosječne udaljenosti — tipično dobro integrirane u sustav suradnji.

  • Eigenvector / PageRank: osobe povezane s drugim “dobro povezanim” osobama, tj. u središtu gustih, utjecajnih nastavnih klastera. To često ne znači “najviše kolegija”, nego “najcentralnije mjesto u mreži suradnje”.

  • HITS (hub/authority): u usmjerenim mrežama može dati nijansiranije uloge (hub kao “izvor prema autoritetima”, authority kao “cilj mnogih”), ali ovdje usmjerenost djelomično dolazi iz konstrukcije (I→N), pa rezultate treba tumačiti kao strukturne uloge u modelu odgovornosti, ne kao “stvarni autoritet” izvan definicije mreže.

par(mfrow=c(3,3))

V(g_weak_giant)$degree <- cent$degree
V(g_weak_giant)$indegree <- cent$in_degree
V(g_weak_giant)$outdegree <- cent$out_degree
V(g_weak_giant)$close <- cent$closeness
V(g_weak_giant)$betwe <- cent$betweenness
V(g_weak_giant)$eigen <- cent$eigenvector
V(g_weak_giant)$pagerank <- cent$pagerank
V(g_weak_giant)$auth <- cent$hits_auth
V(g_weak_giant)$hub <- cent$hits_hub


plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$degree/5,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = degree"
)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$indegree/3,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = indegree"
)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$outdegree/3,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = outdegree"
)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$close*20,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = closeness"
)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$betwe*200,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = betweenness"
)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$eigen*20,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = eigenvector"
)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$pagerank*200,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = page rank"
)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$auth*20,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = authority"
)

plot(
  g_weak_giant,
  layout = lay_giant,
  vertex.size = V(g_weak_giant)$hub*20,
  vertex.label = NA,
  vertex.color = V(g_weak_giant)$col_sast,
  edge.color = E(g_weak_giant)$col,
  edge.arrow.size = 0.25,
  edge.width = E(g_weak_giant)$weight,
  main = "UNIPU mreža (giant weak component) \n veličina čvora = hub"
)




Ekvivalencije

Koncept ekvivalencije uvodi kvalitativno drukčiji pogled na mrežu od onoga koji nude mjere centralnosti. Dok centralnosti rangiraju aktere prema “važnosti”, ekvivalencije odgovaraju na pitanje tko je s kim zamjenjiv u strukturi odnosa. Time prelazimo s individualnih mjera na pozicije, a iz pozicija proizlaze uloge. U klasičnoj literaturi razlikuju se tri temeljna oblika ekvivalencije: strukturna, automorfna i regularna, pri čemu svaka sljedeća predstavlja općenitiji (i teorijski zahtjevniji) koncept.

Enronova mreža e-pošte je dobar kontrast UNIPU mreži jer je relacija prirodno usmjerena (pošiljatelj → primatelj) i često odražava organizacijske tokove (naredbe, izvještavanje, koordinacija). Atribut V(enron)$Note daje “formalnu” funkciju (npr. Vice President, Director, Employee), ali je poanta ove cjeline pokazati da formalna funkcija nije isto što i pozicija. Regularna ekvivalencija upravo hvata “biti isti tip aktera” u smislu povezivanja s ekvivalentnim tipovima (rekurzivna definicija uloga), dok je strukturna ekvivalencija stroža i traži (gotovo) iste susjede; Van Steen (2010) eksplicitno uvodi automorfnu ekvivalenciju kao topološku simetriju te regularnu ekvivalenciju kao ulogu definiranu kroz veze prema ekvivalentnima.



Strukturna ekvivalencija

Strukturna ekvivalencija je najstroži oblik. Dva aktera \(i\) i \(j\) strukturno su ekvivalentna ako imaju identične veze prema svim ostalim akterima u mreži. U matrici susjedstva to znači da su njihovi retci (i stupci, kod usmjerenih mreža) identični.

Formalno, u binarnoj mreži vrijedi:

\[ i \equiv_S j \iff x_{ik} = x_{jk} \ \text{i} \ x_{ki} = x_{kj} \ \forall k \]

gdje je \(x_{ik}\) element matrice susjedstva koji označava postoji li veza od \(i\) prema \(k\). Drugim riječima, za svaki treći čvor \(k\), akteri \(i\) i \(j\) moraju imati isti obrazac veza.


Ovaj kriterij je vrlo restriktivan i u empirijskim mrežama rijetko daje savršene podudarnosti. Zbog toga se u praksi koristi pojam strukturne sličnosti, gdje se identičnost zamjenjuje mjerama udaljenosti ili korelacije između redaka matrice susjedstva (npr. Euklidska udaljenost ili Pearsonova korelacija), što omogućuje grupiranje aktera u približno ekvivalentne pozicije (Wasserman & Faust, 1994; Jackson, 2008).

Strukturna ekvivalencija intuitivno odgovara situacijama u kojima su akteri potpuno zamjenjivi — primjerice, dva zaposlenika koji imaju istog nadređenog i surađuju s istim kolegama.



Enron (g_giant)

U Enron mreži strukturna ekvivalencija bila bi situacija u kojoj dva zaposlenika šalju e-mailove točno istim osobama i primaju e-mailove od točno istih osoba.

S obzirom na to da je riječ o realnoj organizaciji s 182 čvora i 3010 agregiranih veza, takva savršena podudarnost je iznimno rijetka. Čak i zaposlenici istog odjela obično imaju barem jednu komunikacijsku razliku (drugi projekt, druga adresa, druga distribucijska lista).

Ono što u praksi možemo očekivati nisu savršene podudarnosti, nego visoke korelacije redaka matrice susjedstva. To bi moglo identificirati npr.:

  • administrativne asistente koji komuniciraju s istim nadređenima,

  • članove malog projektnog tima,

  • formalno paralelne pozicije u hijerarhiji.

Dakle, u Enronu je strukturna ekvivalencija interpretativno bliska ideji potpune zamjenjivosti u komunikacijskoj ulozi, ali empirijski se pojavljuje rijetko.

Za ekvivalencije je najčišće krenuti od binarne matrice susjedstva (postoji / ne postoji veza). Težine (npr. broj mailova) se mogu koristiti kasnije, ali klasične definicije ekvivalencija su binarne.

library(igraph)
library(sna)

# Helper: binariziraj graf (zadržava smjer, uklanja multi/loop ako treba)
to_binary_simple <- function(g, remove_loops = TRUE) {
  g2 <- g
  # ako postoji weight, sve >0 tretiramo kao 1
  if ("weight" %in% edge_attr_names(g2)) {
    E(g2)$weight <- as.numeric(E(g2)$weight > 0)
  } else {
    E(g2)$weight <- 1
  }
  g2 <- igraph::simplify(
    g2,
    remove.multiple = TRUE,
    remove.loops = remove_loops,
    edge.attr.comb = list(weight = "sum")  # u binarnom slučaju ostaje 1 po paru
  )
  # nakon simplify: opet binariziraj (ako se sumalo)
  E(g2)$weight <- as.numeric(E(g2)$weight > 0)
  g2
}

gE <- to_binary_simple(g_giant)        # Enron giant

Savršena strukturna ekvivalencija je rijetka - trebamo pronaći parove s identičnim obrascem veza. U usmjerenoj mreži tražimo da su i izlazni i ulazni obrasci isti. To možemo provjeriti direktno preko matrice susjedstva.

vnames_safe <- function(g) {
  nm <- igraph::vertex_attr(g, "name")
  if (is.null(nm)) nm <- igraph::as_ids(V(g))  # moramo ubaciti pomoćnu funkciju za Enron, jer nema "imena" čvorova
  as.character(nm)
}

structural_equiv_pairs_exact <- function(g, top_n = 20) {
  A   <- as.matrix(as_adj(g, sparse = FALSE))   # out obrasci
  Ain <- t(A)                                   # in obrasci

  # “potpis” čvora: out + in
  sig <- apply(cbind(A, Ain), 1, paste0, collapse = "")

  vn <- vnames_safe(g)

  groups <- split(vn, sig)
  groups <- groups[sapply(groups, length) > 1]
  groups <- groups[order(sapply(groups, length), decreasing = TRUE)]

  head(groups, top_n)
}


se_exact_enron <- structural_equiv_pairs_exact(gE)

se_exact_enron
## $...
## [1] "53" "87"

U Enron mreži, stroga strukturna ekvivalencija znači da bi dva zaposlenika morala imati potpuno identičan obrazac slanja i primanja poruka prema svim ostalim zaposlenicima u promatranoj mreži. Budući da je riječ o usmjerenoj mreži, kriterij se odnosi istodobno na redak i stupac matrice susjedstva, tj. na OUT i IN profil. U organizacijskoj komunikaciji takva bi situacija implicirala gotovo potpunu zamjenjivost u komunikacijskoj funkciji (isti primatelji, isti pošiljatelji), što je teorijski razumljivo, ali u praksi teško ostvarivo čak i među formalno “paralelnim” radnim mjestima.

Empirijski rezultat ukazuje na to da se pojavljuju tek izolirane i malobrojne skupine čvorova s identičnim potpisom (npr. pronađeni parovi) i konzistentan je s očekivanjem za realnu, heterogenu organizacijsku mrežu. Čak i u slučajevima gdje postoje standardizirani tokovi (distribucijske liste, administrativna podrška, rutinizirana izvješća), dovoljno je da se jedan dodatni kontakt pojavi samo kod jednog člana para da bi stroga ekvivalencija nestala. Stoga nalaz treba čitati kao potvrdu da je “egzaktna” strukturna ekvivalencija u Enronu iznimka, a ne pravilo te da je analitički produktivnije prijeći na strukturnu sličnost (udaljenosti/korelacije) i klasteriranje pozicija.

Ako se takvi rijetki ekvivalentni parovi interpretiraju, najvjerojatniji mehanizmi su institucionalna standardizacija komunikacije (npr. zajedničke liste ili automatizirani obrasci) ili vrlo usko podijeljeni zadaci u kojima dvije adrese funkcioniraju kao gotovo identične “točke ulaza/izlaza” za isti skup interakcija. Međutim, bez dodatnih atributa (tim, uloga, funkcija, mailbox vs osoba) te se interpretacije moraju zadržati na razini strukturne mogućnosti, a ne činjenične atribucije.



UNIPU (g_weak_giant)

U UNIPU mreži strukturna ekvivalencija znači da dvije osobe sudjeluju na točno istim kolegijima i s točno istim suradnicima, uz istu kombinaciju uloga (N–N, I–I, I→N).

Takve situacije su realnije nego u Enronu — primjerice:

  • dva izvođača koji uvijek rade zajedno na istom skupu kolegija,

  • dva nositelja koji su supotpisnici istih kolegija.

Ipak, i ovdje je kriterij vrlo restriktivan. Čim se pojavi jedan dodatni kolegij ili drugačiji tim, identičnost nestaje.

gU <- to_binary_simple(g_weak_giant)   # UNIPU giant weak
se_exact_unipu <- structural_equiv_pairs_exact(gU)
se_exact_unipu
## $...
## [1] "105" "222"
## 
## $...
## [1] "239" "056"
## 
## $...
## [1] "144" "149"
## 
## $...
## [1] "212" "231"

U UNIPU mreži, stroga strukturna ekvivalencija znači da bi dvije osobe morale imati identičan obrazac veza prema svim ostalim osobama u mreži, i to uzimajući u obzir smjer veze (u mreži koja uključuje i suradničku i hijerarhijsku komponentu). U praksi to bi se moglo dogoditi u stabilnim nastavnim konfiguracijama gdje se dva aktera kroz promatrano razdoblje pojavljuju u potpuno istim nastavnim timovima i u istim relacijama prema ostalima. U takvom slučaju, ekvivalencija ne bi nužno bila “osobna zamjenjivost”, nego zamjenjivost u smislu strukturalnog položaja u nastavnoj raspodjeli rada (npr. u slučaju produženog bolovanja jedne osobe, druga osoba može uskočiti bez velikih promjena ili posljedica za nastavni proces, organizaciju i suradnje).

Nalaz više egzaktno ekvivalentnih parova u UNIPU mreži (u odnosu na Enron) metodološki je očekivan jer je relacija u toj mreži često vezana uz ponavljajuće institucionalne obrasce (nastavni timovi, uloge nositelja/izvođača, stabilne suradnje). Ipak, i ovdje je kriterij vrlo restriktivan: dovoljno je da se jedna osoba pojavi na dodatnom kolegiju ili u drugačijoj kombinaciji suradnika pa potpuna identičnost profila nestaje. Zbog toga se i u UNIPU slučaju stroga strukturna ekvivalencija tipično pojavljuje kao lokalni fenomen (manje skupine/parovi), a ne kao dominantan princip organizacije mreže.

Interpretativno, egzaktna strukturna ekvivalencija u UNIPU mreži najčešće bi upućivala na vrlo sličnu “nastavnu portfeljnu strukturu” dvaju aktera u promatranom razdoblju. U kontekstu pozicijske analize to je korisno kao demonstracija najstrožeg kriterija, ali analitički fokus se u pravilu prebacuje na strukturnu sličnost i regularnu ekvivalenciju, jer one bolje zahvaćaju funkcionalnu diferencijaciju sustava i stabilne uloge koje se ponavljaju kroz različite timove.

U obje mreže stroga strukturna ekvivalencija ostaje rijetka jer je “identičnost prema svima” ekstremno zahtjevan uvjet. Razlika je u tome što se u UNIPU mreži češće pojavljuju ponavljajući institucionalni obrasci koji mogu proizvesti identične profile (npr. stabilni timovi i uloge), dok Enronova komunikacija odražava veću heterogenost i nepodudarnost kontakata, pa se egzaktne podudarnosti pojavljuju tek sporadično. Zaključujemo da je u obje mreže strukturna ekvivalencija teorijski jasna, ali empirijski rijetka, te je u praksi zamjenjujemo mjerama strukturne sličnosti.



Automorfna ekvivalencija

Automorfna ekvivalencija ublažava zahtjev identičnih susjeda. Dva aktera su automorfno ekvivalentna ako postoji preslikavanje (automorfizam) grafa na samoga sebe koje jednog aktera preslikava u drugog, a da pritom struktura grafa ostaje nepromijenjena (Van Steen, 2010).

Intuitivno, akteri su automorfno ekvivalentni ako zauzimaju simetrične pozicije u strukturi, iako nisu nužno povezani s istim osobama. Primjer je lančana struktura \(A\)\(B\)\(C\)\(D\): čvorovi \(A\) i \(D\) su automorfno ekvivalentni jer zauzimaju simetrične krajnje pozicije, iako nemaju iste susjede.


Ovaj oblik ekvivalencije oslanja se na graf-teorijsku simetriju i naglašava topološku poziciju, a ne konkretne relacije. Time se uvodi važna distinkcija: strukturna ekvivalencija promatra identitet veza, dok automorfna promatra identitet mjesta u strukturi.

Pojednostavljeno, razdvaja “isti susjedi” od “isto mjesto u strukturi”, ali je u empirijskim društvenim mrežama često ograničene interpretativne snage jer je osjetljiva na granice mreže i lokalne topološke detalje.



Enron

U komunikacijskoj mreži automorfna ekvivalencija traži topološku simetriju, a ne identične kontakte.

Npr.:

  • dva zaposlenika na rubu mreže koji komuniciraju samo s jednim nadređenim,

  • dva člana različitih odjela koji zauzimaju istu “poziciju” u lokalnoj strukturi (npr. oba su posrednici između dva klastera).

Iako možda ne komuniciraju s istim osobama, njihova strukturna uloga u grafu je simetrična.

U Enronu se automorfne ekvivalencije mogu pojaviti u manjim podstrukturama (lokalne simetrije), ali u cijeloj mreži rijetko nalazimo globalne automorfizme zbog kompleksnosti i heterogenosti komunikacije.

library(igraph)

automorphism_size <- function(g) {
  gE <- as.undirected(g, mode = "collapse")
  grp <- automorphism_group(gE, details = FALSE)  
  grp
}

aut_enron <- automorphism_size(gE)

str(aut_enron)
## List of 2
##  $ : 'igraph.vs' int [1:182] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bca9744-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' int [1:182] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bca9744-1648-11f1-8000-010000000000"

aut_enron označava skup svih permutacija čvorova koje preslikavaju graf u samoga sebe, a da pritom struktura ostaje identična. Output sadrži:

  • veličinu grupe (broj automorfizama),

  • generatore grupe (ako tražite details = TRUE),

  • informacije o simetričnim strukturama.

  • Najvažnija informacija je veličina grupe.

Automorfna ekvivalencija u Enron mreži znači da se dva čvora mogu zamijeniti permutacijom čvorova koja čuva cijelu strukturu grafa. U takvoj definiciji nije važno jesu li akteri povezani s istim osobama, nego zauzimaju li simetrično mjesto u topologiji mreže. U empirijskoj komunikacijskoj mreži organizacije, globalne simetrije su tipično rijetke jer je komunikacija snažno obilježena funkcionalnim razlikama (specijalizirane uloge, različiti timovi, razlike u intenzitetu komunikacije), pa čak i “slični” akteri najčešće nisu topološki zamjenjivi na razini cijele mreže.

Rezultat dobiven funkcijom automorphism_group() u takvom se kontekstu obično interpretira kao pokazatelj koliko je mreža strukturno asimetrična. Dobivena vrlo mala automorfna struktura (tj. dvije netrivijalne permutacije ili praktično samo trivijalni automorfizam), to je očekivano: mreža je dovoljno heterogena da gotovo svaki čvor ima jedinstven “otisak” u strukturi. Da su se pojavile automorfne klase, onda bismo ih tumačili u kontekstu njihove povezanosti s lokalnim simetrijama (npr. više perifernih čvorova koji su vezani na isti način prema istom dijelu grafa, ili ponavljajuće “list” strukture). U organizacijskoj interpretaciji, takve simetrije više govore o tome da je dio mreže organiziran kroz ponavljajući obrazac (npr. rubni akteri s jednim dominantnim kontaktom), nego da su akteri u stvarnosti međusobno zamjenjivi u smislu uloge.



UNIPU

UNIPU mreža ima izraženiju modularnost (\(≈0.72\)), pa se automorfna ekvivalencija može intuitivnije uočiti.

Primjeri:

  • dva izvođača koji svaki u svojoj sastavnici rade s jednim nositeljem i nemaju druge veze,

  • dva “periferna” člana različitih zajednica koji su simetrično povezani prema centru svoje grupe.

Ovdje automorfna ekvivalencija ilustrira simetriju pozicija unutar kompetencijskih klastera, neovisno o formalnoj sastavnici.

aut_unipu <- automorphism_size(gU)
str(aut_unipu)
## List of 45
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 17 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "199" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"
##  $ : 'igraph.vs' Named int [1:344] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:344] "195" "215" "099" "278" ...
##   ..- attr(*, "env")=<weakref> 
##   ..- attr(*, "graph")= chr "7bd2b87a-1648-11f1-8000-010000000000"

U UNIPU dijelu se vidi velika lista (“List of 45”), ali to nije nužno ‘mnogo simetrije’ u sociološkom smislu; često znači da postoje orbite/permutacije (koliko “tipova simetričnih pozicija” postoji) jer graf sadrži puno čvorova s vrlo sličnom lokalnom strukturom (npr. više perifernih čvorova vezanih na sličan način), ili zato što koristimo neusmjerenu inačicu grafa (simetrije porastu kad se smjer ignorira).

U UNIPU mreži automorfna ekvivalencija također traži topološku zamjenjivost, ali je vjerojatnost pojave simetrija nešto veća jer je mreža sastavljena od institucionalnih obrazaca koji se ponavljaju. Npr., više “perifernih” aktera može biti povezano na vrlo sličan način prema vlastitom lokalnom klasteru, ili se mogu pojaviti ponavljajuće mikro-strukture (npr. više izvođača s usporedivim vezama prema nositeljima i ograničenim brojem drugih veza). Takvi slučajevi stvaraju simetrične konfiguracije koje su pogodne za automorfizme, iako akteri nisu nužno povezani s istim osobama.

Empirijski rezultat u kojem automorphism_group() vraća bogatiji skup generatora ili više klasa može se interpretirati kao indikator da u mreži postoji više topoloških “šablona” koji se ponavljaju, najčešće unutar modularnih dijelova mreže. Važno je naglasiti da automorfna ekvivalencija ovdje nije isto što i funkcionalna uloga (nositelj/izvođač), nego prije pokazuje da određeni dijelovi mreže imaju strukturnu simetriju. To je ilustrativno korisno jer lijepo razlikuje “isti susjedi” (strukturna) od “isto mjesto u obliku” (automorfna), ali je za sociološki smislenije “uloge” UNIPU sustava automorfna ekvivalencija obično preslaba (previše topološka) i preosjetljiva na granice mreže i detalje konstrukcije brida.



Regularna ekvivalencija

Regularna ekvivalencija je najopćenitiji i sociološki najznačajniji oblik. Dva aktera su regularno ekvivalentna ako imaju istu vrstu odnosa prema akterima koji su i sami ekvivalentni. Definicija je rekurzivna i ne zahtijeva identične susjede.

Formalno, vrijedi:

\[ i \equiv_R j \iff \begin{cases} \forall k: x_{ik} = 1 \Rightarrow \exists l \text{ takav da } x_{jl} = 1 \text{ i } k \equiv_R l \ \forall l: x_{jl} = 1 \Rightarrow \exists k \text{ takav da } x_{ik} = 1 \text{ i } l \equiv_R k \end{cases} \]

Ovdje \(x_{ik}\) označava postojanje veze, a relacija \(\equiv_R\) označava regularnu ekvivalenciju. Drugim riječima, akteri \(i\) i \(j\) nisu povezani s istim osobama, nego s osobama koje zauzimaju istu poziciju.


Primjer je obrazovni sustav: svi profesori su regularno ekvivalentni jer predaju studentima, iako predaju različitim grupama studenata; svi studenti su regularno ekvivalentni jer primaju znanje od profesora. Ovdje se prvi put jasno pojavljuje pojam uloge. Regularna ekvivalencija omogućuje modeliranje funkcionalne diferencijacije: nadređeni, podređeni, klijenti, dobavljači, brokeri.

Upravo je regularna ekvivalencija temelj blokmodeliranja i analize pozicija jer reducira kompleksnu mrežu na sustav odnosa među tipovima aktera, a ne među pojedincima.



Enron

U Enron mreži regularna ekvivalencija može identificirati:

  • sve menadžere koji šalju poruke podređenima i primaju ih od nadređenih,

  • sve administrativne asistente koji komuniciraju s voditeljima,

  • sve “broker” pozicije koje povezuju dva klastera.

Ovdje osobe nisu povezane s istim pojedincima, ali su povezane s akterima iste vrste. Regularna ekvivalencija tako otkriva organizacijske uloge: nadređeni, podređeni, posrednici, specijalisti.

To je već korak prema blokmodeliranju — reduciramo mrežu na odnose među tipovima pozicija.

Za regularnu ekvivalenciju koristimo redist iz sna i opet klasteriramo.

regular_equiv_classes <- function(g, k = 8) {
  A <- as.matrix(as_adj(g, sparse = FALSE))  # binarna out-adjacency
  d <- sna::redist(A)                        # regularne udaljenosti :contentReference[oaicite:7]{index=7}
  hc <- hclust(as.dist(d), method = "average")
  cl <- cutree(hc, k = k)

  split(V(g)$Name, cl)
}

re_classes_enron <- regular_equiv_classes(gE, k = 8)

sapply(re_classes_enron, length) |> sort(decreasing = TRUE)
##   1   4   3   2   5   6   7   8 
## 160   8   7   2   2   1   1   1

Regularna ekvivalencija u Enron mreži hvata ono što strukturna ne može: akteri su regularno ekvivalentni ako imaju veze prema ekvivalentnim tipovima aktera, čak i kada to nisu isti pojedinci. U organizacijskom kontekstu to je upravo ona razina na kojoj počinju “izranjati” uloge: menadžerske razine, administrativna podrška, specijalisti koji komuniciraju prema više funkcionalnih jedinica te brokeri koji povezuju dijelove organizacije.

Dobiveni rezultat klasteriranja na temelju sna::redist() u Enronu pokazuje izrazitu asimetriju veličina klasa (npr. jedna vrlo velika klasa i nekoliko manjih). Takav ishod je čest u realnim komunikacijskim mrežama kada se primjenjuje relativno mali broj klasa k: algoritam često obuhavti veliki dio aktera u jednu široku regularnu poziciju koja predstavlja dominantni tip komunikacijskog ponašanja (npr. mnogi akteri koji primarno komuniciraju unutar svojih lokalnih krugova bez vrlo specifičnog vertikalnog ili brokerskog profila), dok se manjim klasama izdvajaju akteri s izraženijim i stabilnijim obrascima (npr. čvorovi s jakim outflowom prema mnogima, čvorovi koji primaju od mnogih, ili čvorovi koji vežu različite dijelove mreže).

Interpretativno, regularna ekvivalencija u Enronu je najkorisnija kada se klase ne čitaju kao “odjeli”, nego kao funkcionalni tipovi komunikacije. Tipične uloge su npr. “snažni pošiljatelji prema više timova”, “centralne administrativne točke”, “primatelji mnogih poruka” i sl. Velika klasa tada predstavlja “uobičajenu” organizacijsku komunikaciju bez snažne diferencijacije u makro-ulozi, a male klase predstavljaju strukturno distinktne uloge (npr. koordinacijske točke, pozicije s izrazitom vertikalnom asimetrijom, ili pozicije koje su redovito u sredini putova). To je i razlog zašto se nakon toga prirodno prelazi na blokmodeliranje: cilj nije samo klasifikacija, nego razumijevanje odnosa među tim ulogama.



UNIPU

UNIPU mreža je gotovo “školski primjer” regularne ekvivalencije.

  • Svi nositelji su regularno ekvivalentni jer primaju usmjerene veze od izvođača.

  • Svi izvođači su regularno ekvivalentni jer imaju usmjeren odnos prema nositeljima.

  • “Vanjski suradnici” mogu tvoriti zasebnu regularnu poziciju jer su tipično povezani s internim nositeljima.

  • Osobe koje povezuju više sastavnica mogu tvoriti brokersku regularnu poziciju.

Ovdje se jasno pojavljuje pojam uloge: nositelj, izvođač, među-sastavnički most, centralni koordinator.

Regularna ekvivalencija zato daje najsmisleniju interpretaciju za UNIPU mrežu jer odgovara funkcionalnoj diferencijaciji sustava.

regular_equiv_classes <- function(g, k = 8) {
  A <- as.matrix(as_adj(g, sparse = FALSE))  # binarna out-adjacency
  d <- sna::redist(A)                        # regularne udaljenosti :contentReference[oaicite:7]{index=7}
  hc <- hclust(as.dist(d), method = "average")
  cl <- cutree(hc, k = k)

  split(V(g)$name, cl)
}

re_classes_unipu <- regular_equiv_classes(gU, k = 8)
sapply(re_classes_unipu, length) |> sort(decreasing = TRUE)
##   4   2   5   1   6   3   7   8 
## 119  91  55  25  25  23   3   3

U UNIPU mreži regularna ekvivalencija ima posebno jasnu semantiku jer je relacija konstruirana tako da uključuje i hijerarhijsku komponentu (npr. izvođač \(→\) nositelj). To znači da se “tipovi” aktera u mreži često mogu opisati kroz stabilne relacije prema drugim tipovima: izvođači imaju veze prema nositeljima, nositelji primaju od izvođača, a dio aktera može imati mješovite obrasce (npr. i nosi i izvodi, ili povezuje više timova/kolegija). Upravo takve situacije regularna ekvivalencija zahvaća prirodno, jer ne traži iste suradnike nego sličan odnos prema sličnim ulogama - uloge tipa “osobe koje su često nositelji i imaju mnogo izvođača” naspram “osobe koje većinom izvode (usmjereni tok prema nositeljima)” — čak i ako ne rade s istim ljudima.

Rezultat u kojem se dobiva nekoliko većih klasa i nekoliko malih (npr. dvije ili tri dominantne pozicije i par malih specijalnih pozicija) tipično znači da mreža doista sadrži nekoliko osnovnih funkcionalnih uloga koje se ponavljaju kroz sustav, uz manji broj aktera s rubnim ili kombiniranim profilima. U UNIPU interpretaciji, veće klase najčešće odgovaraju glavnim funkcionalnim tipovima (npr. pretežno izvođački profil, pretežno nositeljski profil, mješoviti profil), dok male klase često hvataju aktere koji rade na specifičan način (npr. povezuju više inače slabije povezanih dijelova, imaju izrazitu koncentraciju odnosa, ili se pojavljuju u neuobičajenim konfiguracijama kolegija).

U odnosu na Enron, regularna ekvivalencija je ovdje interpretativno “čišća” jer se strukturni tipovi lakše vežu uz značenje relacije. Zato se i makro-arhitektura (npr. blok gustoće između regularnih pozicija) često može čitati kao trag hijerarhijske logike: očekivano je da blokovi koji odgovaraju izvođač → nositelj budu izraženiji od obrnutog smjera, dok dijagonalni blokovi otkrivaju koliko su uloge unutar sebe kohezivne (npr. koliko se “nositelji” međusobno povezuju, ili koliko se “izvođači” povezuju izvan odnosa prema nositeljima).




Koncept Enron UNIPU Ideja
Strukturna Rijetka, gotovo nikad savršena Moguća u malim nastavnim timovima radimo s istim ljudima
Automorfna Lokalna simetrija u podstrukturama Simetrije unutar kompetencijskih klastera nalazimo se na istom mjestu u strukturi
Regularna Hijerarhijske i brokerske uloge Jasne funkcionalne uloge (nositelj, izvođač) radimo istu vrstu posla u sustavu




Od stroge identičnosti do funkcionalne zamjenjivosti

Tri oblika ekvivalencije mogu se promatrati kao kontinuum:

  • Strukturna → identični susjedi
  • Automorfna → simetrične pozicije
  • Regularna → ista funkcija u sustavu

Kako se krećemo tim kontinuumom, opuštamo kriterij identičnosti i prelazimo s mikro-razine (konkretne veze) na mezorazinu (pozicije) i naposljetku na makrorazinu (uloge u sustavu).

Automorfna ekvivalencija u obje mreže prije svega govori o prisutnosti topoloških simetrija i zato je u realnim, heterogenim mrežama često ograničene analitičke vrijednosti izvan demonstracije koncepta; u Enronu se tipično očekuje vrlo malo netrivijalnih simetrija, dok u UNIPU mreži mogu postojati lokalno ponavljajući obrasci koji generiraju više automorfnih klasa. Regularna ekvivalencija je, nasuprot tome, primarni “most” prema ulogama i blokmodeliranju: u Enronu ona hvata funkcionalne tipove komunikacije (često s jednom velikom “baznom” klasom i nekoliko specifičnih), dok u UNIPU mreži prirodno mapira institucionalno smislenije uloge jer je relacija već konstruirana s ugrađenom funkcionalnom logikom.

U metodološkom smislu, taj prijelaz označava i promjenu istraživačkog pitanja:

  • Strukturna ekvivalencija pita: Tko je povezan s istima?
  • Automorfna pita: Tko zauzima simetrično mjesto?
  • Regularna pita: Tko obavlja istu funkciju?

Time se otvara prostor za blokmodeliranje, analizu hijerarhije i identifikaciju brokera, gatekeepera i autoriteta, jer se uloga ne može objasniti isključivo centralnošću, nego zahtijeva razumijevanje strukturne zamjenjivosti u relacijskom kontekstu.




Pozicijska analiza i blok-modeliranje

Pozicijska analiza predstavlja metodološki prijelaz s analize pojedinačnih aktera na analizu strukturnih klasa unutar mreže. Dok mjere centralnosti rangiraju čvorove prema njihovoj važnosti, pozicijska analiza odgovara na pitanje: koje tipove aktera mreža generira? Njezin je cilj reducirati kompleksnu mrežu velikog broja čvorova i veza na manji broj pozicija, pri čemu se pozicija definira kao skup aktera koji su međusobno ekvivalentni prema određenom kriteriju (najčešće strukturne ili regularne ekvivalencije).

U formalnom smislu, pozicijska analiza polazi od matrice susjedstva \(X = [x_{ij}]\), gdje \(x_{ij}\) označava postojanje ili težinu veze od aktera \(i\) prema akteru \(j\). Ako je mreža veličine \(n\), tada je \(X\) dimenzija \(n \times n\). Cilj je pronaći particiju skupa aktera na \(K\) disjunktnih klasa (pozicija), pri čemu vrijedi:

\[ \bigcup_{k=1}^{K} P_k = V, \quad P_k \cap P_l = \varnothing \ (k \neq l), \]

gdje je \(V\) skup svih čvorova, a \(P_k\) skup aktera u poziciji \(k\). Drugim riječima, svaki akter pripada točno jednoj poziciji.




Mjerenje sličnosti i grupiranje

Prvi korak u pozicijskoj analizi jest mjerenje sličnosti (ili udaljenosti) između aktera na temelju njihovih obrazaca veza. U slučaju strukturne ekvivalencije uspoređuju se retci (i/ili stupci) matrice susjedstva. Npr., Euklidska udaljenost između aktera \(i\) i \(j\) definira se kao:

\[ d_{ij} = \sqrt{\sum_{k=1}^{n} (x_{ik} - x_{jk})^2}. \]

Ovdje \(x_{ik}\) i \(x_{jk}\) predstavljaju veze aktera \(i\) i \(j\) prema akteru \(k\). Što je \(d_{ij}\) manja, to su akteri sličniji u obrascu svojih veza.


Alternativno, može se koristiti Pearsonov koeficijent korelacije, koji mjeri linearnu povezanost između redaka matrice susjedstva. U praksi se na temelju dobivene matrice sličnosti primjenjuju algoritmi grupiranja, poput hijerarhijske klasterske analize (HCA) ili CONCOR algoritma (iterirane korelacije), kako bi se akteri svrstali u pozicije.



Blokmodeliranje: redukcija mreže

Nakon definiranja pozicija, prelazi se na blokmodeliranje. Blokmodeliranje je postupak u kojem se originalna matrica susjedstva reorganizira (permutira) tako da akteri iste pozicije stoje jedni uz druge. Time se u matrici formiraju blokovi — podmatrice koje predstavljaju odnose unutar i između pozicija.

Ako je mreža podijeljena na \(K\) pozicija, tada se matrica može prikazati kao blok-matrica dimenzija \(K \times K\), gdje svaki element predstavlja skup odnosa između dviju pozicija. Gustoća bloka između pozicija \(P_a\) i \(P_b\) računa se kao:

\[ \delta_{ab} = \frac{\sum_{i \in P_a} \sum_{j \in P_b} x_{ij}}{|P_a| \cdot |P_b|}. \]

Ovdje \(|P_a|\) i \(|P_b|\) označavaju broj aktera u odgovarajućim pozicijama, dok brojnik predstavlja ukupan broj ostvarenih veza između tih skupina. Gustoća \(\delta_{ab}\) interpretira se kao vjerojatnost postojanja veze između tipova aktera.




Matrica slike (image matrix)

Kako bi se mreža dodatno pojednostavila, gustoće se često transformiraju u binarne vrijednosti (0 ili 1) na temelju određenog praga \(\alpha\). Ako vrijedi:

\[ \delta_{ab} > \alpha, \]

blok se označava kao 1 (postoji relacija između pozicija), inače kao 0. Rezultat je matrica slike — reducirani prikaz makrostrukture mreže u kojem su čvorovi same pozicije, a veze predstavljaju tipične obrasce odnosa među njima.


Ovaj postupak omogućuje prelazak s mikro-razine (pojedinačne veze) na makro-razinu (odnosi među klasama aktera). Drugim riječima, kompleksna mreža s velikim brojem čvorova transformira se u sažeti graf s malim brojem strukturnih tipova.

Proces pretvaranja sirovih mrežnih podataka u razumljiv blokmodel odvija se kroz nekoliko koraka:

  • Permutirana matrica susjedstva: Redovi i stupci originalne matrice se preslaguju (permutiraju) tako da akteri koji pripadaju istom bloku (klasteru) stoje jedni uz druge. Time blokovi postaju vizualno uočljivi kao kvadrati unutar matrice.

  • Matrica gustoće (Density matrix): Svaki blok u permutiranoj matrici zamjenjuje se jednom vrijednošću koja predstavlja gustoću veza (udio ostvarenih u odnosu na moguće veze) unutar tog bloka.

  • Matrica slike (Image matrix): Gustoće se pretvaraju u binarne vrijednosti (0 ili 1) na temelju određenog kriterija (praga):

    • Lean fit pravilo: Blok je 0 samo ako su sve ćelije 0, inače je 1.
    • Density fit pravilo: Blok je 1 ako je njegova gustoća iznad prosjeka cijele mreže ili iznad odabranog praga (\(\alpha\)).
  • Reducirana makrostruktura (Graf slike): Blokmodel se konačno prikazuje kao pojednostavljeni graf u kojem su čvorovi sami blokovi, a veze među njima predstavljaju relacije utvrđene matricom slike.



Tipovi blokova i interpretacija

Ovisno o obrascu unutar blokova, razlikuju se različite makro-strukture:

  • Null blok — potpuni izostanak veza između dviju pozicija.
  • Complete blok — sve moguće veze su ostvarene.
  • Regularni blok — svaki akter jedne pozicije povezan je s barem jednim akterom druge pozicije.
  • Jezgra–periferija — gusta unutarnja povezanost jezgre i slabija povezanost periferije.
  • Hijerarhijska struktura — asimetrični blokovi koji sugeriraju vertikalnu diferencijaciju.

Blokmodeliranje se može provoditi deduktivno (testiranje unaprijed definirane teorijske strukture) ili induktivno (otkrivanje strukture iz podataka). U oba slučaja, rezultat je formalna reprezentacija makro-arhitekture sustava.



Epistemološke napomene

Važno je naglasiti da blokmodeliranje uključuje niz odluka istraživača: izbor kriterija ekvivalencije, broj pozicija \(K\), prag \(\alpha\) i tip blokova. Te odluke izravno utječu na interpretaciju rezultata. Model je stoga uvijek pojednostavljenje stvarnosti, a ne njezina potpuna reprodukcija.

Unatoč tome, pozicijska analiza i blokmodeliranje omogućuju ono što pojedinačne mjere ne mogu: otkrivanje stabilnih uloga, strukturnih nejednakosti i funkcionalne diferencijacije u kompleksnim mrežama. Time se mreža prestaje promatrati kao skup izoliranih čvorova i postaje sustav odnosa među tipovima aktera, što predstavlja temelj za razumijevanje hijerarhije, moći i institucionalne organizacije.



Primjena

Ovdje su nam pomoćne funkcije koje ćemo koristiti za raščlambu. Ove funkcije nam omogućuju da od grafa dođemo do pozicija (klastera po strukturnoj sličnosti) i zatim do blokmodela (gustoće među pozicijama) i na kraju do grafa slike (makrostrukture).

#Pomoćne funkcije
library(igraph)

# 0/1 matrica susjedstva
adj_mat <- function(g, weights = FALSE) {
  if (weights && "weight" %in% edge_attr_names(g)) {
    as.matrix(as_adjacency_matrix(g, attr = "weight", sparse = FALSE))
  } else {
    as.matrix(as_adjacency_matrix(g, sparse = FALSE))
  }
}

Ova pomoćna funkcija pretvara graf g u matricu susjedstva (adjacency matrix):

  • ako je weights = FALSE, vraća 0/1 matricu:

  • A[i, j] = 1 ako postoji brid i → j, inače 0.

  • ako je weights = TRUE i graf ima atribut brida weight, vraća težinsku matricu:

  • A[i, j] = weight(i→j) (npr. broj mailova ili broj zajedničkih kolegija po smjeru).

Vraća običnu (gustu) R matricu tipa matrix, dimenzije \(n × n\).

Skoro sve u blokmodeliranju kreće od matrice susjedstva:

  • strukturna sličnost se računa usporedbom redaka/stupaca te matrice

  • blok gustoće se računa kao udio (ili prosjek težina) unutar podmatrica \(A[ia, ib]\)

Drugim riječima: graf \(\rightarrow\) matrica \(\rightarrow\) udaljenosti \(\rightarrow\) pozicije \(\rightarrow\) blokovi \(\rightarrow\) slika.

# Strukturna sličnost: udaljenost po OUT + IN obrascu (spajamo redak i stupac)
# -> ovo je standardna praktična aproksimacija strukturne ekvivalencije

dist_structural <- function(g, weights = FALSE, method = "euclidean", scale = TRUE) {
  A <- adj_mat(g, weights = weights)
  X <- cbind(A, t(A))  # OUT + IN obrazac
  if (scale) X <- scale(X)
  dist(X, method = method)
}

Računa udaljenost između čvorova na temelju njihovog obrasca veza.

  • Uzme matricu A (0/1 ili težinsku)

  • Napravi matricu obilježja: X <- cbind(A, t(A))

    • A predstavlja OUT obrazac (kome čvor šalje / na koga “ide”)

    • t(A) predstavlja IN obrazac (tko čvor prima / tko “dolazi” u čvor)

Dakle, za svaki čvor dobijemo jedan dugi vektor: [OUT veze | IN veze]

  • Standardizira stupce (scale(X)), da spriječi da dugačke kolone dominiraju (npr. ako neke osobe imaju ekstremno puno veza).

  • Izračuna dist(X, method) - euklidska udaljenost.

Vraća objekt klase dist (standardni format udaljenosti u R-u).

Ovo je praktična operacionalizacija ideje:

  • strukturna ekvivalencija = identični OUT i IN obrasci

  • u praksi su rijetko identični, zato radimo strukturnu sličnost (tko je “najbliži” po obrascu veza), a za to nam treba matrica udaljenosti - ona je ulaz za klasteriranje (pozicije).

# Klasteriranje -> pozicije
positions_hclust <- function(g, K, weights = FALSE, method = "ward.D2") {
  d <- dist_structural(g, weights = weights)
  hc <- hclust(d, method = method)
  cl <- cutree(hc, k = K)
  list(hc = hc, pos = cl)
}

positions_hclust(g, K, weights = FALSE, method = "ward.D2")

  • radi hijerarhijsko klasteriranje čvorova (HCA) na temelju dist_structural().

Koraci:

  • izračuna d (udaljenosti)

  • napravi dendrogram: hc <- hclust(d, method = method)

  • “reže” dendrogram na K grupa: cl <- cutree(hc, k = K) (gdje mi zadajemo k)

Vraća listu:

  • hc = cijeli dendrogram (koristan za vizualizaciju)

  • pos = vektor duljine n, gdje pos[i] govori kojoj poziciji pripada čvor i

To je korak pretvaranja sličnosti u pozicije. U pozicijskoj analizi to je ključ: ne zanima nas samo tko je centralan, nego koji su tipovi aktera (klase sličnih obrazaca veza).

# Matrica gustoća između pozicija (binarno ili težinski)
block_density <- function(g, pos, weights = FALSE) {
  A <- adj_mat(g, weights = weights)
  labs <- sort(unique(pos))
  B <- matrix(0, nrow = length(labs), ncol = length(labs),
              dimnames = list(paste0("P", labs), paste0("P", labs)))

  for (a in labs) for (b in labs) {
    ia <- which(pos == a)
    ib <- which(pos == b)

    # moguće veze (bez self-loopova ako a==b)
    denom <- length(ia) * length(ib)
    if (a == b) denom <- length(ia) * (length(ia) - 1)

    if (denom <= 0) {
      B[paste0("P", a), paste0("P", b)] <- NA
    } else {
      B[paste0("P", a), paste0("P", b)] <- sum(A[ia, ib]) / denom
    }
  }
  B
}

block_density(g, pos, weights = FALSE)

  • računa matricu gustoća između pozicija (blok-matricu).

  • pos je vektor pozicija (npr. 1..K)

  • labs su sve pozicije koje postoje

  • B[a,b] računa prosječnu “gustoću” veza iz pozicije a prema poziciji b

    • ia <- which(pos == a) (indeksi čvorova u poziciji a)

    • ib <- which(pos == b) (indeksi čvorova u poziciji b)

    • uzme podmatricu A[ia, ib] i zbroji sve veze

podijeli s brojem mogućih veza denom. Što je brojnik ovdje:

  • u binarnoj mreži: brojnik = broj bridova između pozicija

  • u težinskoj mreži: brojnik = zbroj težina između pozicija.

  • Posebno: kad je a == b, izbacuje self-loop mogućnosti: |ia| * (|ia|-1) umjesto |ia|*|ia|

Vraća numeričku matricu B dimenzije K × K, s imenima redaka/stupaca “P1”, “P2”, itd. To je srce blokmodeliranja: umjesto da gledamo tisuće čvorova, gledamo:

  • kakav je odnos pozicija prema pozicijama

  • jesu li blokovi “kohezivni” (visoka dijagonala)

  • postoje li asimetrični tokovi (npr. P3 → P1 visoko, ali P1 → P3 nisko)

Napomena: ako je weights=TRUE, sum(A[ia,ib]) se ponaša kao “ukupna težina” među pozicijama, pa B postaje prosječna težina po mogućoj vezi.

# Matrica slike (0/1) prema pragu:
# - "mean": prag = prosjek nenan elemenata matrice gustoća
# - ili ručno alpha

image_matrix <- function(B, alpha = c("mean", "density"), global_density = NULL) {
  if (is.character(alpha)) {
    if (alpha[1] == "mean") {
      thr <- mean(B, na.rm = TRUE)
    } else if (alpha[1] == "density") {
      thr <- global_density
    } else stop("Nepoznat alpha.")
  } else {
    thr <- alpha
  }
  I <- ifelse(is.na(B), NA, ifelse(B > thr, 1, 0))
  list(I = I, threshold = thr)
}

image_matrix(B, alpha = c("mean","density"), global_density = NULL)

  • pretvara matricu blok gustoća B u matricu slike I (0/1):

  • odredi prag thr:

    • “mean”: prag je prosjek vrijednosti u B (ignorira NA)

    • “density”: prag se zada izvana preko global_density ili alpha može biti broj (npr. 0.05)

    • onda: I[a,b] = 1 ako je B[a,b] > thr, inače 0 (NA ostaje NA)

Vraća listu:

  • I = matrica 0/1 (image matrix)

  • threshold = prag koji je korišten

Blok gustoće B je već redukcija, ali je i dalje “kontinuirana” i teža za brzo čitanje. Matrica slike daje najgrublji makro-prikaz:

  • postoji li “značajan” odnos među pozicijama (1)

  • ili nema (0)

To je ono što kasnije crtamo kao graf (pozicije kao čvorovi).

# Graf slike (pozicije kao čvorovi)
image_graph <- function(I) {
  I2 <- I
  I2[is.na(I2)] <- 0
  graph_from_adjacency_matrix(I2, mode = "directed", diag = FALSE)
}

Pretvara matricu slike \(I\) u graf gdje su čvorovi pozicije.

  • zamijeni NA s 0 (da bi matrica bila valjana)

  • graph_from_adjacency_matrix(I2, mode="directed", diag=FALSE)

Vraća igraph objekt (graf pozicija). Ovo je finalni “graf slike”: najjednostavniji prikaz makrostrukture.

Umjesto originalne mreže dobijemo graf od recimo 6–10 pozicija, koji se može interpretirati kao:

  • “tko tipično komunicira s kim”

  • “postoji li hijerarhija / tok”

  • “jezgra-periferija” (ako jedna pozicija ima veze prema mnogima)



ENRON (g_giant)

strukturna sličnost \(→\) pozicije \(→\) blokmodel

Odabir broja pozicija K - za vizualni prikaz je praktično uzeti K = 6 do 10 (da graf slike ostane čitljiv). Primjer s K = 6:

gE <- g_giant

K_E <- 6
resE <- positions_hclust(gE, K = K_E, weights = FALSE)  # binarno
posE <- resE$pos

table(posE)
## posE
##  1  2  3  4  5  6 
## 86 35 24 16 16  5
V(gE)$pos <- posE

Ovdje grupiramo čvorove prema tome koliko su im slični obrasci slanja i primanja poruka (OUT i IN). Dobivene “pozicije” nisu “odjeli”, nego strukturne klase: npr. čvorovi koji komuniciraju sličnim skupovima drugih čvorova (ili “na sličan način”).

Permutirana matrica i blok gustoće

B_E <- block_density(gE, posE, weights = FALSE)
round(B_E, 3)
##       P1    P2    P3    P4    P5    P6
## P1 0.048 0.052 0.029 0.009 0.029 0.098
## P2 0.072 0.322 0.048 0.029 0.059 0.194
## P3 0.042 0.064 0.513 0.125 0.146 0.667
## P4 0.023 0.027 0.102 0.800 0.031 0.088
## P5 0.039 0.089 0.167 0.023 0.608 0.088
## P6 0.367 0.606 0.708 0.175 0.188 0.950

B_E[a,b] je gustoća veza iz bloka pozicija Pa prema Pb. Visoke vrijednosti na dijagonali (\(Pa→Pa\)) sugeriraju “kohezivne” pozicije; visoke vrijednosti izvan dijagonale sugeriraju usmjerene tokove između tipova aktera (npr. “broadcast” pozicija → “receiving” pozicija).

Napomena:

  • permutirana matrica = vizualni trik (redoslijed čvorova)

  • matrica gustoće = stvarna redukcija (\(K×K\))

ordE <- order(posE)
AE <- adj_mat(gE, weights = FALSE)
image(AE[ordE, ordE], main = "ENRON: permutirana matrica susjedstva (po pozicijama)")

Matrica slike i graf slike

Prag možemo uzeti kao prosjek blok gustoća (mean fit) ili alternativno, medijan:

imgE <- image_matrix(B_E, alpha = "mean")
imgE$threshold
## [1] 0.211766
I_E <- imgE$I

gE_img <- image_graph(I_E)
gE_img
## IGRAPH 7f6abdb DN-- 6 4 -- 
## + attr: name (v/c)
## + edges from 7f6abdb (vertex names):
## [1] P3->P6 P6->P1 P6->P2 P6->P3
plot(gE_img, vertex.label = V(gE_img)$name,
     main = "ENRON: graf slike (pozicije kao čvorovi)")

Ovo je sažetak makrostrukture: čvorovi su pozicije, a brid znači “iznadprosječna gustoća veza” između pozicija. Ako vidimo npr. da \(P2 \rightarrow P5\) postoji, a obratno ne, to je indikacija asimetrije u komunikacijskom toku između dviju strukturnih klasa.

Ovo je odličan trenutak pokažemo regularnu ekvivalenciju bez REGE/CONCOR implementacija: pozicije ne nastaju iz sličnosti redaka, nego iz uloge. Ovdje pristupamo deduktivnom blokmodeliranju (regularna ideja), gdje tretiramo “uloge” kao pozicije. Enron Note sadrži pozicije tipa Vice President, Director, Manager i sl., pa možemo napraviti role-blokmodel:

gE <- g_giant

note <- V(gE)$Note
note <- ifelse(is.na(note) | note == "NA", "Unknown", note)

is_mgmt <- grepl("Vice President|Director|Manager|CEO|President|Managing Director", note, ignore.case = TRUE)
roleE <- ifelse(is_mgmt, "Management", "Non-management")
table(roleE)
## roleE
##     Management Non-management 
##             76            106
V(gE)$role_pos <- factor(roleE, levels = c("Management","Non-management"))
pos_roleE <- as.integer(V(gE)$role_pos)

B_roleE <- block_density(gE, pos_roleE, weights = FALSE)
round(B_roleE, 3)
##       P1    P2
## P1 0.162 0.070
## P2 0.087 0.074
img_roleE <- image_matrix(B_roleE, alpha = "mean")
g_roleE_img <- image_graph(img_roleE$I)
plot(g_roleE_img, vertex.label = levels(V(gE)$role_pos),
     main = "ENRON: graf slike (pozicije = Management/Non-management)")

Ovo je “uloga” blokmodel: promatramo jesu li komunikacijski tokovi različiti između menadžmenta i ostalih.

  • Management → Non-management blok izraženiji od obrnutog, to nalikuje broadcast/koordinaciji.

  • obratno, to može nalikovati reporting/eskalaciji.

  • oba jaka, mreža je više “kolaborativna” nego strogo hijerarhijska.



UNIPU (g_weak_giant)

strukturna sličnost → pozicije → blokmodel

UNIPU mreža ima drugačiju semantiku brida (suradnja + hijerarhija), pa je zanimljivo vidjeti hoće li pozicije “izvući” tu logiku.

gU <- g_weak_giant

K_U <- 8
resU <- positions_hclust(gU, K = K_U, weights = FALSE)
posU <- resU$pos

table(posU)
## posU
##   1   2   3   4   5   6   7   8 
##  33 242  15  24  18   4   1   7
V(gU)$pos <- posU

Blok gustoće i matrica slike

B_U <- block_density(gU, posU, weights = FALSE)
round(B_U, 3)
##       P1    P2    P3    P4    P5    P6   P7    P8
## P1 0.964 0.008 0.006 0.004 0.005 0.000 0.03 0.000
## P2 0.011 0.011 0.003 0.011 0.012 0.043 0.05 0.004
## P3 0.006 0.002 0.800 0.000 0.000 0.000 1.00 0.000
## P4 0.004 0.011 0.000 0.683 0.000 0.010 0.00 0.000
## P5 0.005 0.009 0.000 0.000 1.000 0.000 0.00 0.286
## P6 0.000 0.043 0.000 0.010 0.000 1.000 0.00 0.000
## P7 0.030 0.033 0.267 0.000 0.000 0.000   NA 0.000
## P8 0.000 0.003 0.000 0.000 0.143 0.000 0.00 1.000
ordU <- order(posU)
AU <- adj_mat(gU, weights = FALSE)
image(AU[ordU, ordU], main = "Unipu: permutirana matrica susjedstva (po pozicijama)")

  • masa na dijagonali (najviše): takve pozicije su “suradnički klasteri” (ljudi koji često rade zajedno na kolegijima).

  • izraženi jednosmjerni blokovi: to može reflektirati dio konstrukcije brida Izvođač \(→\) Nositelj, tj. hijerarhijsku komponentu.

  • “lokalni” blokovi, to se često poklapa s grupiranjem po stručnosti/kompetenciji (a ne nužno po sastavnicama).

imgU <- image_matrix(B_U, alpha = "mean")
imgU$threshold
## [1] 0.1191644
I_U <- imgU$I

gU_img <- image_graph(I_U)
plot(gU_img, vertex.label = V(gU_img)$name,
     main = "UNIPU: graf slike (pozicije kao čvorovi)")

Sad pristupamo deduktivnom blokmodeliranju - deduktivno blokmodeliranje po operacionaliziranim ulogama (IN/OUT tip), gdje tretiramo “uloge” kao pozicije.

Ako nemamo direktan atribut “uloga osobe”, možemo napraviti jednostavnu, transparentnu operacionalizaciju:

  • više OUT nego IN (češće “izvođač \(→\) nositelj”)

  • više IN nego OUT (češće “prima” veze, tj. nositelj na više kolegija)

deg_in  <- igraph::degree(gU, mode = "in")
deg_out <- igraph::degree(gU, mode = "out")

roleU <- ifelse(deg_out > deg_in, "više_out",
         ifelse(deg_in > deg_out, "više_in", "balans"))
table(roleU)
## roleU
##   balans  više_in više_out 
##      126       72      146
V(gU)$role_pos <- factor(roleU, levels = c("više_in","balans","više_out"))
pos_roleU <- as.integer(V(gU)$role_pos)

B_roleU <- block_density(gU, pos_roleU, weights = FALSE)
round(B_roleU, 3)
##       P1    P2    P3
## P1 0.056 0.038 0.022
## P2 0.039 0.029 0.014
## P3 0.042 0.014 0.025
img_roleU <- image_matrix(B_roleU, alpha = "mean")
g_roleU_img <- image_graph(img_roleU$I)
plot(g_roleU_img, vertex.label = levels(V(gU)$role_pos),
     main = "UNIPU: graf slike (pozicije = uloga po IN/OUT)")

Ovo nije “savršena” regularna ekvivalencija, ali je intuitivno jasna: dobivamo pozicije koje su definirane ponašanjem u usmjerenoj mreži (tko češće “ide prema” drugima). Ako graf slike pokaže npr. snažan blok više_out \(→\) više_in, to podržava interpretaciju hijerarhijskog toka (izvođači prema nositeljima).



Praktične koristi blokmodeliranja

  • Redukcija podataka: Omogućuje istraživačima da objasne velik dio varijacije složenog sustava pomoću samo nekoliko ključnih pozicija, što olakšava razumijevanje globalne arhitekture.
  • Identifikacija uloga: Otkriva uloge koje akteri obnašaju unutar sustava (npr. tko su lideri, tko je periferija, a tko djeluje kao most), čak i kada sami akteri nisu svjesni tih obrazaca.
  • Usporedba mreža: Blokovi omogućuju izravnu usporedbu različitih institucija (npr. dvije škole) ili praćenje promjena iste mreže kroz vrijeme (npr. evolucija političke polarizacije).
  • Predviđanje veza: Na temelju “image matrice” (matrice slike) može se predvidjeti vjerojatnost postojanja veze između bilo koja dva aktera u mreži na temelju blokova kojima pripadaju.



Empirijski primjeri iz prakse i njihova korisnost

  1. Politička polarizacija u SAD-u: Korištenjem CONCOR algoritma na podacima o glasovanju senatora, blokmodeliranje je otkrilo rastuću fragmentaciju sustava. Korist se očitovala u vizualnom dokazu kako se senatori grupiraju u dva sve izoliranija kohezivna bloka koji se podudaraju s političkim strankama.
  2. Međunarodna trgovina (World Trade Network): Blokmodeliranje se koristi za testiranje teorije svjetskih sustava, identificirajući jezgru (bogate, povezane zemlje) i periferiju (zemlje ovisne o jezgri). To je bilo korisno za precizno mapiranje globalnih ekonomskih poravnanja i predviđanje ekonomskog rasta nacija.
  3. Školske mreže prijateljstva: Usporedbom dviju srednjih škola (Jefferson i Sunshine High), istraživači su identificirali različite role-strukture (npr. “popularna jezgra”, “insajderi s periferije”, “poručnici”). Ovo je pomoglo u razumijevanju kako etnička pripadnost i dob oblikuju hijerarhiju i socijalnu klimu unutar obrazovnih ustanova.
  4. Američki Vrhovni sud: Primjena potpisanih (signed) blokmodela na odluke sudaca otkrila je ne samo konzervativne i liberalne blokove, već i specifične posredničke uloge (npr. sudac Blackmun) koji su služili kao mostovi između suprotstavljenih frakcija.
  5. Biološke mreže (Babuni): Analiza mreže timarenja babuna pokazala je da struktura nije nasumična, već se centrira oko ženki (jezgra), dok su mužjaci na periferiji. Ovo je potvrdilo hipotezu o stabilnoj hijerarhiji unutar životinjskih skupina utemeljenu na spolu.
  6. Antropološki sustavi razmjene (Kula Ring): Blokmodeli su korišteni za identifikaciju pozicija u plemenskim sustavima razmjene, pokazujući kako lokalne kulturne norme proizvode stabilne makrostrukture kojih pojedinci u sustavu često nisu svjesni.


Blokovi su korisni jer su omogućili prijelaz s metaforičkog opisa društva na preciznu provjeru pretpostavki o moći, statusu i društvenoj integraciji. Bez alata poput blokmodeliranja, identifikacija ovih “dubokih struktura” u masovnim skupovima podataka bila bi intuitivno nemoguća.




Jezgra–periferija i makro-arhitektura (pozicijska perspektiva)

U prethodnoj lekciji model jezgre–periferije analiziran je kao globalno svojstvo mreže: gusto povezana jezgra okružena rjeđe povezanom periferijom. U ovom poglavlju nadovezujemo se na taj model, ali ga promatramo iz pozicijske perspektive. Jezgra–periferija više nije samo opis gustoće, nego postaje specifičan blokmodel, odnosno rezultat grupiranja aktera u dvije (ili više) strukturne pozicije.

U idealnom binarnom modelu jezgra–periferija matrica slike ima oblik:

\[ \begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix} \]

gdje prvi redak/stupac predstavlja jezgru, a drugi periferiju. Element 1 označava prisutnost tipične veze između pozicija, dok 0 označava njezin izostanak. Takva struktura implicira:

  • visoku gustoću unutar jezgre (\(\delta_{CC}\) visoka),
  • umjerenu ili visoku gustoću između jezgre i periferije (\(\delta_{CP}\), \(\delta_{PC}\)),
  • nisku gustoću unutar periferije (\(\delta_{PP}\) bliska nuli).


Ovdje \(\delta_{ab}\) označava gustoću bloka između pozicija \(a\) i \(b\), definiranu kao udio ostvarenih u odnosu na moguće veze između tih skupina. Time jezgra–periferija postaje pozicijski model, a ne samo vizualni dojam mreže.



Jezgra kao pozicija, a ne skup najcentralnijih čvorova

Važno je razlikovati dva pristupa:

  • Rangiranje prema centralnosti (npr. najviši stupanj, najviši eigenvector).
  • Identifikaciju jezgre putem blokmodeliranja.

U prvom slučaju jezgra je implicitno definirana kao skup najcentralnijih aktera. U drugom slučaju jezgra je definirana obrascem veza, a ne pojedinačnom važnošću. Moguće je da akter nema najvišu centralnost, ali pripada jezgri jer je dio gusto povezanog bloka.

Time se pokazuje ključna razlika između centralnosti i pozicije: jezgra nije nužno skup “najvažnijih”, nego skup aktera koji dijele istu strukturnu ulogu u makro-arhitekturi.



Makro-arhitektura kao sustav pozicija

Jezgra–periferija predstavlja jedan od najjednostavnijih oblika makro-arhitekture. Općenito, makro-arhitektura označava obrazac odnosa među pozicijama, a ne među pojedincima. U tom smislu, svaka mreža može se reducirati na manji broj strukturnih tipova:

  • Jedinstvena jezgra s perifernim satelitima,
  • Višestruke jezgre (segmentirana struktura),
  • Hijerarhijski slojevi,
  • Polarizirani blokovi.

Blokmodeliranje omogućuje formalno testiranje takvih obrazaca. Ako je mreža podijeljena na \(K\) pozicija, tada makro-arhitekturu predstavlja matrica slike dimenzija \(K \times K\), koja sažima cjelokupnu strukturu sustava.



Jezgra–periferija i hijerarhija

Model jezgre–periferije često implicira latentnu hijerarhiju, ali te dvije strukture nisu identične. Jezgra može biti horizontalno organizirana (visoka međusobna povezanost bez jasne vertikalne dominacije), dok hijerarhija zahtijeva asimetriju i acikličnost odnosa. U usmjerenim mrežama, gustoća veza iz periferije prema jezgri može upućivati na prestiž ili autoritet jezgre, dok su veze iz jezgre prema periferiji indikator kontrole ili distribucije resursa.

Stoga jezgra–periferija može biti interpretirana kao:

  • horizontalna diferencijacija (centar nasuprot rubu),
  • ili vertikalna diferencijacija (dominantni nasuprot podređenima),

ovisno o smjeru i prirodi veza.



Dinamička perspektiva

U kontekstu rasta mreže, jezgra često nastaje nakon prelaska kritične gustoće (prijelaz faze). Pojava gigantske komponente omogućuje konsolidaciju najpovezanijih aktera u stabilnu jezgru. Time jezgra postaje rezultat emergentne makro-organizacije, a ne unaprijed zadane strukture. Ovime ćemo se detaljnije pozabaviti kasnije u tekstu.



Metodološka napomena

Identifikacija jezgre ovisi o:

  • kriteriju particioniranja,
  • broju pozicija \(K\),
  • pragu gustoće,
  • usmjerenosti i ponderiranosti mreže.

Različiti kriteriji mogu proizvesti različite interpretacije jezgre. Stoga jezgra–periferija nije ontološka činjenica, nego model strukturalne redukcije.


U kontekstu ove lekcije, model jezgre–periferije služi kao prijelaz prema potpunoj pozicijskoj analizi. On pokazuje kako se globalno svojstvo mreže može reinterpretirati kao sustav pozicija i blokova. Time se makro-arhitektura mreže prestaje promatrati kao agregat pojedinačnih centralnosti i postaje strukturirani odnos među tipovima aktera, što je temelj za razumijevanje uloga, hijerarhije i funkcionalne diferencijacije u složenim sustavima.



Primjena

Ovdje možemo napraviti model jezgra–periferija kao 2-pozicijski blokmodel za Enron (g_giant) i UNIPU (g_weak_giant).

Ideja: uzmemo jednu transparentnu proceduru particioniranja (npr. k-core kao aproksimaciju jezgre), dobijemo dvije skupine (Core i Periphery), pa izračunamo blok-gustoće:

  • \(\delta_{CC}\) (jezgra → jezgra)
  • \(\delta_{CP}\) (jezgra → periferija)
  • \(\delta_{PC}\) (periferija → jezgra)
  • \(\delta_{PP}\) (periferija → periferija)

i usporedimo ih s idealom \(\begin{pmatrix}1&1\\1&0\end{pmatrix}\).

Pomoćne funkcije - “jedan blok” koda koji radi za obje mreže.

library(igraph)

# 1) Jezgra/periferija preko k-core (na undirected projekciji)
#    - core_method = "kmax": jezgra = čvorovi s coreness == max(coreness)
#    - core_method = "k_ge": jezgra = čvorovi s coreness >= k (ručno)
#    - core_method = "top_prop": jezgra = top x% po coreness (npr. 10%)
core_partition_kcore <- function(g, core_method = c("top_prop","kmax","k_ge"),
                                 top_prop = 0.10, k = NULL) {
  core_method <- match.arg(core_method)

  # k-core je definiran za neusmjereni graf -> koristimo collapse projekciju
  gU <- as.undirected(g, mode = "collapse")
  kc <- coreness(gU)

  if (core_method == "kmax") {
    core_idx <- which(kc == max(kc, na.rm = TRUE))
  } else if (core_method == "k_ge") {
    stopifnot(!is.null(k))
    core_idx <- which(kc >= k)
  } else { # top_prop
    thr <- as.numeric(quantile(kc, probs = 1 - top_prop, na.rm = TRUE))
    core_idx <- which(kc >= thr)
  }

  core_names <- V(g)$name[core_idx]
  per_names  <- setdiff(V(g)$name, core_names)

  list(
    kcore = kc,
    core = core_names,
    periphery = per_names
  )
}

# 2) Blok-gustoće za Core/Periphery (usmjereno ili neusmjereno)
#    gustoća = broj bridova između skupova / broj mogućih bridova
block_densities_cp <- function(g, core_names) {
  is_dir <- igraph::is.directed(g)

  C <- V(g)[name %in% core_names]
  P <- V(g)[!name %in% core_names]

  nC <- length(C); nP <- length(P)

  # edge selectors (igraph)
  eCC <- E(g)[.from(C) & .to(C)]
  eCP <- E(g)[.from(C) & .to(P)]
  ePC <- E(g)[.from(P) & .to(C)]
  ePP <- E(g)[.from(P) & .to(P)]

  mCC <- length(eCC); mCP <- length(eCP); mPC <- length(ePC); mPP <- length(ePP)

  # denom: broj mogućih bridova (bez self-loopova)
  if (is_dir) {
    dCC <- nC * (nC - 1)
    dPP <- nP * (nP - 1)
    dCP <- nC * nP
    dPC <- nP * nC
  } else {
    # u neusmjerenom: parovi bez redoslijeda
    dCC <- nC * (nC - 1) / 2
    dPP <- nP * (nP - 1) / 2
    dCP <- nC * nP
    dPC <- nP * nC  # isto kao dCP, ali držimo matricu 2x2 radi čitljivosti
  }

  dens <- matrix(NA_real_, 2, 2, dimnames = list(c("Core","Periphery"),
                                                 c("Core","Periphery")))
  dens["Core","Core"] <- ifelse(dCC > 0, mCC / dCC, NA)
  dens["Core","Periphery"] <- ifelse(dCP > 0, mCP / dCP, NA)
  dens["Periphery","Core"] <- ifelse(dPC > 0, mPC / dPC, NA)
  dens["Periphery","Periphery"] <- ifelse(dPP > 0, mPP / dPP, NA)

  list(
    sizes = c(core = nC, periphery = nP),
    edges = c(CC = mCC, CP = mCP, PC = mPC, PP = mPP),
    density = dens
  )
}

# 3) Matrica slike (ideal jezgra-periferija) prema pragu (mean ili ručno)
image_matrix_2 <- function(B, alpha = c("mean","value"), value = NULL) {
  alpha <- match.arg(alpha)
  thr <- if (alpha == "mean") mean(B, na.rm = TRUE) else value
  I <- ifelse(is.na(B), NA, ifelse(B > thr, 1, 0))
  list(I = I, threshold = thr)
}

# 4) Brzi plot: oboji jezgru i periferiju
plot_core_periphery <- function(g, core_names, main = "Core–Periphery") {
  V(g)$cp <- ifelse(V(g)$name %in% core_names, "Core", "Periphery")
  cols <- c(Core = "black", Periphery = "grey80")
  plot(g,
       vertex.color = cols[V(g)$cp],
       vertex.size = 4,
       vertex.label = NA,
       edge.arrow.size = 0.2,
       main = main)
}

Zašto je ovo “pozicijska” analiza? Jer jezgru definiramo kao poziciju (Core), a ne kao “top 10 po centralnosti” (ili sl.), i onda gledamo blok-gustoće između pozicija.

K-core je definiran za neusmjerene grafove (klasično), pa se ovdje koristi projekcija koja ignorira smjer kako bi se dobila robusnija “kohezivna” jezgra.



ENRON (g_giant): jezgra–periferija kao 2-blok model

Particija: jezgra = top 10% po k-core indeksu

gE <- g_giant
V(gE)$name <- V(gE)$Name

cpE <- core_partition_kcore(gE, core_method = "top_prop", top_prop = 0.10)
length(cpE$core); length(cpE$periphery)
## [1] 94
## [1] 53
# Blok-gustoće (na usmjerenoj mreži, jer je Enron usmjeren)
bdE <- block_densities_cp(gE, core_names = cpE$core)
bdE$sizes
##      core periphery 
##       118        64
round(bdE$density, 4)
##             Core Periphery
## Core      0.1502    0.0581
## Periphery 0.0376    0.0531

Kako čitamo bdE$density?

  • Ako je \(\delta_{CC}\) (Core→Core) najveća, jezgra je “kohezivna” (vidimo da je tako)
  • Ako su \(\delta_{CP}\) i/ili \(\delta_{PC}\) umjerene/visoke, jezgra i periferija su povezane (povezanost postoji)
  • Ako je \(\delta_{PP}\) niska, periferija je “rijetka” (periferija ovdje nije baš rijetka, odgovara povezanosti jezgre-periferije)

Matrica slike (2×2) i usporedba s idealom

imgE <- image_matrix_2(bdE$density, alpha = "mean")
imgE$threshold
## [1] 0.07474093
imgE$I
##           Core Periphery
## Core         1         0
## Periphery    0         0

U idealnom jezgra–periferija modelu očekujemo:

  • Core→Core = 1
  • Core→Periphery = 1
  • Periphery→Core = 1 (ili barem nije 0)
  • Periphery→Periphery = 0

Ovdje imamo poklapanje samo u C-C = 1, ostalo su nule. Prag “mean” može biti pregrub, a core-periphery u praksi često nije čisti obrazac (pogotovo u komunikacijskim mrežama gdje periferija može imati međusobne veze). Može se činiti kao da model ne valja, iako je zapravo česta empirijska situacija.

Kod usmjerenih mreža posebno gledamo asimetriju:

  • ako je Periphery→Core jače od Core→Periphery, to nalikuje “reporting/prestiž”
  • ako je Core→Periphery jače, to nalikuje “broadcast/koordinacija” (ovdje uviđamo ovaj slučaj, jezgra dominira)

Vizualna ilustracija

set.seed(1)
plot_core_periphery(gE, cpE$core, main = "ENRON: jezgra (crno) i periferija (sivo)")

U Enron mreži jezgra–periferija ovdje je operacionalizirana kao dvopozicijski blokmodel dobiven transparentnom procedurom particioniranja (k-core na neusmjerenoj “collapse” projekciji), pri čemu se jezgra definira kao pozicija, a ne kao skup “najcentralnijih”. Takva definicija je metodološki konzistentna s pozicijskom perspektivom: akteri ulaze u jezgru zato što dijele strukturnu karakteristiku “ugrađenosti” u gusti podgraf, a ne zato što su pojedinačno visoko rangirani po jednoj centralnosti.

Izračunate blok-gustoće za usmjereni graf pokazuju da je \(\delta_{CC}\) najveća (\(\approx 0.150\)), što je u skladu s interpretacijom jezgre kao kohezivnog dijela sustava: unutar jezgre postoji relativno visok udio realiziranih usmjerenih veza u odnosu na broj mogućih. Međutim, gustoće između jezgre i periferije, \(\delta_{CP}\) i \(\delta_{PC}\), ostaju umjerene, a \(\delta_{PP}\) nije “blizu nule”, nego je usporediva s vezama između pozicija. To sugerira da, pod ovom particijom, periferija u Enronu nije čisto “rijetka zona” s minimalnom internom povezanošću, nego dio mreže u kojem i dalje postoji netrivijalna razina komunikacijskih relacija.

Asimetrija između \(\delta_{CP}\) i \(\delta_{PC}\) (ovdje je Core→Periphery veće od Periphery→Core) upućuje na to da jezgra u prosjeku više “emitira” veze prema periferiji nego obratno. U komunikacijskom kontekstu to je kompatibilno s interpretacijom jezgre kao koordinacijskog ili distribucijskog sloja (npr. slanje informacija, zadataka ili obavijesti prema širem krugu), iako takva interpretacija uvijek ostaje uvjetovana definicijom veze (što točno brid predstavlja u agregaciji e-maila).

Matrica slike dobivena pragom temeljenim na aritmetičkoj sredini gustoća rezultira obrascem u kojem samo blok jezgra→jezgra prelazi prag, a ostali blokovi padaju ispod njega. To ne znači da “jezgra–periferija ne postoji”, nego da je taj način binarizacije (jedan globalni prag na temelju sredine) vrlo strog i često reducira 2×2 matricu na “samo CC je dovoljno visok”. U praksi je za jezgra–periferija modele često smislenije interpretirati relativne odnose među gustoćama (redoslijed \(\delta_{CC}\) naspram ostalih) ili koristiti prag koji je teorijski motiviran (npr. očekivanje “PP nisko” u apsolutnom smislu), a ne nužno prag izračunat kao prosjek četiriju blokova.



UNIPU (g_weak_giant): jezgra–periferija u mreži suradnje/uloga

UNIPU bridi su mješavina suradničke (N–N, I–I) i usmjerene uloge (I→N). Zbog toga je korisno gledati:

  • blok-gustoće u usmjerenoj verziji (kao što je graf),
  • i po potrebi usporediti s neusmjerenom projekcijom (ako nas zanima čisto “suradnička” jezgra).

Particija: jezgra = top 10% po k-core indeksu

gU <- g_weak_giant

cpU <- core_partition_kcore(gU, core_method = "top_prop", top_prop = 0.10)
length(cpU$core); length(cpU$periphery)
## [1] 52
## [1] 292
bdU <- block_densities_cp(gU, core_names = cpU$core)
bdU$sizes
##      core periphery 
##        52       292
round(bdU$density, 4)
##             Core Periphery
## Core      0.5128    0.0088
## Periphery 0.0112    0.0175

Kad je \(\delta_{CC}\) osjetno veća od ostalih blokova, jezgru možemo tumačiti kao kohezivnu strukturnu poziciju. Kad je \(\delta_{PP}\) niska, periferija je slabo međusobno povezana, što je konzistentno s jezgra–periferija modelom. U usmjerenoj mreži, razlika između \(\delta_{CP}\) i \(\delta_{PC}\) sugerira asimetrične tokove (npr. koordinacija nasuprot eskalaciji / prestižu), no ovdje to ne vidimo. Kod UNIPU mreže, jezgra se može tumačiti kao skup aktera s ponavljanim zajedničkim angažmanima, dok asimetrija može reflektirati dio definicije brida (izvođač → nositelj).

Matrica slike

imgU <- image_matrix_2(bdU$density, alpha = "mean")
imgU$threshold
## [1] 0.1375765
imgU$I
##           Core Periphery
## Core         1         0
## Periphery    0         0

Ne vidimo obrazac blizak idealu (PP ~ 0, CC visoko), onda je “jezgra–periferija” nije dobar sažetak makro-arhitekture.

set.seed(1)
plot_core_periphery(gU, cpU$core, main = "UNIPU: jezgra (crno) i periferija (sivo)")

Jedna usporedba: jezgra kao pozicija vs “top centralnost” - kratka demonstracija razlike jezgre temeljem centralnosti i pozicijske jezgre

top_degree <- function(g, p = 0.10) {
  d <- igraph::degree(g, mode = "all")
  thr <- as.numeric(quantile(d, probs = 1 - p, na.rm = TRUE))
  V(g)$name[d >= thr]
}

coreE_kcore <- cpE$core
coreE_deg   <- top_degree(gE, p = 0.10)

length(intersect(coreE_kcore, coreE_deg)) / length(union(coreE_kcore, coreE_deg))
## [1] 0.2638889

Ovo daje Jaccard preklapanje: “jezgra kao pozicija nije nužno skup najcentralnijih čvorova”.

U UNIPU mreži ista procedura (k-core na neusmjerenoj projekciji, zatim blok-gustoće na izvornom grafu) daje izrazito jasnu separaciju u odnosu na Enron: \(\delta_{CC}\) je vrlo visoka \((\approx 0.513)\), dok su \(\delta_{CP}\), \(\delta_{PC}\) i \(\delta_{PP}\) znatno niže (reda veličine stotinki). Takav rezultat je mnogo bliži intuitivnom jezgra–periferija obrascu jer implicira da jezgra čini gust, kohezivan “klub” aktera među kojima su veze česte, dok periferija ima relativno malo veza i prema jezgri i unutar sebe.

Niska \(\delta_{PP}\) dodatno podržava interpretaciju periferije kao rjeđe povezane zone, a niske gustoće između pozicija upućuju na to da jezgra nije samo “centralni dio” koji je snažno povezan sa svim ostalima, nego prije svega interno kohezivna pozicija. To je interpretativno važno: jezgra–periferija u idealnom smislu očekuje i relativno snažnu povezanost Core–Periphery, dok ovdje dominantno iskače unutarjezgrena kohezija. U tom smislu, ovaj nalaz može sugerirati da UNIPU mreža, pod ovom particijom, više nalikuje sustavu s jednim vrlo gustim podskupom i većom “okolinom” koja nije intenzivno integrirana s jezgrom, nego je prisutna kroz slabije i rjeđe relacije.

S obzirom na to da UNIPU relacija može kombinirati suradničke veze i usmjerene uloge, interpretacija razlika \(\delta_{CP}\) i \(\delta_{PC}\) mora biti oprezna: asimetrija blokova može reflektirati institucionalni smjer relacije (npr. izvođač → nositelj) jednako kao i stvarne tokove koordinacije ili prestiža. Ipak, činjenica da su oba međubloka niska, a CC vrlo visok, najčvršće podupire zaključak o postojanju “pozicijske jezgre” kao kohezivnog bloka.

Matrica slike dobivena pragom sredine ponovno daje samo \(CC=1\), ali ovdje taj ishod ima jasniju semantiku: zato što je \(\delta_{CC}\) višestruko veća od ostalih, globalni prag prirodno odvaja jezgru od svega ostalog. U UNIPU slučaju to je konzistentno s time da jezgra dominira kao strukturni fenomen, dok ostali blokovi ostaju na nižoj” razini gustoće.


U Enronu dvopozicijski jezgra–periferija model, izveden k-core aproksimacijom, daje jezgru koja jest kohezivnija od ostatka sustava, ali periferija nije dovoljno “rijetka” da bi idealni obrazac bio dobar sažetak makro-arhitekture; jezgra se ovdje može čitati više kao “relativno gušća zona” unutar općenito gusto povezane komunikacijske mreže. U UNIPU mreži, naprotiv, kontrast \(\delta_{CC}\)) prema ostalim blokovima je toliko izražen da jezgra–periferija kao pozicijski blokmodel postaje znatno uvjerljivija redukcija, pri čemu je dominantna karakteristika jezgre visoka unutarnja kohezija, a ne nužno snažna integracija periferije kroz veze s jezgrom.




Hijerarhija

U prethodnim lekcijama hijerarhija je spominjana kao globalno svojstvo usmjerenih mreža, osobito u kontekstu asimetrije i acikličnosti. U ovom poglavlju promatramo hijerarhiju iz pozicijske perspektive: kao specifičnu makro-arhitekturu koja proizlazi iz diferencijacije uloga i vertikalne raspodjele moći. Drugim riječima, hijerarhija je strukturirani odnos među pozicijama, a ne samo skup centralnih aktera.



Hijerarhija kao usmjereni aciklički graf (DAG)

U graf-teorijskom smislu, čista hijerarhija modelira se kao usmjereni aciklički graf (Directed Acyclic Graph – DAG). Usmjerenost znači da su veze asimetrične (npr. nadređeni → podređeni), dok acikličnost znači da ne postoji zatvoreni usmjereni put koji bi omogućio povratak na početni čvor.

Formalno, u DAG-u ne postoji niz čvorova \(v_1, v_2, \dots, v_k\) takav da:

\[ v_1 \rightarrow v_2 \rightarrow \dots \rightarrow v_k \rightarrow v_1. \]

Odsutnost ciklusa jamči jednoznačnu orijentaciju moći ili autoriteta. Ako bi ciklus postojao, to bi impliciralo uzajamnu dominaciju, što je u suprotnosti s idejom hijerarhije.




Idealni model: outtree

Najčišći oblik hijerarhije jest usmjereno stablo s jedinstvenim korijenom (outtree). U takvoj strukturi postoji jedan vršni čvor (korijen) iz kojeg polaze svi ostali putevi, a svaki čvor (osim korijena) ima točno jednog nadređenog. Ako mreža ima \(n\) čvorova, broj bridova u outtree strukturi iznosi:

\[ m = n - 1. \]

Ova relacija označava minimalan broj veza potreban da bi svi čvorovi ostali povezani bez stvaranja ciklusa. Outtree je stoga najefikasniji oblik hijerarhijske organizacije jer koristi najmanji broj veza za održavanje potpune dostižnosti.


U empirijskim mrežama rijetko nalazimo savršeni outtree, ali on služi kao normativni model prema kojem se procjenjuje stupanj hijerarhijskosti sustava.



Krackhardtove mjere hijerarhije

David Krackhardt predložio je skup graf-teorijskih indeksa za kvantifikaciju stupnja do kojeg mreža nalikuje idealnoj hijerarhiji (Krackhardt, 2014). Ove mjere operacionaliziraju četiri dimenzije:

  • Connectedness (Povezanost) – udio parova čvorova koji su međusobno dostižni putem nekog usmjerenog puta. U savršenoj hijerarhiji vrijednost je 1.

  • Hierarchy (Hijerarhija) – mjera odsutnosti reciprociteta. Ako postoji veza \(i \rightarrow j\), tada ne smije postojati \(j \rightarrow i\). Indeks poprima vrijednost 1 kada nema recipročnih odnosa.

  • Efficiency (Efikasnost) – odnos stvarnog broja veza prema minimalnom broju potrebnom za održavanje povezanosti (\(n - 1\)). Svaka dodatna veza koja stvara alternativne putove smanjuje efikasnost.

  • Least Upper Boundness (LUBness) – mjeri postoji li jedinstveni vrh sustava, odnosno ima li svaki par čvorova zajedničkog nadređenog koji ih povezuje.


Sve četiri mjere skalirane su u intervalu \([0,1]\), gdje vrijednost 1 označava potpunu usklađenost s idealnim hijerarhijskim modelom.



Hijerarhija i pozicijska analiza

Iz perspektive pozicijske analize, hijerarhija se može interpretirati kao specifičan blokmodel u kojem su blokovi organizirani vertikalno. Matrica slike poprima gornjetrokutasti (ili donjetrokutasti) oblik, što odražava asimetrične relacije među pozicijama.

Ako je mreža podijeljena na \(K\) pozicija, hijerarhijska struktura podrazumijeva da za svaki par pozicija \((P_a, P_b)\) vrijedi:

\[ \delta_{ab} > 0 \Rightarrow \delta_{ba} \approx 0, \]

pri čemu \(\delta_{ab}\) označava gustoću veza iz pozicije \(a\) prema poziciji \(b\). Time se formalizira jednosmjernost dominacije između razina.


Hijerarhija stoga nije samo raspodjela centralnosti, nego uređeni sustav pozicija u kojem su uloge diferencirane prema vertikalnom principu (npr. uprava \(→\) menadžment \(→\) operativna razina).



Formalna i neformalna hijerarhija

Važno je razlikovati formalno propisanu hijerarhiju (organizacijska shema) od hijerarhije koja proizlazi iz stvarnih interakcija (npr. mreža savjeta ili utjecaja). Analiza mreže često otkriva odstupanja između te dvije razine. Neformalni lideri mogu imati veću strukturnu moć od formalno nadređenih, osobito ako zauzimaju brokerske ili centralne pozicije.

Time hijerarhija postaje empirijski mjerljiva struktura, a ne samo normativna kategorija.



Hijerarhija, stabilnost i ranjivost

Hijerarhijske mreže imaju specifične funkcionalne karakteristike:

  • Visoka koordinacijska učinkovitost (jasan tok naredbi).
  • Niska redundancija (malo alternativnih putova).
  • Visoka ranjivost na uklanjanje vršnih čvorova.

Uklanjanje korijena u outtree strukturi može fragmentirati cijeli sustav. Suprotno tome, horizontalno organizirane mreže pokazuju veću otpornost, ali manju koordinacijsku jasnoću.

U kontekstu ove lekcije, hijerarhija predstavlja završni oblik pozicijske diferencijacije: mreža više nije samo skup ekvivalentnih klasa, nego uređeni sustav razina. Time se koncept pozicije proširuje iz horizontalne sličnosti (ekvivalencija) na vertikalnu diferencijaciju (dominacija i podređenost), što je temelj za razumijevanje moći, autoriteta i institucionalne organizacije u društvenim i tehničkim sustavima.



Praktične koristi od analize hijerarhije

  1. Smanjenje konflikta i povećanje konsenzusa: Jasno definirane hijerarhije smanjuju napetosti jer akteri razumiju svoje uloge i rjeđe osporavaju tuđu dominaciju. Istraživanja pokazuju da jasnoća strukture moći u grupi snažno predviđa konsenzus u vjerovanjima njezinih članova.
  2. Identifikacija neformalne organizacije: Analiza omogućuje usporedbu formalnih hijerarhija (propisanih pravilnicima) s informalnim strukturama (tko se zapravo pita za savjet ili tko stvarno utječe na odluke). To otkriva “uska grla” (bottlenecks) i stvarne kanale kroz koje se posao obavlja.
  3. Optimizacija protoka resursa: Resursi i informacije u hijerarhijama prirodno teku prema vrhovnim pozicijama. Analizom hijerarhije organizacije mogu identificirati ključne brokere i gatekeepere koji kontroliraju te tokove.
  4. Mjerenje sistemske robusnosti i ranjivosti: Hijerarhijske mjere, poput Krackhardtovih indeksa, pomažu u procjeni koliko je mreža “mršava” i efikasna. Primjerice, uklanjanje čvorova s visokim stupnjem u strogoj hijerarhiji može dovesti do trenutne fragmentacije cijelog sustava.



Primjeri: Enron i Unipu

# 1) Je li mreža DAG?
igraph::is_dag(gE)
## [1] FALSE
igraph::is_dag(gU)
## [1] FALSE
# 2) Koliko je mreža recipročna (0..1); čista hijerarhija -> blizu 0
igraph::reciprocity(gE, ignore.loops = TRUE)
## [1] 0.6066445
igraph::reciprocity(gU, ignore.loops = TRUE)
## [1] 0.9218551
# 3) Jaka povezanost (SCC): ciklusi se pojavljuju kao SCC veličine > 1
sccE <- igraph::components(gE, mode = "strong")
sccU <- igraph::components(gU, mode = "strong")

sort(sccE$csize, decreasing = TRUE)[1:10]
##  [1] 174   1   1   1   1   1   1   1   1  NA
sort(sccU$csize, decreasing = TRUE)[1:10]
##  [1] 296   6   3   3   2   2   2   2   1   1
# Udio čvorova koji su u "cikličkim grupama" (SCC > 1)
mean(sccE$csize[sccE$membership] > 1)
## [1] 0.956044
mean(sccU$csize[sccU$membership] > 1)
## [1] 0.9186047

“Kompromis” za empiriju: kondenzacija u DAG (condensation graph)

is_dag(FALSE) za obje mreže samo kaže: postoji barem jedan ciklus. U e-mail i suradničkim mrežama to je normalno.

reciprocity(gE)=0.6066 i reciprocity(gU)=0.9219 govore “koliko često veze postoje u oba smjera” te visok reciprocitet znači uzajamnu komunikaciju/suradnju, što više očekujemo naći u UNIPU (suradničke veze, timovi) nego u Enronu (iako i u e-mailu reciprocitet može biti visok zbog odgovaranja).

Čak i kad originalna mreža nije DAG, možemo je svesti na DAG tako da svaki SCC skupimo u jedan čvor. To je standardna tehnika: “hijerarhija među cikličkim blokovima”.

# Kondenzacija: svaki SCC postaje jedan "super-čvor" -> rezultat je DAG
# 1) Jake komponente
sccE <- igraph::components(gE, "strong")

# 2) Kontrakcija: svaka komponenta postaje jedan čvor
gE_cond <- igraph::contract(gE, sccE$membership)

# 3) Uklanjanje višestrukih bridova i self-loopova
gE_cond <- igraph::simplify(gE_cond, remove.loops = TRUE)

# 4) Provjera: sada mora biti DAG
is_dag(gE_cond)
## [1] TRUE
sccU <- igraph::components(gU, "strong")

gU_cond <- igraph::contract(gU, sccU$membership)
gU_cond <- igraph::simplify(gU_cond, remove.loops = TRUE)

is_dag(gU_cond)
## [1] TRUE
vcount(gE_cond)
## [1] 9
ecount(gE_cond)
## [1] 8
vcount(gU_cond)
## [1] 36
ecount(gU_cond)
## [1] 36
# Koliko je "razina" u toj DAG makro-strukturi?
# topo_sort daje poredak kompatibilan s hijerarhijom (ako je DAG)
topoE <- topo_sort(gE_cond, mode = "out")
topoU <- topo_sort(gU_cond, mode = "out")

head(names(topoE))
## [1] "NA"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
## [2] "c(\"Albert Meyers\", \"Thomas Martin\", \"Andrea Ring\", \"Andrew Lewis\", \"Andy Zipper\", \"Jeffrey Shankman\", \"Barry Tycholiz\", \"Benjamin Rogers\", \"Bill Rapp\", \"NA\", \"Bradley Mckay\", \"NA\", \"Richard Sanders\", \"Cara Semperger\", \"Daron Giron\", \"Charles Weldon\", \"Chris Dorland\", \"Chris Germany\", \"NA\", \"Cooper Richey\", \"Craig Dean\", \"Dana Davis\", \"Dan Hyvl\", \"Danny McCarty\", \"Daren Farmer\", \"Darrell Schoolcraft\", \"Daron Giron\", \"David Delainey\", \"Susan Bailey\", \"NA\", \"Diana Scholtes\", \"Thomas Martin\", \"Don Baughman\", \n\"Drew Fossum\", \"James Steffes\", \"NA\", \"NA\", \"Mark Haedicke\", \"Elizabeth Sager\", \"Eric Bass\", \"Eric Saibi\", \"Errol McLaughlin\", \"Sandra Brawner\", \"Larry Campbell\", \"Peter Keavey\", \"Fletcher Sturm\", \"Frank Ermis\", \"Geir Solberg\", \"Geoffery Storey\", \"Gerald Nemec\", \"Greg Whalley\", \"Harpreet Arora\", \"Andrew Lewis\", \"Holden Salisbury\", \"Hunter Shively\", \"James Derrick\", \"James Steffes\", \"Jane Tholt\", \"NA\", \"Jason Wolfe\", \"Jay Reitmeyer\", \"Jeff Dasovich\", \"Jeff King\", \"John Hodge\", \"Jeffrey Shankman\", \n\"Jeffery Skilling\", \"Daren Farmer\", \"NA\", \"Jim Schwieger\", \"Vince Kaminski\", \"Steven Kean\", \"NA\", \"Joe Parks\", \"Joe Quenet\", \"Joe Stepenovitch\", \"John Arnold\", \"John Forney\", \"NA\", \"John Hodge\", \"John Lavorato\", \"John Zufferli\", \"Jonathan Mckay\", \"Fletcher Sturm\", \"Juan Hernandez\", \"Judy Townsend\", \"Philip Allen\", \"Kam Keiser\", \"Kate Symes\", \"Kay Mann\", \"Keith Holst\", \"Kenneth Lay\", \"Kevin Hyatt\", \"Kevin Presto\", \"Kevin Ruscitti\", \"Kimberly Watson\", \"Kim Ward\", \"Larry Campbell\", \"Lawrence May\", \"Randall Gay\", \n\"Lindy Donoho\", \"NA\", \"NA\", \"Patrice Mims\", \"Louise Kitchen\", \"Lynn Blair\", \"NA\", \"Marie Heard\", \"Mark Haedicke\", \"NA\", \"Mark Taylor\", \"Mark Whitt\", \"Martin Cuilla\", \"Matthew Lenhart\", \"Matthew Motley\", \"NA\", \"John Forney\", \"Michelle Cash\", \"Michelle Lokay\", \"Mike Carson\", \"Michael Grigsby\", \"Michael Maggi\", \"NA\", \"Mike Swerzbin\", \"Phillip Love\", \"Monika Causholli\", \"NA\", \"Kevin Presto\", \"Susan Scott\", \"Jane Tholt\", \"Patrice Mims\", \"Paul Thomas\", \"Peter Keavey\", \"Philip Allen\", \"Phillip Love\", \"Phillip Platter\", \n\"Randall Gay\", \"Richard Ring\", \"Richard Sanders\", \"Richard Shapiro\", \"Rick Buy\", \"Robert Badeer\", \"Robert Benson\", \"Rod Hayslett\", \"Ryan Slinger\", \"Sally Beck\", \"Sandra Brawner\", \"NA\", \"NA\", \"Scott Neal\", \"Shelley Corman\", \"Hunter Shively\", \"Stacy Dickson\", \"Stanley Horton\", \"Stephanie Panus\", \"Steven Kean\", \"Susan Bailey\", \"Susan Pereira\", \"Susan Scott\", \"Kim Ward\", \"Tana Jones\", \"Teb Lokey\", \"Theresa Staab\", \"John Hodge\", \"Thomas Martin\", \"Paul Lucci\", \"Tom Donohoe\", \"Tori Kuykendall\", \"Tracy Geaccone\", \n\"Vince Kaminski\", \"Vladi Pimenov\", \"Charles Weldon\", \"David Delainey\", \"Susan Pereira\", \"Stacey White\")"
## [3] "NA"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
## [4] "NA"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
## [5] "NA"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
## [6] "Michelle Lokay"
head(names(topoU))
## [1] "231" "352" "056" "088" "212" "239"

Za Enron se vidi ogromna jaka komponenta (174) i vrlo visok udio čvorova u cikličkim skupinama. Treba naglasiti da to znači da je u agregiranoj mreži većina čvorova međusobno dostižna u oba smjera (postoji put i i→j i j→i), što je “anti-DAG” obrazac i tipično za komunikaciju.

Za UNIPU: SCC od 296 + nekoliko manjih SCC; opet znači da većina čvorova pripada uzajamno povezanoj jezgri u smislu dostižnosti (ne nužno core-periphery).

Kondenzacija (contract SCC u DAG) - vcount(gE_cond)=9 i vcount(gU_cond)=36 su “super-čvorovi” koji predstavljaju SCC blokove; DAG se odnosi na odnose među blokovima, ne među pojedincima.

Provjera da Enron mreža nije DAG potvrđuje očekivani empirijski obrazac: e-mail komunikacija u organizaciji uključuje povratne petlje, uzajamno odgovaranje i kruženje informacija, pa stoga struktura ne može biti strogo aciklična. To je izravno vidljivo i u vrlo visokoj recipročnosti (\(≈0.61\)), koja implicira da velik udio parova čvorova razmjenjuje veze u oba smjera. U Krackhardtovu smislu, takva recipročnost smanjuje “čistoću” hijerarhije jer idealna hijerarhija pretpostavlja dominaciju bez uzvraćanja, odnosno usmjerenost nalik zapovjednom lancu.

Analiza jakih komponenti dodatno pojašnjava ovu sliku: najveća SCC u Enronu ima 174 čvora, a udio čvorova koji pripadaju komponentama većim od 1 iznosi \(≈0.96\). To znači da je gotovo cijeli sustav uklopljen u jednu veliku cikličku jezgru u smislu dostižnosti putem usmjerenih putova, što je kompatibilno s organizacijskom komunikacijom gdje se informacije i zahtjevi često mogu “vratiti” do polazišta kroz neki lanac posrednika. Kondenzacijom SCC-ova dobiva se DAG s vrlo malo “super-čvorova” (9) i gotovo linearnom strukturom (8 bridova), što sugerira da se većina cikličnosti događa unutar jedne dominantne komunikacijske mase, dok je hijerarhija među tim masama relativno gruba i niskodimenzionalna.

UNIPU mreža također nije DAG, što je očekivano s obzirom na to da sustav sadrži i simetrične relacije (N–N, I–I) i relacije koje u pravilu nose smjer (I→N), pa se ciklusi mogu pojaviti i kroz uzajamne suradnje i kroz kombinacije uloga. Recipročnost je vrlo visoka (\(≈0.92\)), što znači da je gotovo sva relacijska struktura uzajamna. To snažno ograničava interpretaciju mreže kao “hijerarhijske” u strogo graf-teorijskom smislu: čak i kad postoji vertikalna semantika u nekim bridovima, ukupna mrežna topologija dominatno je obilježena uzvraćanjem i kooperacijom.

Struktura jakih komponenti pokazuje veliku dominantnu SCC (296 čvorova) i nekoliko manjih cikličkih skupina, a udio čvorova u SCC-ovima većim od 1 je \(≈0.92\). To znači da je velika većina sustava uklopljena u ciklički povezanu jezgru, slično kao i kod Enrona, ali uz nešto više fragmentacije na dodatne SCC-ove. Kondenzacija daje znatno veći DAG nego u Enronu (36 super-čvorova i 36 bridova), što implicira da se cikličnost pojavljuje u više odvojenih “blokova” i da je makro-struktura među blokovima razgranatija. U institucionalnim podacima to je kompatibilno s postojanjem više relativno autonomnih nastavnih/organizacijskih klastera koji su interno gusto recipročni, ali su međusobno povezani preko ograničenog broja relacija.

Krackhardtovi indeksi hijerarhije

Najjednostavnije je koristiti paket sna jer on već ima Krackhardtove mjere (računaju se na matrici, ne na igraph objektu).

Važna napomena: sna funkcije očekuju matricu ili network objekt. Ako im damo igraph, dobijemo grešku.

AE <- as.matrix(as_adjacency_matrix(gE, sparse = FALSE))  # 0/1
AU <- as.matrix(as_adjacency_matrix(gU, sparse = FALSE))  # 0/1

library(sna)

# Connectedness: koliko je parova čvorova dostižno putem usmjerenog puta
sna::connectedness(AE)
## [1] 1
sna::connectedness(AU)
## [1] 1
# Hierarchy: odsutnost recipročnosti (u Krackhardt smislu)
sna::hierarchy(AE)
##        Mut 
## 0.07188392
sna::hierarchy(AU)
##         Mut 
## 0.004169774
# Efficiency: “mršavost” strukture u odnosu na minimalni broj veza (n-1)
sna::efficiency(AE)
## [1] 0.9136473
sna::efficiency(AU)
## [1] 0.9761579
# LUBness: postoji li jedinstveni “gornji nadređeni” za parove
sna::lubness(AE)
## [1] 1
sna::lubness(AU)
## [1] 0.1749612

Kako to tumačimo (u tekstu):

  • Ove četiri vrijednosti možemo čitati kao “koliko mreža nalikuje idealnoj hijerarhiji”.

  • Za Enron tipično očekujemo: nižu hijerarhiju i nižu efikasnost (komunikacija je redundantna).

  • Za UNIPU očekujemo: hijerarhija nije “čista” (jer imamo simetrične veze N–N i I–I), ali u smjeru I→N često se vidi vertikalni element.

Krackhardt “hierarchy” je visok kad nema recipročnosti; ovdje je nizak jer je reciprocitet visok — to je konzistentno s prethodnom mjerom reciprociteta.

Za Enron, connectedness = 1 pokazuje da je, u smislu usmjerenih putova, mreža maksimalno “dostižna” (što je u praksi česta posljedica postojanja velike SCC). Hijerarhija je niska (\(≈0.072\)), što je konzistentno s visokom recipročnosti i prisutnošću ciklusa: mreža je daleko od idealno hijerarhijske. Istovremeno, visoka efikasnost (\(≈0.914\)) upućuje da je struktura relativno “mršava” u odnosu na minimalni broj veza potreban za povezivost, ali bez implikacije da je pritom hijerarhijska; efikasnost ovdje prije govori da se dosezanje u mreži ostvaruje bez ekstremne redundancije, iako se i dalje zadržavaju povratne veze. LUBness = 1 znači da, prema toj mjeri, parovi čvorova imaju jedinstvene “najniže zajedničke nadređene” u relevantnom smislu mjere, što se može javiti i u sustavima koji nisu čisti DAG jer Lubness nije ekvivalentna zahtjevu acikličnosti, nego stabilnosti nadređenih relacija u dosežnosti.

Za Unipu, connectedness = 1 opet pokazuje maksimalnu dostižnost, no hijerarhija je praktički nula (\(≈0.004\)), što je u skladu s recipročnosti bliskoj 1: sustav topološki nimalo ne nalikuje čistoj hijerarhiji. Efikasnost je vrlo visoka (\(≈0.976\)), što govori da se dosezanje realizira s relativno malo “viška” veza u odnosu na minimum potreban za povezivost, ali taj nalaz treba čitati uz oprez jer u visoko recipročnim mrežama redundancija ne mora izgledati kao “višak” u istom smislu kao u strogo hijerarhijskim strukturama. Lubness je niska (\(≈0.175\)), što sugerira da ne postoji stabilan jedinstveni “gornji” čvor za mnoge parove, što je upravo ono što očekujemo u sustavu s mnogo paralelnih suradničkih putova i bez jednoznačno definiranog vrha.

Hijerarhija kao blokmodel (pozicijska perspektiva)

Ovdje ne uvodimo nove funkcije — koristimo ono što već imamo iz blokmodel dijela:

  • posE, posU (pozicije iz HCA)

  • B_E, B_U (blok gustoće)

  • I_E, I_U (matrica slike)

Ideja: ako je hijerarhija prisutna između pozicija, onda se nakon dobrog poretka pozicija veze koncentriraju iznad (ili ispod) dijagonale.

  1. Poredak pozicija po “net flow” (OUT–IN između pozicija)
netflow_E <- rowSums(B_E, na.rm = TRUE) - colSums(B_E, na.rm = TRUE)
netflow_U <- rowSums(B_U, na.rm = TRUE) - colSums(B_U, na.rm = TRUE)

ordE <- order(netflow_E, decreasing = TRUE)
ordU <- order(netflow_U, decreasing = TRUE)

# Permutirani blokovi (da “hijerarhija” postane vidljiva)
B_E_ord <- B_E[ordE, ordE]
B_U_ord <- B_U[ordU, ordU]

round(B_E_ord, 3)
##       P6    P3    P5    P4    P1    P2
## P6 0.950 0.708 0.188 0.175 0.367 0.606
## P3 0.667 0.513 0.146 0.125 0.042 0.064
## P5 0.088 0.167 0.608 0.023 0.039 0.089
## P4 0.088 0.102 0.031 0.800 0.023 0.027
## P1 0.098 0.029 0.029 0.009 0.048 0.052
## P2 0.194 0.048 0.059 0.029 0.072 0.322
round(B_U_ord, 3)
##       P3    P5    P2    P6    P4    P1    P8   P7
## P3 0.800 0.000 0.002 0.000 0.000 0.006 0.000 1.00
## P5 0.000 1.000 0.009 0.000 0.000 0.005 0.286 0.00
## P2 0.003 0.012 0.011 0.043 0.011 0.011 0.004 0.05
## P6 0.000 0.000 0.043 1.000 0.010 0.000 0.000 0.00
## P4 0.000 0.000 0.011 0.010 0.683 0.004 0.000 0.00
## P1 0.006 0.005 0.008 0.000 0.004 0.964 0.000 0.03
## P8 0.000 0.143 0.003 0.000 0.000 0.000 1.000 0.00
## P7 0.267 0.000 0.033 0.000 0.000 0.030 0.000   NA

Pozicije s većim “netflow” su više razine (više šalju prema drugim pozicijama nego što primaju).

Hijerarhijski uzorak znači: veće gustoće se “slijevaju” prema jednoj strani matrice (gore/desno ili dolje/lijevo).

  1. Matrica slike: je li “uglavnom trokutasta”?
# Ako već imate I_E i I_U (image matrix), samo ih permutirajte:
I_E_ord <- I_E[ordE, ordE]
I_U_ord <- I_U[ordU, ordU]

I_E_ord
##    P6 P3 P5 P4 P1 P2
## P6  1  1  0  0  1  1
## P3  1  1  0  0  0  0
## P5  0  0  1  0  0  0
## P4  0  0  0  1  0  0
## P1  0  0  0  0  0  0
## P2  0  0  0  0  0  1

Pozicijska perspektiva hijerarhije kroz blokmodel dodatno pokazuje da se “vertikalnost” ne pojavljuje primarno kao jednostavna gornjetrokutasta matrica gustoća. Nakon poretka pozicija po net-flowu, matrica gustoća i matrica slike pokazuju koncentraciju veza u nekoliko blokova, ali ne i čistu trokutastu strukturu; indeks “trokutastosti” (\(≈0.5\)) sugerira određenu asimetriju prema jednoj strani, no ne dovoljno jasnu da bi se makro-arhitektura svela na uredan hijerarhijski slojeviti poredak pozicija. Drugim riječima, Enronova “hijerarhija” u ovim rezultatima izgleda više kao mješavina gustih unutarnjih blokova i selektivnih među-blok veza, nego kao uredan lanac razina.

I_U_ord
##    P3 P5 P2 P6 P4 P1 P8 P7
## P3  1  0  0  0  0  0  0  1
## P5  0  1  0  0  0  0  1  0
## P2  0  0  0  0  0  0  0  0
## P6  0  0  0  1  0  0  0  0
## P4  0  0  0  0  1  0  0  0
## P1  0  0  0  0  0  1  0  0
## P8  0  1  0  0  0  0  1  0
## P7  1  0  0  0  0  0  0 NA

UNIPU-ova matrica slike ne pokazuje obrazac koji bi se mogao čitati kao “hijerarhijski” u smislu trokutaste koncentracije veza iznad ili ispod dijagonale. Dominantan signal je blok-dijagonalnost: većina pozicija ima “1” prvenstveno na vlastitoj dijagonali (P5, P6, P4, P1, P8), što znači da su intra-pozicijske veze dovoljno guste da prijeđu prag binarizacije, dok su veze između različitih pozicija uglavnom ispod praga (0).

Nekoliko izuzetaka ukazuje na selektivne međupozicijske relacije, ali one su simetrično raspoređene i ne tvore stabilan lanac razina. Konkretno, vidljiv je uzajaman odnos P3↔︎P7 (P3→P7 i P7→P3) te odnos P5↔︎P8 (P5→P8 i P8→P5). To je konzistentno s ranijim nalazima o visokoj recipročnosti i općenito sugerira da se pozicije u UNIPU mreži ponašaju kao relativno zatvoreni “funkcionalni blokovi” s nekoliko mostova između odabranih parova blokova, a ne kao strogo poredane razine hijerarhije.

Redak/stupac P2 je posvuda 0, što znači da ta pozicija u matrici slike ne ulazi u “gust” odnos ni s kim pri zadanom pragu (uključujući i samu sebe). To se tipično događa kada je pozicija brojna ali rijetka, ili kada su veze te pozicije disperzirane po više blokova, pa nijedan blok ne prijeđe prag gustoće u binarizaciji. NA u (P7,P7) znači da za taj blok gustoća nije definirana ili je neprocjenjiva (najčešće zbog vrlo male pozicije ili nula mogućih veza nakon odabira/čišćenja), pa taj element ne treba interpretirati sadržajno.

Dakle, UNIPU ovdje izgleda primarno modularno (blokovi + nekoliko selektivnih među-blok veza), a ne hijerarhijski.

Ako želimo jednu brojku (jednostavan indeks “trokutastosti”):

M <- I_E_ord
diag(M) <- NA
up <- sum(M[upper.tri(M)] == 1, na.rm = TRUE)
lo <- sum(M[lower.tri(M)] == 1, na.rm = TRUE)
(up - lo) / (up + lo)
## [1] 0.5
M <- I_U_ord
diag(M) <- NA
up <- sum(M[upper.tri(M)] == 1, na.rm = TRUE)
lo <- sum(M[lower.tri(M)] == 1, na.rm = TRUE)
(up - lo) / (up + lo)
## [1] 0



Empirijski primjeri iz prakse i njihova korisnost

  • Uspon obitelji Medici u Firenci: Jedan od najpoznatijih primjera u mrežnoj znanosti koristi analizu hijerarhije i brokeragea kako bi objasnio uspon ove obitelji. Iako nisu bili najbogatiji, Medici su zauzeli ključnu brokersku poziciju u neformalnoj hijerarhiji brakova i poslovnih veza, što im je omogućilo da koordiniraju inače nepovezane frakcije elite i pretvore tu poziciju u apsolutnu političku moć.
  • Akademski “kastinski sustav”: Analiza hijerarhije u mrežama razmjene doktora znanosti (PhD exchange networks) otkrila je postojanje stabilnih prestižnih hijerarhija u akademskoj zajednici. Ovo je bilo korisno za razumijevanje nejednakosti pri zapošljavanju na sveučilištima, pokazujući da kandidati s vrhovnih institucija u hijerarhiji imaju nerazmjerno veće šanse za dobivanje pozicija na drugim visokorangiranim odjelima.
  • Organizacija u učionicama: Istraživanja u školama (npr. McFarland) pokazala su kako neformalna hijerarhija među učenicima utječe na otpor prema autoritetu. Učionice s nejasnom ili razbijenom hijerarhijom podložnije su svakodnevnim oblicima prkosa i otežanom radu nastavnika.
  • Wikipedia i digitalni sustavi: Analiza formiranja hijerarhije među urednicima Wikipedije otkrila je da se čak i u otvorenim sustavima koji teže horizontalnosti brzo razvijaju strukture vodstva i autoriteta koje su nužne za održavanje kvalitete sadržaja i rješavanje uredničkih sporova.
  • Biološki sustavi (Dominacija kod životinja): Modeli hijerarhije primijenjeni su na proučavanje rasta struktura dominacije kod kokoši (transitivni odnosi) i babuna (timarenje kao valuta statusa), potvrđujući da su hijerarhijski obrasci univerzalni mehanizam organizacije živih sustava.


Zaključno, analiza hijerarhije pretvara apstraktne pojmove poput “utjecaja” u mjerljive varijable koje pomažu predvidjeti stabilnost i učinkovitost ljudskih i tehničkih sustava.




Uloge (brokerage, gatekeeper, liaison)

Nakon što smo definirali pozicije i makro-arhitekturu mreže, sljedeći korak jest razumjeti dinamičku funkciju aktera unutar i između tih pozicija. Uloga nije isto što i centralnost niti isto što i pripadnost poziciji. Centralnost mjeri relativnu važnost, pozicija označava strukturnu klasu, dok uloga opisuje način na koji akter posreduje, kontrolira ili usmjerava tokove između drugih aktera ili grupa.

Jedan od najutjecajnijih formalnih pristupa analizi uloga jest model brokerskih pozicija Goulda i Fernandeza (1989). Ovaj pristup promatra usmjerene trijade u kojima jedan akter posreduje između dva druga aktera koji nisu izravno povezani. Ključna je ideja da značenje posredovanja ovisi o grupnoj pripadnosti sudionika.

Pretpostavimo trijadu oblika:

\[ i \rightarrow b \rightarrow j, \]

gdje je \(b\) broker koji posreduje između aktera \(i\) (izvor) i \(j\) (odredište). Uloga brokera određuje se prema tome pripada li isti ili različitim grupama u odnosu na \(i\) i \(j\).




Brokerage kao strukturalni fenomen

Brokerage označava situaciju u kojoj akter zauzima strukturnu rupu između dviju skupina (Burt, 1992). Takva pozicija omogućuje kontrolu nad protokom informacija, resursa ili utjecaja. No, Gould i Fernandez pokazuju da nisu sve brokerske pozicije jednake: njihovo značenje ovisi o granicama grupa.

Formalno, neka je \(g(x)\) oznaka grupe kojoj akter \(x\) pripada. Tada se uloge razlikuju prema relaciji između \(g(i)\), \(g(b)\) i \(g(j)\).




Coordinator (Koordinator)

Koordinator posreduje između dva aktera iste grupe kojoj i sam pripada:

\[ g(i) = g(b) = g(j). \]


On djeluje unutar vlastite zajednice i olakšava koordinaciju među njezinim članovima. Funkcionalno, koordinator doprinosi unutarnjoj koheziji i smanjuje transakcijske troškove komunikacije.

U organizacijskom kontekstu to može biti voditelj tima koji povezuje članove istog odjela. Iako takav akter ne mora biti globalno najcentralniji, njegova je uloga presudna za stabilnost unutar bloka.



Gatekeeper (Vratar)

Gatekeeper kontrolira ulaz informacija iz druge grupe u vlastitu grupu:

\[ g(i) \neq g(b) = g(j). \]


On prima informacije iz vanjskog sustava i odlučuje koje će se informacije prenijeti unutar njegove grupe. Time gatekeeper ima normativnu i selektivnu moć. Njegova pozicija omogućuje filtriranje, reinterpretaciju ili blokiranje tokova.

U institucionalnim sustavima to može biti urednik, regulator ili menadžer koji odobrava prijedloge izvana. U mrežama znanja, gatekeeper odlučuje koji će vanjski impulsi postati dio lokalne prakse.



Representative (Predstavnik)

Suprotno gatekeeperu, representative prenosi informacije iz vlastite grupe prema van:

\[ g(i) = g(b) \neq g(j). \]


On je glas svoje zajednice prema drugima. Iako strukturalno sličan gatekeeperu, njegova funkcija je eksterna: omogućuje projekciju interesa ili resursa prema drugim blokovima.



Liaison (Posrednik između grupa)

Liaison povezuje dvije različite grupe, a da sam ne pripada nijednoj od njih:

\[ g(i) \neq g(b) \neq g(j), \quad g(i) \neq g(j). \]


Ovdje broker djeluje kao neutralna treća strana. On nema interni identitet u odnosu na grupe koje povezuje, što mu može dati veću fleksibilnost, ali i manju legitimnost.

U praksi to može biti konzultant, medijator ili vanjski stručnjak koji povezuje inače nepovezane sustave.



Uloga kao relacijska kategorija

Važno je naglasiti da su brokerske uloge relacijske, a ne inherentne osobine aktera. Isti akter može biti koordinator u jednoj situaciji, a liaison u drugoj, ovisno o strukturi mreže i definiciji grupa.

Broj brokerskih epizoda može se formalno kvantificirati brojanjem svih trijada u kojima akter zauzima određeni položaj. Time se dobiva distribucija uloga unutar mreže.



Uloge i moć

Brokerage je povezan s konceptom moći jer kontrola nad informacijskim tokovima stvara asimetriju. Akter koji zatvara strukturnu rupu može ostvariti prednost kroz:

  • pristup heterogenim informacijama,
  • arbitražu između grupa,
  • kontrolu distribucije resursa.

Međutim, brokerske pozicije mogu biti i ranjive: ako se uspostavi izravna veza između dviju grupa, uloga brokera nestaje. Stoga je brokerska moć često dinamična i ovisna o stabilnosti strukturnih granica.



Uloge i makro-arhitektura

U kontekstu blokmodeliranja, uloge se mogu interpretirati kao funkcionalne veze između pozicija. Dok blokmodel definira tko pripada kojoj klasi, analiza uloga pokazuje kako klase međusobno komuniciraju.

Time se zatvara krug:

  • Ekvivalencija → definira pozicije.
  • Blokmodeliranje → definira makro-strukturu.
  • Brokerage → definira dinamičku funkciju unutar te strukture.

Uloge stoga predstavljaju operativnu dimenziju pozicijske analize: one pokazuju kako se struktura prevodi u proces, odnosno kako raspored veza generira tokove moći, informacija i utjecaja u mreži.

Autoritet i hubovi (HITS): uloge u usmjerenim hijerarhijama

U prethodnoj lekciji analizirali smo HITS algoritam kao metodu rangiranja čvorova u usmjerenim mrežama. Ovdje ga reinterpretiramo u kontekstu uloga i hijerarhije. HITS (Hyperlink-Induced Topic Search) ne mjeri samo “važnost”, nego diferencira dvije komplementarne strukturne funkcije: autoritet i hub. Time uvodi asimetričnu diferencijaciju uloga koja je posebno relevantna u hijerarhijskim i proto-hijerarhijskim sustavima.

Temeljna ideja HITS algoritma jest kružna definicija:

  • Čvor je dobar autoritet ako na njega upućuju dobri hubovi.
  • Čvor je dobar hub ako upućuje na dobre autoritete.
  • Autoritet čvora proporcionalan je zbroju hub vrijednosti čvorova koji na njega upućuju.
  • Hub vrijednost proporcionalna je zbroju autoritetnih vrijednosti čvorova na koje upućuje.

HITS formalizira razliku između:

  • prestiža (authority) – akter kojeg drugi prepoznaju kao relevantan izvor,
  • distribucijske funkcije (hub) – akter koji usmjerava prema relevantnim izvorima.

U društvenim mrežama znanja, autoritet može biti stručnjak ili institucija koja generira referentne informacije, dok hub može biti akter koji povezuje druge s tim izvorima (npr. urednik, kurator, mentor). U citatnim mrežama autoritet je rad koji se često citira od strane važnih radova, dok je hub rad koji citira ključnu literaturu.

Time HITS diferencira dvije vrste moći:

  • epistemičku moć (biti referenca),
  • navigacijsku moć (usmjeravati prema referencama).

U kontekstu hijerarhije, HITS omogućuje identifikaciju vertikalne diferencijacije uloga. U idealnoj hijerarhijskoj strukturi (npr. outtree), vršni čvor često ima visoku autoritetnu vrijednost ako prima mnoge veze, dok srednje razine mogu imati visoke hub vrijednosti jer distribuiraju naredbe ili informacije prema nižim razinama.

Ako mreža pokazuje snažnu asimetriju (malo reciprociteta i malo ciklusa), autoriteti i hubovi prirodno se diferenciraju. U mrežama s visokom reciprocitetnošću ili gustoćom, ta se diferencijacija smanjuje jer čvorovi istodobno primaju i šalju velik broj veza.

Stoga HITS može poslužiti kao indikator stupnja funkcionalne diferencijacije unutar usmjerenog sustava.

Iz pozicijske perspektive, autoriteti i hubovi često se koncentriraju u određenim blokovima. Primjerice:

  • Jezgra može sadržavati većinu autoriteta.
  • Periferija može imati veći udio hubova koji upućuju prema jezgri.
  • U hijerarhijskom blokmodelu autoriteti su često na vrhu vertikalne strukture, dok hubovi posreduju između razina.

Ako je mreža podijeljena na pozicije \(P_1, \dots, P_K\), moguće je analizirati distribuciju prosječnih autoritetnih i hub vrijednosti po pozicijama:

\[ \bar{a}*k = \frac{1}{|P_k|} \sum*{i \in P_k} a_i, \]

\[ \bar{h}*k = \frac{1}{|P_k|} \sum*{i \in P_k} h_i. \]

Ovdje \(\bar{a}_k\) i \(\bar{h}_k\) predstavljaju prosječnu autoritetnu i hub vrijednost pozicije \(k\), a \(|P_k|\) broj aktera u toj poziciji. Time HITS postaje alat za interpretaciju uloga na razini blokova, a ne samo pojedinaca.




Stabilnost i ranjivost

Mreže s izraženim hubovima pokazuju specifičnu topološku dinamiku:

  • Uklanjanje ključnih hubova može fragmentirati sustav.
  • Uklanjanje pojedinačnih autoriteta smanjuje informacijski prestiž, ali ne mora narušiti strukturalnu povezanost.

U scale-free mrežama hubovi su posebno kritični za održavanje globalne dostižnosti. Time HITS povezuje koncept uloga s konceptom robusnosti sustava.



Epistemološka napomena

HITS je osjetljiv na strukturu podgrafa i može reflektirati lokalne gustoće ili zajednice. Njegove vrijednosti nisu apsolutne mjere važnosti, nego relativne unutar danog konteksta mreže. Stoga interpretacija autoriteta i hubova uvijek mora uzeti u obzir granice mreže i prirodu relacije.

U okviru ove lekcije, HITS predstavlja most između centralnosti i uloga. Dok su klasične mjere centralnosti često simetrične, HITS formalizira asimetričnu diferencijaciju funkcija unutar usmjerenih mreža. Autoritet i hub nisu samo numeričke vrijednosti, nego pozicijske uloge koje proizlaze iz hijerarhijske i funkcionalne organizacije sustava.



Praktične koristi analize autoriteta i hubova

  1. Razumijevanje navigacije i protoka resursa: Hubovi dramatično mijenjaju način na koji se krećemo kroz mrežu. U “scale-free” sustavima, prisutnost hubova omogućuje dosezanje većine odredišta kroz minimalan broj koraka, što povećava učinkovitost protoka informacija ili materije.
  2. Identifikacija strukturne važnosti nasuprot pukoj popularnosti: Analiza omogućuje prepoznavanje “vrijednih odredišta” (autoriteta) koja ne moraju imati najveći broj veza, ali su prepoznata od strane najkvalitetnijih “vodiča” (hubova).
  3. Procjena sistemske robusnosti i ranjivosti: Hubovi su ključne točke oslonca; njihovo uklanjanje (uslijed napada ili kvara) može dovesti do trenutne fragmentacije mreže na nepovezane komponente. U tehnološkim sustavima, hubovi su kritične točke čiji kvar izaziva kaskadne neuspjehe.
  4. Poboljšanje rangiranja i pretraživanja informacija: Ova analiza omogućuje razlikovanje radova ili stranica koji sintetiziraju literaturu od onih koji predstavljaju temeljne reference.



Primjeri

Enron

library(intergraph)
library(network)
library(sna)

gE <- g_giant

# Identifikator čvorova (ENRON često ima V(g)$Name; igraph standardno koristi V(g)$name)
# U analizi ćemo držati "id" koji je ljudski čitljiv, ali NE mijenjamo nužno V(g)$name.
idE <- if ("Name" %in% vertex_attr_names(gE)) V(gE)$Name else V(gE)$name

# Odabir grupiranja za brokerage
# Najjednostavnije: koristiti pozicije koje smo već dobili (posE).
# Ako ih još nismo upisali u graf:
if (!"pos" %in% vertex_attr_names(gE)) {
  # pretpostavka: posE postoji kao vektor duljine vcount(gE)
  V(gE)$pos <- posE
}

groupsE <- as.character(V(gE)$pos)  # grupe moraju biti vektor po čvorovima

table(groupsE)
## groupsE
##  1  2  3  4  5  6 
## 86 35 24 16 16  5
# Gould–Fernandez brokerage (trijade i->b->j, ovisno o grupama)
# Pretvorba igraph -> network (iz intergraph)
edE <- igraph::as_data_frame(gE, what = "edges") %>%
  transmute(from = as.character(from),
            to   = as.character(to))

netE <- network::as.network(edE, directed = TRUE)

# brokerage() računa broj pojavljivanja aktera kao:
# coordinator, gatekeeper, representative, liaison, (i često "itinerant"/"consultant" ovisno o implementaciji)
# Tipično se koristi directed=TRUE ako je mreža usmjerena.
brE <- sna::brokerage(netE, cl = groupsE)

# brE je objekt s tablicama po ulogama (ovisno o verziji sna).
str(brE)
## List of 14
##  $ raw.nli: num [1:182, 1:6] 1 38 9 1 36 0 11 17 4 28 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:182] "1" "2" "3" "4" ...
##   .. ..$ : chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ exp.nli: num [1:182, 1:6] 54.16 54.16 54.16 54.16 8.51 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:182] "1" "2" "3" "4" ...
##   .. ..$ : chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ sd.nli : num [1:182, 1:6] 27.06 27.06 27.06 27.06 7.04 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:182] "1" "2" "3" "4" ...
##   .. ..$ : chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ z.nli  : num [1:182, 1:6] -1.965 -0.597 -1.669 -1.965 3.905 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:182] "1" "2" "3" "4" ...
##   .. ..$ : chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ raw.gli: Named num [1:6] 3368 7604 7593 7403 17588 ...
##   ..- attr(*, "names")= chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ exp.gli: Named num [1:6] 5100 7944 7944 7944 16052 ...
##   ..- attr(*, "names")= chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ sd.gli : Named num [1:6] 338 357 340 340 674 ...
##   ..- attr(*, "names")= chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ z.gli  : Named num [1:6] -5.121 -0.952 -1.031 -1.59 2.279 ...
##   ..- attr(*, "names")= chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ exp.grp: num [1:6, 1:6] 54.16 8.51 3.84 1.59 1.59 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:6] "1" "2" "3" "4" ...
##   .. ..$ : chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ sd.grp : num [1:6, 1:6] 27.06 7.04 4 2.17 2.17 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:6] "1" "2" "3" "4" ...
##   .. ..$ : chr [1:6] "w_I" "w_O" "b_IO" "b_OI" ...
##  $ cl     : chr [1:182] "1" "1" "1" "1" ...
##  $ clid   : chr [1:6] "1" "2" "3" "4" ...
##  $ n      : num [1:6] 86 35 24 16 16 5
##  $ N      : num 182
##  - attr(*, "class")= chr "brokerage"
# node-level brokerage counts (po akteru)
brE_df <- data.frame(
  id    = idE,
  group = groupsE,
  brE$raw.nli,
  row.names = NULL,
  check.names = FALSE
)

head(brE_df)
##                 id group w_I w_O b_IO b_OI b_O   t
## 1    Albert Meyers     1   1   1    3    2   1   8
## 2    Thomas Martin     1  38   2   23   35  20 118
## 3      Andrea Ring     1   9  12    9   21  11  62
## 4     Andrew Lewis     1   1   1    1    3   1   7
## 5      Andy Zipper     2  36  64  101  117 235 553
## 6 Jeffrey Shankman     3   0  15    5    9  27  56
brE_df <- dplyr::rename(
  brE_df,
  coordinator   = w_I,
  gatekeeper    = w_O,
  representative= b_IO,
  liaison       = b_OI
)

# top 10 koordinatora / gatekeepera / predstavnika / liaison
brE_df %>% dplyr::arrange(dplyr::desc(coordinator)) %>% head(10)
##              id group coordinator gatekeeper representative liaison  b_O    t
## 1            NA     1         411        312            752     712  920 3107
## 2   John Forney     1         358         90            369     448  359 1624
## 3            NA     2         253       1026            950     771 1798 4798
## 4    Kate Symes     1         178         70            212     253  200  913
## 5            NA     1         147         57            135     209  131  679
## 6    Joe Quenet     1         125         77            184     248  266  900
## 7            NA     1         122         59            230     153  218  782
## 8  Andrew Lewis     1          90         15             71     144   70  390
## 9   Mike Carson     1          71          6             61      37   26  201
## 10 Don Baughman     1          68         13             46      49   10  186
brE_df %>% dplyr::arrange(dplyr::desc(gatekeeper))  %>% head(10)
##                id group coordinator gatekeeper representative liaison  b_O    t
## 1              NA     2         253       1026            950     771 1798 4798
## 2    Rod Hayslett     4           0        491             31      30  856 1408
## 3        Rick Buy     3          40        424            232     260  923 1879
## 4              NA     1         411        312            752     712  920 3107
## 5   Stacy Dickson     5           4        250             98      57  543  952
## 6     Jason Wolfe     2          21        191            108      92  226  638
## 7  David Delainey     3           8        178            130      48  384  748
## 8  Barry Tycholiz     2          11        167             76      75  384  713
## 9    Gerald Nemec     5           1        163             49      21  304  538
## 10             NA     3          10        162             76      86  312  646
brE_df %>% dplyr::arrange(dplyr::desc(representative)) %>% head(10)
##                id group coordinator gatekeeper representative liaison  b_O    t
## 1              NA     2         253       1026            950     771 1798 4798
## 2              NA     1         411        312            752     712  920 3107
## 3     John Forney     1         358         90            369     448  359 1624
## 4     Randall Gay     2          51        153            304     115  473 1096
## 5        Rick Buy     3          40        424            232     260  923 1879
## 6              NA     1         122         59            230     153  218  782
## 7      Kate Symes     1         178         70            212     253  200  913
## 8      Joe Quenet     1         125         77            184     248  266  900
## 9              NA     1         147         57            135     209  131  679
## 10 David Delainey     3           8        178            130      48  384  748
brE_df %>% dplyr::arrange(dplyr::desc(liaison)) %>% head(10)
##              id group coordinator gatekeeper representative liaison  b_O    t
## 1            NA     2         253       1026            950     771 1798 4798
## 2            NA     1         411        312            752     712  920 3107
## 3   John Forney     1         358         90            369     448  359 1624
## 4      Rick Buy     3          40        424            232     260  923 1879
## 5    Kate Symes     1         178         70            212     253  200  913
## 6    Joe Quenet     1         125         77            184     248  266  900
## 7            NA     1         147         57            135     209  131  679
## 8            NA     1         122         59            230     153  218  782
## 9  Andrew Lewis     1          90         15             71     144   70  390
## 10  Andy Zipper     2          36         64            101     117  235  553

Iščitavanje:

  • coordinator: posreduje unutar iste grupe (g(i)=g(b)=g(j)) -> “unutarnja koordinacija”
  • gatekeeper: izvana -> u svoju grupu (g(i)≠g(b)=g(j)) -> “kontrola ulaza”
  • representative: iz svoje grupe -> van (g(i)=g(b)≠g(j)) -> “glas prema van”
  • liaison: između dvije različite grupe, broker je “treći” (g(i)≠g(b)≠g(j), g(i)≠g(j)) -> “posredovanje među blokovima”

Tumačenje:

Ulogama posredovanja (Gould–Fernandez brokerage) dobiva se druga dimenzija strukture: akteri se pojavljuju kao brokeri u trijadama i→b→j ovisno o tome pripadaju li isti ili različitim pozicijama. Visoke vrijednosti koordinatora impliciraju snažno posredovanje unutar iste pozicije (intra-blok koordinacija), dok visoki gatekeeper i representative ukazuju na kontrolu “granica” pozicije, tj. na čvorove kroz koje ulaze ili izlaze relacije između pozicija. U Enronu su u vrhovima lista prisutni i nedostajući identifikatori (“NA”), što je analitički važan signal o kvaliteti metapodataka: ti čvorovi mogu biti tehničke adrese, liste, ili zapisi bez imena, pa njihovu interpretaciju kao “osoba” treba ograničiti. Unatoč tome, raspodjela brokerstva po pozicijama je informativna jer pokazuje da određene pozicije nose nesrazmjeran dio međublok posredovanja, što je tipično za komunikacijske mreže gdje mali broj aktera ili adresa stabilno kanalizira razmjenu među segmentima organizacije.

# HITS: authority i hub (igraph)
hitsE_auth <- igraph::authority_score(gE)$vector
hitsE_hub  <- igraph::hub_score(gE)$vector

V(gE)$hits_auth <- hitsE_auth
V(gE)$hits_hub  <- hitsE_hub

# Top autoriteti i top hubovi
E_auth_top <- head(order(hitsE_auth, decreasing = TRUE), 10)
E_hub_top  <- head(order(hitsE_hub,  decreasing = TRUE), 10)

data.frame(id = idE[E_auth_top], group = groupsE[E_auth_top], auth = hitsE_auth[E_auth_top])
##                 id group      auth
## 1    John Lavorato     6 1.0000000
## 2   Louise Kitchen     6 0.9420741
## 3     Greg Whalley     3 0.7995592
## 4       Scott Neal     2 0.7584562
## 5  Michael Grigsby     2 0.7202247
## 6   David Delainey     3 0.7065892
## 7      John Arnold     2 0.6631496
## 8      Andy Zipper     2 0.6156507
## 9      Steven Kean     3 0.6130554
## 10        Rick Buy     3 0.6098001
data.frame(id = idE[E_hub_top],  group = groupsE[E_hub_top],  hub  = hitsE_hub[E_hub_top])
##                 id group       hub
## 1    John Lavorato     6 1.0000000
## 2               NA     6 0.9155274
## 3   Louise Kitchen     6 0.8655132
## 4       Sally Beck     6 0.8401255
## 5      Kenneth Lay     6 0.6278173
## 6    Jeff Dasovich     3 0.5177157
## 7   David Delainey     3 0.4957444
## 8  Michael Grigsby     2 0.4808434
## 9      John Arnold     2 0.4721971
## 10      Scott Neal     2 0.4402708
# HITS po grupama (pozicijska interpretacija)
# Prosječni autoritet/hub unutar pozicija
aggregate(hitsE_auth, by = list(group = groupsE), FUN = mean)
##   group         x
## 1     1 0.1760920
## 2     2 0.3645630
## 3     3 0.4857725
## 4     4 0.2011937
## 5     5 0.2563166
## 6     6 0.6842747
aggregate(hitsE_hub,  by = list(group = groupsE), FUN = mean)
##   group          x
## 1     1 0.06975407
## 2     2 0.21439695
## 3     3 0.33912847
## 4     4 0.12893044
## 5     5 0.19797428
## 6     6 0.84979670

HITS (authority i hub) u Enronu jasno diferencira pozicije: prosječni authority i hub najviši su u jednoj poziciji (grupa 6), što je kompatibilno s interpretacijom te pozicije kao strukturne “jezgre” informacijske validacije i distribucije. Autoriteti su čvorovi na koje “pokazuju” hubovi, pa visoke authority vrijednosti sugeriraju da su ti akteri česte mete komunikacije onih koji puno šalju; visoki hubovi, obratno, sugeriraju čvorove koji intenzivno upućuju prema autoritetima. U komunikacijskom kontekstu to se može čitati kao kombinacija prestiža (primanje) i kapaciteta za usmjeravanje ili koordinaciju (slanje prema relevantnima), pri čemu se sadržaj komunikacije ne pretpostavlja, nego se zaključuje isključivo iz topologije usmjerenih veza.



Unipu

gU <- g_weak_giant

idU <- V(gU)$name  # UNIPU ima anonimizirani ID u "name"

# Grupa A: "formalno" (sastavnica nastavnika)
# (Napomena: kod vas sastavnica nastavnika je atribut čvora: V(gU)$sast_nast)
groupsU_formal <- as.character(V(gU)$sast_nast)
groupsU_formal[is.na(groupsU_formal) | groupsU_formal == ""] <- "vanjski"
table(groupsU_formal)
## groupsU_formal
##         fet        ffpu        fipu fipu | tfpu        fooz         fpz 
##          37          48          15           1          23           7 
##        mapu        mfpu        tfpu     vanjski 
##           8          10          10         185
# Grupa B: "po kompetenciji/stručnosti" (pozicije iz strukturne sličnosti)
# Ako posU već postoji:
if (!"pos" %in% vertex_attr_names(gU)) {
  # pretpostavka: posU postoji kao vektor duljine vcount(gU)
  V(gU)$pos <- posU
}
groupsU_pos <- as.character(V(gU)$pos)
table(groupsU_pos)
## groupsU_pos
##   1   2   3   4   5   6   7   8 
##  33 242  15  24  18   4   1   7
# Gould–Fernandez brokerage (trijade i->b->j, ovisno o grupama)
# Pretvorba igraph -> network (iz intergraph)
edU <- igraph::as_data_frame(gU, what = "edges") %>%
  transmute(from = as.character(from),
            to   = as.character(to))

netU <- network::as.network(edU, directed = TRUE)

# 3a) brokerage prema sastavnicama (formalna podjela)
brU_formal <- sna::brokerage(netU, cl = groupsU_formal)

brU_df <- data.frame(
  id    = idU,
  group = groupsU_formal,
  brU_formal$raw.nli,
  row.names = NULL,
  check.names = FALSE
)

brU_df <- dplyr::rename(
  brU_df,
  coordinator   = w_I,
  gatekeeper    = w_O,
  representative= b_IO,
  liaison       = b_OI
)

# top 10 koordinatora / gatekeepera / predstavnika / liaison
brU_df %>% dplyr::arrange(dplyr::desc(coordinator)) %>% head(10)
##     id group coordinator gatekeeper representative liaison b_O   t
## 1  110  ffpu         166         38             95     121  14 434
## 2  223  ffpu         123         36             75      84   0 318
## 3  075   fet         111         38             69      91   8 317
## 4  052   fet         111         47             69     114  10 351
## 5  328   fet         106         31             51      85   8 281
## 6  142   fet          82         54            202     177 120 635
## 7  353  ffpu          82         14             42      33   0 171
## 8  273  ffpu          81          0             12      12   0 105
## 9  026  ffpu          81          4             16      24   0 125
## 10 127   fet          73         16             50      29   4 172
brU_df %>% dplyr::arrange(dplyr::desc(gatekeeper))  %>% head(10)
##     id   group coordinator gatekeeper representative liaison b_O   t
## 1  210    tfpu           7        163             47      42  25 284
## 2  247     fet           0        156            142     160  30 488
## 3  045    tfpu           3        139             35      32  24 233
## 4  225     fet          28        116            243     199 148 734
## 5  069    mfpu          19         94             70      70  62 315
## 6  181 vanjski           0         71             13      13   8 105
## 7  346 vanjski          33         68             65      58   0 224
## 8  029    mfpu          13         67             42      33  25 180
## 9  185    tfpu           3         67             15      11   0  96
## 10 204    fooz          34         65             63     120 105 387
brU_df %>% dplyr::arrange(dplyr::desc(representative)) %>% head(10)
##     id   group coordinator gatekeeper representative liaison b_O   t
## 1  225     fet          28        116            243     199 148 734
## 2  142     fet          82         54            202     177 120 635
## 3  058    fipu           5         34            154       3  88 284
## 4  247     fet           0        156            142     160  30 488
## 5  110    ffpu         166         38             95     121  14 434
## 6  223    ffpu         123         36             75      84   0 318
## 7  069    mfpu          19         94             70      70  62 315
## 8  075     fet         111         38             69      91   8 317
## 9  052     fet         111         47             69     114  10 351
## 10 214 vanjski          38          0             66      44   0 148
brU_df %>% dplyr::arrange(dplyr::desc(liaison)) %>% head(10)
##     id group coordinator gatekeeper representative liaison b_O   t
## 1  225   fet          28        116            243     199 148 734
## 2  142   fet          82         54            202     177 120 635
## 3  247   fet           0        156            142     160  30 488
## 4  110  ffpu         166         38             95     121  14 434
## 5  204  fooz          34         65             63     120 105 387
## 6  052   fet         111         47             69     114  10 351
## 7  208   fet          28         48             66     105  34 281
## 8  075   fet         111         38             69      91   8 317
## 9  328   fet         106         31             51      85   8 281
## 10 223  ffpu         123         36             75      84   0 318
# 3b) brokerage prema pozicijama (kompetencijsko/stručno grupiranje)
brU_pos <- sna::brokerage(netU, cl = groupsU_pos)

brU_df <- data.frame(
  id    = idU,
  group = groupsU_formal,
  brU_pos$raw.nli,
  row.names = NULL,
  check.names = FALSE
)

brU_df <- dplyr::rename(
  brU_df,
  coordinator   = w_I,
  gatekeeper    = w_O,
  representative= b_IO,
  liaison       = b_OI
)

# top 10 koordinatora / gatekeepera / predstavnika / liaison
brU_df %>% dplyr::arrange(dplyr::desc(coordinator)) %>% head(10)
##     id group coordinator gatekeeper representative liaison b_O   t
## 1  119  ffpu         154          1             11      55   0 221
## 2  309  ffpu         153          0              0       0   0 153
## 3  224  ffpu         153          0              0      23   0 176
## 4  109  ffpu         120          2             41      42   0 205
## 5  307  fipu         114          0             27      16   2 159
## 6  179  fooz          70          0             11       5   0  86
## 7  089   fpz          65          0              5       7   0  77
## 8  314  ffpu          62          0              6       0   0  68
## 9  269  ffpu          45          6             37      28   8 124
## 10 087  ffpu          44          0              0       0   0  44
brU_df %>% dplyr::arrange(dplyr::desc(gatekeeper))  %>% head(10)
##     id   group coordinator gatekeeper representative liaison b_O   t
## 1  069    mfpu           0        196             44      43  32 315
## 2  029    mfpu           0        132             23      25   0 180
## 3  210    tfpu           0         88              0       0 196 284
## 4  225     fet          38         59            344     280  13 734
## 5  223    ffpu           0         54            134     130   0 318
## 6  110    ffpu          27         49            131     214  13 434
## 7  204    fooz           0         47             99     195  46 387
## 8  348 vanjski           0         35              9       8   0  52
## 9  154 vanjski           0         30              9       7   0  46
## 10 247     fet           0         28            210     237  13 488
brU_df %>% dplyr::arrange(dplyr::desc(representative)) %>% head(10)
##     id   group coordinator gatekeeper representative liaison b_O   t
## 1  225     fet          38         59            344     280  13 734
## 2  142     fet           0         26            310     275  24 635
## 3  247     fet           0         28            210     237  13 488
## 4  223    ffpu           0         54            134     130   0 318
## 5  110    ffpu          27         49            131     214  13 434
## 6  075     fet          38         12            118     149   0 317
## 7  052     fet          38         18            118     177   0 351
## 8  068 vanjski           0          0            108      90   0 198
## 9  346 vanjski           0         25            103      96   0 224
## 10 026    ffpu           0         22            100       3   0 125
brU_df %>% dplyr::arrange(dplyr::desc(liaison)) %>% head(10)
##     id group coordinator gatekeeper representative liaison b_O   t
## 1  225   fet          38         59            344     280  13 734
## 2  142   fet           0         26            310     275  24 635
## 3  058  fipu           0          6             31     247   0 284
## 4  247   fet           0         28            210     237  13 488
## 5  110  ffpu          27         49            131     214  13 434
## 6  204  fooz           0         47             99     195  46 387
## 7  328   fet           0         11             90     180   0 281
## 8  052   fet          38         18            118     177   0 351
## 9  075   fet          38         12            118     149   0 317
## 10 208   fet          38          6             87     146   4 281

Brokerage analiza na UNIPU-u je posebno osjetljiva na odabir grupiranja, pa je smisleno računati ju i prema formalnim sastavnicama i prema pozicijama. Kada se grupe definiraju formalno (sastavnice), visoke vrijednosti gatekeepera i representative tipično identificiraju aktere koji strukturirano povezuju svoju sastavnicu s ostatkom sustava; u ovom kontekstu to su potencijalni koordinatori suradnje “preko granica” organizacijskih jedinica. Kada se grupe definiraju pozicijski (posU), brokerstvo hvata posredovanje između kompetencijskih/strukturnih blokova, pa se u vrhovima pojavljuju akteri koji nisu nužno formalno na “granici” sastavnice, nego su strukturno u ulozi spajanja tipova angažmana. U oba slučaja, činjenica da se vrhovi liaison uloga poklapaju s visokim representative vrijednostima sugerira da se ključni posrednici pojavljuju i kao “glas” vlastite skupine prema van i kao međublok posrednici u širem smislu.

# HITS na UNIPU (authority/hub)
hitsU_auth <- igraph::authority_score(gU)$vector
hitsU_hub  <- igraph::hub_score(gU)$vector

V(gU)$hits_auth <- hitsU_auth
V(gU)$hits_hub  <- hitsU_hub

# Top autoriteti / hubovi
U_auth_top <- head(order(hitsU_auth, decreasing = TRUE), 10)
U_hub_top  <- head(order(hitsU_hub,  decreasing = TRUE), 10)

data.frame(id = idU[U_auth_top], sastavnica = groupsU_formal[U_auth_top], auth = hitsU_auth[U_auth_top])
##      id sastavnica      auth
## 274 274        fet 1.0000000
## 181 181    vanjski 0.8969055
## 165 165        fet 0.8793509
## 208 208        fet 0.7662269
## 011 011        fet 0.7346762
## 114 114    vanjski 0.7278885
## 170 170        fet 0.6717632
## 159 159    vanjski 0.6500824
## 334 334        fet 0.6256583
## 293 293    vanjski 0.6228406
data.frame(id = idU[U_hub_top],  sastavnica = groupsU_formal[U_hub_top], hub  = hitsU_hub[U_hub_top])
##      id sastavnica       hub
## 274 274        fet 1.0000000
## 165 165        fet 0.9878248
## 181 181    vanjski 0.9275276
## 001 001        fet 0.8232420
## 208 208        fet 0.7949074
## 011 011        fet 0.7685031
## 114 114    vanjski 0.7600358
## 170 170        fet 0.7495497
## 159 159    vanjski 0.7049028
## 064 064        fet 0.6783699
# HITS po pozicijama (kompetencijska/stručna perspektiva)
aggregate(hitsU_auth, by = list(pos = groupsU_pos), FUN = mean)
##   pos            x
## 1   1 0.5147529558
## 2   2 0.0074871816
## 3   3 0.0059103476
## 4   4 0.0020530311
## 5   5 0.0030780623
## 6   6 0.0003245411
## 7   7 0.0243641543
## 8   8 0.0005416359
aggregate(hitsU_hub,  by = list(pos = groupsU_pos), FUN = mean)
##   pos            x
## 1   1 0.5571718298
## 2   2 0.0101791510
## 3   3 0.0069018515
## 4   4 0.0022732618
## 5   5 0.0032128644
## 6   6 0.0003116144
## 7   7 0.0127719886
## 8   8 0.0003395191

HITS u UNIPU mreži pokazuje izrazitu koncentraciju authority/hub vrijednosti u malom broju čvorova i u jednoj poziciji: prosječne vrijednosti po pozicijama sugeriraju da je jedna pozicija daleko iznad ostalih po oba indeksa. U usmjerenim mrežama HITS često izdvaja “čvorišta” (hubove) koja upućuju prema istaknutim akterima (autoritetima), i “autoritet” čvorove koji primaju veze od relevantnih hubova. U UNIPU kontekstu, to se može interpretirati kao strukturno izdvajanje aktera koji su istovremeno intenzivno uključeni u relacije prema mnogima i centralni kao mete relacija, što je kompatibilno s ulogama visokog koordinacijskog opterećenja ili formalne odgovornosti, ali sama mjera ne razlučuje je li to posljedica formalne hijerarhije ili organizacijskog “hubiranja” suradnje. Prosjeci po sastavnicama dodatno sugeriraju da određene sastavnice nose veći dio te HITS strukture, dok kategorija “vanjski” ima nenultu prosječnu vrijednost, što je indikativno za vanjske aktere koji su uvezani s ključnim internim čvorovima.

# HITS po sastavnicama (formalna perspektiva)
aggregate(hitsU_auth, by = list(sast = groupsU_formal), FUN = mean)
##           sast            x
## 1          fet 3.490858e-01
## 2         ffpu 2.925704e-03
## 3         fipu 5.462054e-02
## 4  fipu | tfpu 7.691712e-04
## 5         fooz 1.901050e-03
## 6          fpz 4.080607e-04
## 7         mapu 1.219846e-05
## 8         mfpu 1.974417e-04
## 9         tfpu 8.583086e-03
## 10     vanjski 2.708304e-02
aggregate(hitsU_hub,  by = list(sast = groupsU_formal), FUN = mean)
##           sast            x
## 1          fet 3.845853e-01
## 2         ffpu 3.221966e-03
## 3         fipu 6.369243e-02
## 4  fipu | tfpu 9.480458e-04
## 5         fooz 1.919989e-03
## 6          fpz 4.232417e-04
## 7         mapu 2.578121e-05
## 8         mfpu 2.037721e-04
## 9         tfpu 8.384622e-03
## 10     vanjski 3.031610e-02

U oba sustava, visoka recipročnost i dominantne jake komponente znače da “hijerarhija” u strogo DAG smislu nije empirijski adekvatan opis, pa je kondenzacija u DAG najprimjereniji kompromis: hijerarhiju je smislenije promatrati kao odnos među cikličkim blokovima nego među pojedinačnim akterima. Enron pritom pokazuje grublju makro-strukturu (malo SCC blokova), dok UNIPU pokazuje razgranatiju kondenziranu strukturu (više blokova), što je kompatibilno s institucionalno segmentiranijim sustavom. Krackhardtova hijerarhija je niska u oba slučaja, ali je UNIPU ekstremniji primjer zbog gotovo potpune recipročnosti, dok Enron zadržava nešto više asimetrije i time nešto više “vertikalnog signala”, iako još uvijek daleko od idealne hijerarhije.






Empirijski primjeri iz prakse i njihova korisnost

  • World Wide Web (Web pretraživanje): Ovo je izvorna primjena algoritma. Web stranice dobivaju visoke ocjene kao hubovi ako upućuju na relevantne autoritete (poput Wikipedije), što je ključno za poboljšanje algoritama pretraživanja i rangiranja informacija.
  • Svjetska turistička mreža: Analiza (podaci iz 2018.) koristi HITS za razlikovanje tranzitnih zemalja i krajnjih destinacija.
  • Ekosustav R paketa: U usmjerenoj mreži ovisnosti, određeni paketi (npr. stats, rlang, utils) djeluju kao infrastrukturni autoriteti.
    • R paketi: Identificiranje “temeljnih” paketa o kojima ovisi cijeli sustav. Analiza pokazuje da bi kvar tih “hubova” uzrokovao krah velikog dijela ekosustava zbog kaskadnih ovisnosti.
  • Zrakoplovne mreže: Velike zračne luke (npr. Chicago ili Los Angeles) djeluju kao hubovi koji povezuju mnoštvo manjih zračnih luka. Ovakav model omogućuje zrakoplovnim kompanijama optimizaciju ruta putem hub-and-spoke modela, smanjujući operativne troškove uz zadržavanje globalne dostižnosti.
  • Citatne mreže: Razlikuju se pregledni radovi koji sintetiziraju i upućuju na ključnu literaturu (hubovi) od radova koji su sami postali temeljne reference (autoriteti). Citatne mreže pomažu istraživačima u brzoj identifikaciji najrelevantnije literature u novim znanstvenim poljima.





Phase transition i nastanak pozicija

U prethodnim lekcijama prijelaz faze (phase transition) analiziran je kao globalni fenomen rasta mreže: u modelima tipa Erdős–Rényi, pri povećanju vjerojatnosti veze \(p\) dolazi do nagle promjene strukture kada se pojavi gigantska komponenta. U ovom poglavlju taj koncept reinterpretiramo iz perspektive pozicija i uloga. Ključno pitanje glasi: kada i kako mreža počinje generirati stabilne strukturne pozicije?



Prijelaz faze kao strukturni prag

U nasumičnoj mreži s \(n\) čvorova i vjerojatnošću veze \(p\), očekivani broj veza iznosi približno:

\[ m \approx \frac{n(n-1)}{2} p. \]

Ključni parametar je očekivani stupanj:

\[ \langle k \rangle = p(n-1). \]

Kada vrijedi:

\[ \langle k \rangle \approx 1, \]

dolazi do kritične točke u kojoj se mala, fragmentirana komponentna struktura transformira u sustav s jednom dominantnom komponentom. Ovaj nagli kvalitativni skok naziva se prijelaz faze.


Do tog trenutka mreža je skup izoliranih ili slabo povezanih klastera; nakon prijelaza, većina čvorova postaje dio iste relacijske cjeline.



Od povezanosti do diferencijacije

Za pozicijsku analizu ključno je sljedeće: pozicije postaju stabilne tek kada mreža ima dovoljno relacijskog materijala. U izrazito rijetkim mrežama nema dovoljno strukture da bi se razvile diferencirane uloge. Veze su sporadične i ne generiraju sustavne obrasce.

Tek nakon prelaska kritične gustoće pojavljuju se:

  • stabilne razlike u stupnjevima,
  • koncentracija veza u određenim dijelovima,
  • početci jezgre,
  • formiranje mostova između podskupina.

Drugim riječima, prijelaz faze ne stvara samo povezanost, nego omogućuje nastanak strukturne nejednakosti.

U modelima preferencijalnog povezivanja (Barabási–Albert), novi čvorovi imaju veću vjerojatnost povezivanja s već povezanima. Time se spontano formiraju hubovi, a mreža poprima skalno-slobodnu distribuciju stupnjeva.

Ovaj proces vodi diferencijaciji pozicija:

  • Akteri s visokim stupnjem postaju jezgra.
  • Manje povezani čvorovi ostaju na periferiji.
  • Neki čvorovi zauzimaju brokerske položaje između klastera.

Pozicije ovdje nisu unaprijed zadane, nego emergentne — nastaju iz lokalnih pravila rasta.

Regularna ekvivalencija podrazumijeva postojanje stabilnih tipova odnosa (npr. nadređeni–podređeni, proizvođač–potrošač). Takva struktura zahtijeva dovoljnu gustoću i rekurzivnost odnosa.

Ako mreža nije prešla prag povezanosti, rekurzivna definicija regularne ekvivalencije nema empirijsku podlogu, jer nema stabilnih klasa aktera. Nakon prijelaza faze, međutim, formiraju se obrasci koji omogućuju grupiranje u blokove i identifikaciju uloga.

Stoga se može reći:

Phase transition je uvjet mogućnosti pozicijske diferencijacije.

U usmjerenim mrežama povećanje gustoće može dovesti do pojave acikličnih dominacijskih struktura ili, suprotno, do povećanja reciprociteta i cikličnosti. U ranoj fazi mreže teško je govoriti o hijerarhiji jer nema dovoljno relacija da bi se formirala jasna vertikalna struktura.

Tek kada mreža postane dovoljno povezana:

  • pojavljuju se razine,
  • diferenciraju se autoriteti i hubovi,
  • stabiliziraju se brokerske uloge.

Hijerarhija je stoga sekundarni fenomen — rezultat kumulativnog rasta i reorganizacije mreže nakon kritične točke.

Prijelaz faze naglašava da pozicije nisu statične. Kako mreža raste ili gubi veze:

  • pozicije se mogu konsolidirati,
  • brokerske uloge mogu nestati ako se zatvore strukturne rupe,
  • jezgra se može fragmentirati,
  • hijerarhija se može izravnati ili zaoštriti.

Pozicijska analiza stoga nije samo statička klasifikacija, nego snimka sustava u određenom trenutku razvoja.



Primjer

Za ilustraciju, koristimo prikaz kroz rast Erdős–Rényi mreže tako da dodajemo bridove jedan po jedan (prijelaz faze oko \(⟨k⟩≈1\)).Ideja: dok je ⟨k⟩ < 1 mreža je fragmentirana; kako se ⟨k⟩ približava 1, naglo raste najveća komponenta. Nakon toga često raste i “strukturni signal” (npr. modularnost), pa zajednice/pozicije postaju stabilnije.

set.seed(1)

# Parametri
n <- 120                 # broj čvorova
m_max <- 400             # koliko bridova ukupno dodajemo
snap_at <- c(seq(1, 9, by = 1), seq(10, 49, by = 10), seq(50, 149, by= 20), seq(150, m_max, by = 50))

# (1) pripremimo sve moguće bridove (neusmjereno, bez self-loop)
all_pairs <- t(combn(seq_len(n), 2))
all_pairs <- all_pairs[sample(nrow(all_pairs)), ]   # random redoslijed

# (2) inicijalni graf (bez bridova)
g <- make_empty_graph(n = n, directed = FALSE)
lay <- layout_with_fr(g)  # fiksiramo layout radi usporedbe kroz vrijeme

# pomoćne "minimalne" metrike po snimci
get_stats <- function(g) {
  # prosječni stupanj
  k_avg <- mean(igraph::degree(g))

  # udio najveće komponente
  comp <- igraph::components(g)
  giant_share <- max(comp$csize) / igraph::vcount(g)

  # modularnost (na neusmjerenoj mreži)
  if (igraph::ecount(g) == 0) {
    mod <- NA_real_
    n_comm <- NA_integer_
  } else {
    comm <- igraph::cluster_louvain(g)
    mod <- igraph::modularity(comm)
    n_comm <- length(igraph::sizes(comm))
  }

  c(k_avg = k_avg, giant_share = giant_share, modularity = mod, n_comm = n_comm)
}

stats <- data.frame(m = integer(), k_avg = double(), giant_share = double(),
                    modularity = double(), n_comm = integer())
# za sličan grafički prikaz onome iz animacije ispod
for (m in 1:m_max) {
  # dodajemo po 1 brid
  e <- all_pairs[m, ]
  g <- add_edges(g, c(e[1], e[2]))
  
  # ako je m snimka
  if (m %in% snap_at) {
    s <- get_stats(g)
    stats <- rbind(stats, data.frame(m = m, t(s)))
    
    # obojaj najveću komponentu (vizualni “klik” prijelaza faze)
    comp <- igraph::components(g)
    giant_id <- which.max(comp$csize)
    col_v <- ifelse(comp$membership == giant_id, "black", "grey80")
    
    frame_i <- frame_i + 1
    fn <- sprintf("frames_ge/frame_%03d.png", frame_i)
    png(fn, width = 1200, height = 800, res = 150)
    
    plot(g,
         layout = lay,
         vertex.size = 4,
         vertex.label = NA,
         vertex.color = col_v,
         edge.color = "grey70",
         main = paste0("m = ", m,
                       " | <k> = ", round(s["k_avg"], 2),
                       "\nGiant_comp_udio = ", round(s["giant_share"], 2)))
    dev.off()
  }
}

par(mfrow = c(1, 2))

plot(stats$m, stats$giant_share, type = "b", pch = 16,
     xlab = "broj bridova m", ylab = "udio najveće komponente",
     main = "Phase transition: nastanak gigantske komponente")

plot(stats$m, stats$modularity, type = "b", pch = 16,
     xlab = "broj bridova m", ylab = "modularnost (Louvain)",
     main = "Signal pozicija: modularnost zajednica")

  • U ranim snimkama vidimo mali broj izoliranih klastera; “crna” boja (najveća komponenta) zauzima mali dio čvorova.
  • Kako ⟨k⟩ raste prema 1, pojavljuje se nagla promjena: jedna komponenta “proguta” većinu čvorova. To je prijelaz faze.
  • Nakon prijelaza, mreža ima dovoljno relacijskog materijala da se počnu stabilizirati makro-obrasci: zajednice/pozicije i uloge (hubovi, brokeri) postaju uočljiviji.



Epistemološka implikacija

Uvođenje prijelaza faze u analizu pozicija ima važnu teorijsku implikaciju: uloge nisu inherentne osobinama aktera, nego proizlaze iz globalne konfiguracije sustava. Tek kada mreža postigne određeni stupanj kompleksnosti, moguće je govoriti o stabilnim pozicijama poput jezgre, periferije, brokera ili autoriteta.

Time se zatvara konceptualni luk ove teme:

  • lokalne veze → globalna povezanost,
  • globalna povezanost → diferencijacija pozicija,
  • diferencijacija pozicija → stabilne uloge,
  • stabilne uloge → hijerarhija i makro-arhitektura.

Phase transition tako predstavlja most između dinamike rasta i strukturne organizacije mreže — trenutak u kojem kvantitativna promjena (više veza) prelazi u kvalitativnu promjenu (nastanak društvene strukture).




Dualnost i granice modeliranja

U prethodnim poglavljima analizirali smo kako se iz relacijskih podataka mogu izdvojiti pozicije, uloge i makro-arhitektura mreže. No, svaki takav rezultat ovisi o načinu na koji je mreža konstruirana. Koncept dualnosti i problem granica mreže (boundary problem) podsjećaju nas da mrežna analiza nije neutralna reprodukcija stvarnosti, nego modeliranje određenog aspekta sustava.



Dualnost čvor–veza (Breiger)

Breiger (1974) pokazuje da društvena struktura ima dvostruku narav: akteri su povezani kroz aktivnosti, a aktivnosti su povezane kroz aktere. To znači da svaka jednopartitna mreža (npr. mreža suradnje među studentima) može biti promatrana kao projekcija dvomodalne mreže (npr. studenti–kolegiji).

Formalno, neka je \(B\) binarna matrica afilijacije dimenzija \(n \times m\), gdje redci predstavljaju aktere, a stupci događaje ili aktivnosti. Element \(b_{ik} = 1\) označava da akter \(i\) sudjeluje u aktivnosti \(k\).

Iz takve matrice moguće je konstruirati:

  • mrežu aktera:

\[ A = B B^T, \]

  • mrežu aktivnosti:

\[ C = B^T B. \]

Matrica \(A\) prikazuje koliko akteri dijele zajedničkih aktivnosti, dok \(C\) prikazuje koliko aktivnosti dijele iste sudionike. Ovdje se jasno vidi dualnost: ono što interpretiramo kao “vezu” u jednoj projekciji zapravo je posljedica zajedničkog sudjelovanja u drugoj dimenziji.


Time se postavlja ključno pitanje: jesu li pozicije svojstvo aktera ili aktivnosti? Odgovor ovisi o razini analize.

Modeliranje omogućuje:

  • identifikaciju stabilnih obrazaca,
  • redukciju kompleksnosti,
  • usporedbu različitih mreža,
  • formalno testiranje teorija o moći, hijerarhiji ili diferencijaciji.

Blokmodeliranje, primjerice, komprimira mrežu s \(n\) čvorova na \(K\) pozicija (\(K \ll n\)), čime se omogućuje uvid u makro-arhitekturu sustava. HITS diferencira autoritete i hubove; brokerage otkriva kontrolne točke; hijerarhijske mjere kvantificiraju vertikalnu strukturu.

Bez modeliranja, takve regularnosti bile bi nevidljive u mnoštvu pojedinačnih veza.

Svaka redukcija podrazumijeva gubitak informacije. Kada definiramo pozicije, implicitno pretpostavljamo da su akteri unutar iste pozicije dovoljno slični da se mogu tretirati kao klasa. Time zanemarujemo:

  • individualne motive,
  • kontekstualne atribute,
  • povijesnu dinamiku odnosa,
  • značenje same relacije.

Blokmodeliranje pretvara raznolike interakcije u agregirane gustoće. HITS sažima složene tokove u dvije numeričke vrijednosti. Hijerarhijski modeli pretpostavljaju acikličnost i jasnoću dominacije, iako stvarni sustavi često uključuju reciprocitet i pregovaranje.

Model je, dakle, apstrakcija — a apstrakcija uvijek selektira.

Jedno od najvažnijih metodoloških pitanja jest: tko je uključen u mrežu, a tko nije?

Granice se mogu definirati:

  • administrativno (npr. zaposlenici jedne organizacije),
  • relacijski (npr. svi povezani unutar dva koraka),
  • teorijski (npr. akteri relevantni za određeni proces).

Pogrešno postavljena granica može:

  • izostaviti ključne brokere,
  • umjetno povećati gustoću,
  • promijeniti distribuciju centralnosti,
  • redefinirati pozicije i uloge.

Primjerice, ako iz mreže izostavimo vanjske partnere, interna struktura može izgledati hijerarhijski, iako je u širem kontekstu horizontalno integrirana.



Projekcija i distorzija

Kod dvomodalnih mreža projekcija na jednopartitnu mrežu može proizvesti lažnu gustoću ili umjetne klastere. Ako više aktera sudjeluje u istoj velikoj aktivnosti, projekcija može stvoriti potpun blok (complete block), iako među njima ne postoji izravna interakcija.

Time dualnost pokazuje da:

  • struktura može biti artefakt projekcije,
  • pozicije mogu ovisiti o razini analize,
  • makro-arhitektura nije inherentno “u” podacima, nego u modelu.



Ontološka i epistemološka implikacija

Iz perspektive ove lekcije, najvažnija implikacija glasi:

Pozicije i uloge nisu ontološke kategorije, nego relacijski konstrukt definiran unutar određenog modela.

Hijerarhija, jezgra, broker, autoritet — sve su to interpretacije obrasca veza unutar određenih granica i pretpostavki. Promjena razine analize (npr. s aktera na događaje), promjena granice ili promjena praga gustoće može promijeniti i samu klasifikaciju.

Dualnost i granice modeliranja zatvaraju konceptualni luk ove cjeline. U početku smo se pitali zašto centralnost nije dovoljna. Zatim smo definirali ekvivalencije, pozicije, blokove, hijerarhiju i uloge. Sada uviđamo da su sve te kategorije rezultat:

  • odabira reprezentacije,
  • definicije granica,
  • izbora kriterija ekvivalencije,
  • interpretativnog okvira.

Mrežna analiza omogućuje iznimno precizno matematičko modeliranje društvene strukture, ali njezina snaga proizlazi upravo iz svijesti o vlastitim ograničenjima. Dualnost nas podsjeća da je svaka mreža istodobno i druga mreža — ovisno o tome što tretiramo kao čvor, a što kao vezu.

Time analiza pozicija i uloga postaje ne samo tehnički alat, nego i teorijski okvir za razumijevanje kako se struktura konstruira, interpretira i transformira.



Primjeri

  1. Uvijek je moguće: iz jednopartitne mreže napraviti bipartitnu čvor–brid (node–edge incidence), pa se projekcijom vratiti natrag. Ovo radi i za Enron i za Unipu, bez ikakvih dodatnih podataka.

  2. Breiger dualnost (akter–aktivnost): iz bipartitne mreže (npr. osobe–kolegiji) napraviti dvije projekcije: mrežu osoba i mrežu kolegija. To je “prava” dualnost koju opisuje (\(BB^T\)) i (\(B^T B\)). Ovo je prirodno pokazati na UNIPU, jer imamo predmet (kolegij) kao atribut.



ENRON

Osnovna ideja: svaki brid postane jedan “event-čvor”. Povežemo (\(u,v\)) s tim event-čvorom. To je bipartitni graf: (originalni čvorovi) – (brid-čvorovi). Projekcija natrag na originalne čvorove vraća originalnu mrežu (u idealnom slučaju 1:1).

library(igraph)
library(dplyr)

gE <- g_giant

# 1) Jedinstveni ID čvora:
idE <- if ("name" %in% vertex_attr_names(gE)) V(gE)$name else as.character(seq_len(vcount(gE)))

# 2) Oznaka (smije biti duplicirana): Enron Name
labE <- if ("Name" %in% vertex_attr_names(gE)) V(gE)$Name else idE
labE[labE == "NA"] <- "Unknown"   # "NA" je string, ne NA

# 3) Edgelist iz igrapha (ovdje from/to obično već odgovaraju V(gE)$name)
edE0 <- igraph::as_data_frame(gE, what = "edges") |>
  transmute(from = as.character(from), to = as.character(to)) |>
  mutate(e_id = paste0("E_", row_number()))

# Ako su from/to numerički indeksi, onda treba mapiranje na idE:
# edE0 <- edE0 |> mutate(from = idE[as.integer(from)], to = idE[as.integer(to)])

# 4) Bipartitne veze: P_<id> -- E_<edge>
bip_ed_E <- bind_rows(
  transmute(edE0, from = paste0("P_", from), to = e_id),
  transmute(edE0, from = paste0("P_", to),   to = e_id)
)

# 5) Vertex tablica: "person" + "edge-node"
V_nodes <- data.frame(
  name  = paste0("P_", idE),
  type  = FALSE,         # FALSE = person
  label = labE,          # labela smije biti duplicirana
  stringsAsFactors = FALSE
)

V_edges <- data.frame(
  name = unique(edE0$e_id),
  type = TRUE,           # TRUE = edge-node
  stringsAsFactors = FALSE
)

V_bip_E <- bind_rows(V_nodes, V_edges)
stopifnot(anyDuplicated(V_bip_E$name) == 0)

# 6) Konstrukcija bipartitnog grafa
gE_bip <- graph_from_data_frame(bip_ed_E, directed = FALSE, vertices = V_bip_E)

gE_bip
## IGRAPH 840a5cd UN-B 3192 6020 -- 
## + attr: name (v/c), type (v/l), label (v/c)
## + edges from 840a5cd (vertex names):
##  [1] P_1--E_1  P_1--E_2  P_1--E_3  P_1--E_4  P_1--E_5  P_1--E_6  P_2--E_7 
##  [8] P_2--E_8  P_2--E_9  P_2--E_10 P_2--E_11 P_2--E_12 P_2--E_13 P_2--E_14
## [15] P_2--E_15 P_2--E_16 P_2--E_17 P_3--E_18 P_3--E_19 P_3--E_20 P_3--E_21
## [22] P_3--E_22 P_3--E_23 P_3--E_24 P_3--E_25 P_3--E_26 P_3--E_27 P_3--E_28
## [29] P_4--E_29 P_4--E_30 P_4--E_31 P_5--E_32 P_5--E_33 P_5--E_34 P_5--E_35
## [36] P_5--E_36 P_5--E_37 P_5--E_38 P_5--E_39 P_5--E_40 P_5--E_41 P_5--E_42
## [43] P_5--E_43 P_5--E_44 P_5--E_45 P_5--E_46 P_5--E_47 P_5--E_48 P_5--E_49
## [50] P_5--E_50 P_5--E_51 P_5--E_52 P_5--E_53 P_5--E_54 P_5--E_55 P_5--E_56
## + ... omitted several edges
table(V(gE_bip)$type)  # koliko "person" vs "edge-nodes"
## 
## FALSE  TRUE 
##   182  3010
# 4) Projekcija natrag na "aktere" (type=FALSE)
projE <- bipartite_projection(gE_bip, which = "false")  # "false" = originalni čvorovi
projE
## IGRAPH 840c6ef UNW- 182 2097 -- 
## + attr: name (v/c), label (v/c), weight (e/n)
## + edges from 840c6ef (vertex names):
##  [1] P_1--P_10  P_1--P_21  P_1--P_49  P_1--P_91  P_1--P_104 P_1--P_151
##  [7] P_1--P_105 P_2--P_16  P_2--P_40  P_2--P_44  P_2--P_69  P_2--P_71 
## [13] P_2--P_75  P_2--P_82  P_2--P_88  P_2--P_107 P_2--P_156 P_2--P_158
## [19] P_2--P_5   P_2--P_7   P_2--P_30  P_2--P_78  P_2--P_85  P_2--P_89 
## [25] P_2--P_90  P_2--P_94  P_2--P_105 P_2--P_125 P_2--P_152 P_3--P_11 
## [31] P_3--P_18  P_3--P_44  P_3--P_51  P_3--P_88  P_3--P_138 P_3--P_143
## [37] P_3--P_153 P_3--P_155 P_3--P_156 P_3--P_165 P_3--P_60  P_3--P_78 
## [43] P_3--P_82  P_3--P_84  P_3--P_90  P_3--P_105 P_3--P_129 P_3--P_144
## + ... omitted several edges
# 5) Provjera: broj bridova bi trebao odgovarati (može biti > ako postoje multi-bridovi)
c(
  original_edges = ecount(gE),
  back_edges     = ecount(igraph::simplify(projE, remove.multiple = TRUE, remove.loops = TRUE))
)
## original_edges     back_edges 
##           3010           2097
# 6) Jedan pokazatelj: gustoća (pokazuje da se projekcijom ovdje ništa "ne napuhuje")
c(
  dens_original = edge_density(as.undirected(igraph::simplify(gE))),
  dens_back     = edge_density(as.undirected(igraph::simplify(projE)))
)
## dens_original     dens_back 
##     0.1273147     0.1273147
  • napravili smo bipartitnu mrežu tipa osoba–brid (edge-nodes).

  • kad to projeciramo natrag na “osoba–osoba”, dobijemo vezu između dvije osobe ako dijele barem jedan edge-node.

  • u edge-node konstrukciji, svaka originalna veza (\(u,v\)) stvara jedan edge-node \(E_k\) koji je spojen baš s \(u\) i \(v\). Projekcija natrag zato “zna” samo da su \(u\) i \(v\) povezani — isto kao original.

Razlika u back_edges (2097 vs 3010) dolazi od ovoga:

  • originalni gE je usmjeren i može imati oba smjera \(u→v\) i \(v→u\) kao dva različita brida.

  • Kad smo računali gustoću, koristili smo as.undirected(simplify(...)), pa se ti parovi spajaju u jednu neusmjerenu vezu.

  • Zato projekcija (koja po prirodi označava “barem jedan odnos između \(u\) i \(v\)”) završi s istim skupom neusmjerenih parova kao i as.undirected(simplify(gE)).

Drugim riječima: edge-node dual je u ovom smislu gotovo “bez gubitka” kad se vratimo na neusmjereni simple graf.



UNIPU

library(igraph)
library(dplyr)

gU <- g_weak_giant

edU <- igraph::as_data_frame(gU, what = "edges") |>
  transmute(from = as.character(from),
            to   = as.character(to),
            e_id = paste0("e", row_number()))

V_nodes <- data.frame(name = V(gU)$name, type = FALSE)
V_edges <- data.frame(name = edU$e_id,   type = TRUE)
V_bip_U <- bind_rows(V_nodes, V_edges)

bip_ed_U <- bind_rows(
  transmute(edU, from = from, to = e_id),
  transmute(edU, from = to,   to = e_id)
)

gU_bip <- graph_from_data_frame(bip_ed_U, directed = FALSE, vertices = V_bip_U)

projU <- bipartite_projection(gU_bip, which = "false")
gU_back <- projU

c(
  original_edges = ecount(gU),
  back_edges     = ecount(igraph::simplify(gU_back, remove.multiple = TRUE, remove.loops = TRUE))
)
## original_edges     back_edges 
##           3148           1697
c(
  dens_original = edge_density(as.undirected(igraph::simplify(gU))),
  dens_back     = edge_density(as.undirected(igraph::simplify(gU_back)))
)
## dens_original     dens_back 
##    0.02876466    0.02876466

Zašto su gustoće iste, ali je back_edges manji?

Naš edge-node bipartitni graf kodira svaki originalni brid kao jedan “event čvor” e_id, spojen s oba kraja brida (from—e_id i to—e_id). Kad projeciramo to natrag na osobe, dvije osobe dobiju vezu ako dijele barem jedan edge-node. To u biti znači da u projekciji postoji veza između \(u\) i \(v\) ⇔ u originalu je postojao barem jedan brid između \(u\) i \(v\) (u bilo kojem smjeru).

gU je usmjeren i može imati oba smjera \(u→v\) i \(v→u\) kao dvije različite veze (a često i višestruke po paru). Projekcija iz edge-node konstrukcije daje (praktično) neusmjeren “simple” odnos “\(u\) i \(v\) su povezani barem jednom” i zbog toga dobivamo razliku u broju bridova. Odnosno, kad se radi “edge-node” bipartitizacija i povratna projekcija, koristimo transformaciju koja, uz simplify() i uklanjanje multiple/loops, može kolabirati multiplicitete i promijeniti broj bridova, ali gustoća može ostati ista jer se mijenja i broj mogućih bridova (ili se rezultat dodatno pojednostavnjuje).

Ovo je dualnost “čvor–veza” (incidencija). Ne mijenja semantiku relacije; pokazuje da je i “brid” također objekt koji se može modelirati kao čvor, ovisno o istraživačkom pitanju.

Provjera (usporedba s usmjerenom i neusmjerenom varijantom gU):

gU_simple_undir <- as.undirected(
  igraph::simplify(gU, remove.multiple = TRUE, remove.loops = TRUE),
  mode = "collapse"
)

gU_back_simple_undir <- as.undirected(
  igraph::simplify(gU_back, remove.multiple = TRUE, remove.loops = TRUE),
  mode = "collapse"
)

c(
  e_original_directed = ecount(gU),
  e_original_undir    = ecount(gU_simple_undir),
  e_back_undir        = ecount(gU_back_simple_undir)
)
## e_original_directed    e_original_undir        e_back_undir 
##                3148                1697                1697
c(
  dens_original_undir = edge_density(gU_simple_undir),
  dens_back_undir     = edge_density(gU_back_simple_undir)
)
## dens_original_undir     dens_back_undir 
##          0.02876466          0.02876466

Ova provjera potvrđuje prethodno dano objašnjenje razlike u broju bridova.


Bipartitna (osoba–kolegij) → jednopartitne projekcije (osobe i kolegiji) - Breiger: (\(A = B B^T\)), (\(C = B^T B\)); prirodno za UNIPU jer imamo predmet. Ovdje se lijepo vidi i “distorzija projekcije”: jedan kolegij s puno izvođača stvara “klik” u projekciji osoba.

Iz predmet (atribut brida) konstruirati ćemo veze osoba–kolegij.

library(igraph)
library(dplyr)

gU <- g_weak_giant

# 1) Iz bridova izvučemo "tko sudjeluje na kojem kolegiju"
#    (ako brid predstavlja odnos na kolegiju, oba kraja su sudionici tog kolegija)
edU <- igraph::as_data_frame(gU, what = "edges") |>
  transmute(from = as.character(from),
            to   = as.character(to),
            predmet = as.character(predmet))

# parovi (osoba, kolegij) iz oba kraja brida
affU <- bind_rows(
  transmute(edU, osoba = from, kolegij = predmet),
  transmute(edU, osoba = to,   kolegij = predmet)
) |>
  filter(!is.na(kolegij), kolegij != "") |>
  distinct()

# 2) Bipartitni graf osoba–kolegij
V_osoba   <- data.frame(name = sort(unique(affU$osoba)),   type = FALSE)
V_kolegij <- data.frame(name = sort(unique(affU$kolegij)), type = TRUE)
V_bip     <- bind_rows(V_osoba, V_kolegij)

gU_aff <- graph_from_data_frame(
  d = transmute(affU, from = osoba, to = kolegij),
  directed = FALSE,
  vertices = V_bip
)

# 3) Projekcije: osobe i kolegiji
proj <- bipartite_projection(gU_aff)

gU_person <- proj$proj1   # (ovisno o verziji igraph-a, ponekad je proj1 = type FALSE)
gU_course <- proj$proj2

# sigurnije: eksplicitno
gU_person <- bipartite_projection(gU_aff, which = "false")
gU_course <- bipartite_projection(gU_aff, which = "true")

# 4) Pokazatelji koji demonstriraju "napuhavanje" projekcije:
#    gustoća i prosječni stupanj
out <- rbind(
  data.frame(mreza = "bipartitna (osoba-kolegij)",
             n = vcount(gU_aff), m = ecount(gU_aff),
             density = igraph::edge_density(gU_aff),
             k_avg = mean(igraph::degree(gU_aff))),
  data.frame(mreza = "projekcija osobe-osobe",
             n = vcount(gU_person), m = ecount(gU_person),
             density = igraph::edge_density(igraph::simplify(gU_person)),
             k_avg = mean(igraph::degree(igraph::simplify(gU_person)))),
  data.frame(mreza = "projekcija kolegij-kolegij",
             n = vcount(gU_course), m = ecount(gU_course),
             density = igraph::edge_density(igraph::simplify(gU_course)),
             k_avg = mean(igraph::degree(igraph::simplify(gU_course))))
)

print(out)
##                        mreza   n    m     density     k_avg
## 1 bipartitna (osoba-kolegij) 668  996 0.004470818  2.982036
## 2     projekcija osobe-osobe 344 3801 0.064428097 22.098837
## 3 projekcija kolegij-kolegij 324 1645 0.031437526 10.154321
  1. Bipartitna mreža (osoba–kolegij)
  • n = 668 čvorova = 344 osobe + 324 kolegija

  • m = 996 afilijacijskih veza (osoba je vezana na kolegij)

  • gustoća = 0.0045 (očekivano vrlo rijetka)

  • prosječni stupanj = 2.98

U bipartitnom grafu to znači: prosječan čvor (osoba ili kolegij) ima oko 3 veze. (Nije isto kao “prosječan broj kolegija po osobi”, jer se prosjek računa preko oba tipa čvorova.)

  1. Projekcija osoba–osoba
  • n = 344 (samo osobe)

  • m = 3801, gustoća = 0.064, k_avg = 22.10

  • dvije osobe su povezane ako dijele barem jedan kolegij → to često “napuhuje” broj veza.

Prosječno je osoba povezana s ~22 druge osobe u projekciji, što je puno “gušće” iskustvo nego u originalnoj bipartitnoj reprezentaciji.

  1. Projekcija kolegij–kolegij
  • n = 324 (samo kolegiji)

  • m = 1645, gustoća = 0.031, k_avg = 10.15

  • dva kolegija su povezana ako dijele barem jednu osobu → otkriva “klastere kurikuluma” (kolegiji koji dijele nastavnike/izvođače), ali opet projekcija proizvodi dodatne veze.

Bipartitna mreža nosi “izvornu” strukturu (tko sudjeluje u čemu), a jednopartitne projekcije su model koji dodaje relacije “dijele X”, što mijenja gustoću, stupnjeve i kasnije pozicije/uloge.

# za prikaz je dobro pojednostaviti projekcije (maknuti loopove i multiple)
g_aff   <- gU_aff
g_pp    <- igraph::simplify(gU_person, remove.multiple = TRUE, remove.loops = TRUE)
g_cc    <- igraph::simplify(gU_course, remove.multiple = TRUE, remove.loops = TRUE)

# layouti (odvojeno, jer grafovi imaju različite skupove čvorova)
set.seed(1)
lay_aff <- layout_with_fr(g_aff)
lay_pp  <- layout_with_fr(g_pp)
lay_cc  <- layout_with_fr(g_cc)

# boje: bipartitno obojimo po tipu čvora, projekcije jednobojno
col_aff <- ifelse(V(g_aff)$type, "grey60", "red")  # TRUE=kolegij, FALSE=osoba

# crtanje
par(mfrow = c(1, 3), mar = c(1, 1, 3, 1))

plot(
  g_aff, layout = lay_aff,
  vertex.color = col_aff, 
  vertex.size = 3,
  vertex.label = NA, 
  edge.color = "grey80",
  main = paste0("Bipartitna (osoba–kolegij)\n",
                "n=", vcount(g_aff), ", m=", ecount(g_aff),
                ", dens=", round(edge_density(g_aff), 4))
)

plot(
  g_pp, layout = lay_pp,
  vertex.color = "grey60", 
  vertex.size = 3,
  vertex.label = NA, 
  edge.color = "grey80",
  main = paste0("Projekcija osoba–osoba\n",
                "n=", vcount(g_pp), ", m=", ecount(g_pp),
                ", dens=", round(edge_density(g_pp), 4))
)

plot(
  g_cc, layout = lay_cc,
  vertex.color = "grey60", 
  vertex.size = 3,
  vertex.label = NA, 
  edge.color = "grey80",
  main = paste0("Projekcija kolegij–kolegij\n",
                "n=", vcount(g_cc), ", m=", ecount(g_cc),
                ", dens=", round(edge_density(g_cc), 4))
)

U nastavku demonstriramo kako odluka o granici mreže (boundary problem) izravno mijenja dobivenu strukturu. U dvomodalnoj mreži osoba–kolegij, projekcija na mrežu osoba–osoba može postati umjetno gusta ako uključimo kolegije s velikim brojem sudionika (jedan “veliki” kolegij može povezati velik dio ljudi u kliku). Zato uvodimo jednostavno, ilustrativno pravilo: izbacujemo kolegije iznad odabranog praga broja sudionika i ponovno gradimo bipartitnu mrežu te projekciju. Usporedbom gustoće projekcije prije i poslije filtriranja vidimo da promjena granice (koje aktivnosti računamo kao relevantne) mijenja gustoću, potencijalne klastere i posljedično i interpretaciju “pozicija”.

library(dplyr)
library(igraph)

# broj sudionika po kolegiju
course_size <- affU |> count(kolegij, name = "n_osoba")

# npr. izbaciti kolegije s > 12 sudionika (prag je ilustrativni, ne "istina")
affU_small <- affU |>
  left_join(course_size, by = "kolegij") |>
  filter(n_osoba <= 12) |>
  select(osoba, kolegij)

gU_aff_small <- graph_from_data_frame(
  transmute(affU_small, from = osoba, to = kolegij),
  directed = FALSE,
  vertices = V_bip
)

gU_person_small <- bipartite_projection(gU_aff_small, which = "false")

c(
  dens_person_all   = edge_density(igraph::simplify(gU_person)),
  dens_person_small = edge_density(igraph::simplify(gU_person_small))
)
##   dens_person_all dens_person_small 
##        0.06442810        0.01225507

Promjenom granice (što ulazi kao “aktivnost” i koje aktivnosti se smatraju relevantnima) mijenjaju se gustoća, klasteri i time i “pozicije”.




Memento

Pozicija: Strukturno mjesto čvora u mreži (obrazac veza).

Uloga: Funkcija/ponašanje čvora proizlazi iz njegove pozicije.

Strukturna ekvivalencija: Čvorovi povezani s istim drugima na sličan način.

Regularna ekvivalencija: Čvorovi imaju slične veze prema sličnim tipovima čvorova.

Automorfna ekvivalencija: Čvorovi su automorfno ekvivalentni ako ih je moguće međusobno zamijeniti bez promjene ukupne strukture mreže (globalna topološka simetrija).

Orbita (u automorfnoj ekvivalenciji): Skup čvorova koji su međusobno zamjenjivi u okviru iste automorfne simetrije grafa.

Makro-arhitektura: Obrazac odnosa među pozicijama (sažetak strukture na razini blokova).

Blok-modeliranje: Grupiranje čvorova u blokove prema ekvivalenciji/uzorcima veza.

Matrica slike (image matrix): Sažeta matrica gustoća između pozicija (blokmodel na razini klasa).

Dualnost čvor–veza: Čvorovi i veze se mogu modelirati međusobno (npr. događaji).

Hijerarhija (mrežna): Obrazac odnosa u kojem su veze usmjerene od “viših” prema “nižim” razinama, uz minimalnu recipročnost i odsutnost ciklusa.

Usmjerena aciklička mreža (DAG): Usmjerena mreža bez ciklusa, u kojoj nije moguće krenuti od čvora i vratiti se u njega slijedeći smjer veza.

Jaka povezana komponenta (SCC): Skup čvorova u usmjerenoj mreži u kojem je svaki čvor dostižan iz svakog drugog čvora putem usmjerenih putova.

Kondenzacija mreže: Postupak u kojem se svaka jaka povezana komponenta zamjenjuje jednim “super-čvorom”, čime nastaje DAG među tim komponentama.

Dominacija: Asimetričan odnos moći/utjecaja (npr. A kontrolira B).

Podređenost: Suprotno dominaciji; pozicija niže moći u odnosu.

Centar–periferija (pozicijski): Pozicije definirane blizinom jezgre i uzorkom veza.

Autoritet: Čvor prepoznat kao izvor pouzdanih/važnih informacija.

Prestiž: Status čvora često mjerljiv primanjem veza (indegree).

Status: Socijalna vrijednost/pozicija u sustavu odnosa.

Formalne uloge: Uloge definirane pravilima (npr. menadžer).

Neformalne uloge: Uloge nastale kroz praksu (mentor, posrednik).

Organizacijska struktura: Formalna raspodjela funkcija i odgovornosti.

Mrežna hijerarhija: Hijerarhijski obrazac vidljiv u odnosima, ne nužno formalno.

DAG (usmjereni aciklički graf): Struktura bez ciklusa; ideal hijerarhije.

Outtree: Minimalna hijerarhijska struktura s jednim korijenom (m = n − 1).

Vertikalne veze: Veze između razina (nadređeni–podređeni).

Horizontalne veze: Veze među istom razinom (kolege).

Prijelaz faze (Phase transition): Kritična točka gustoće pri kojoj nastaje gigantska komponenta i omogućuje diferencijaciju pozicija.

Funkcionalna diferencijacija: Različite funkcije/uloge u podsustavima.

Gould–Fernandez posredovanje (brokerage): Klasifikacija uloga aktera u trijadama i→b→j ovisno o pripadnosti skupinama (koordinator, gatekeeper, representative, liaison).

Uloge mostova: Čvorovi koji spajaju dijelove mreže.

Gatekeeper: Čvor koji kontrolira ulaz/izlaz informacija prema grupi.

Koordinator (Coordinator): Posreduje unutar vlastite grupe.

Representative (Predstavnik): Prenosi informacije iz svoje grupe prema drugoj.

Liaison: Posreduje između dviju grupa kojima ne pripada.

Brokerage: Posredovanje u trijadi i → b → j ovisno o grupama.

Projekcija (one-mode projection): Transformacija bipartitne mreže u jednopartitnu mrežu u kojoj su čvorovi povezani ako dijele zajednički entitet iz druge skupine.




Pitanja za ponavljanje

  1. Automorfna ekvivalencija podrazumijeva da su čvorovi:
  1. povezani s istim drugim čvorovima identičnim vezama
  2. zamjenjivi bez promjene ukupne strukture mreže
  3. smješteni u istoj jako povezanoj komponenti
  4. dio iste k-core jezgre
  1. Regularna ekvivalencija znači da čvorovi:
  1. imaju veze prema istim konkretnim čvorovima
  2. imaju slične veze prema sličnim tipovima čvorova
  3. pripadaju istoj formalnoj organizacijskoj jedinici
  4. imaju identičan stupanj centralnosti
  1. Strukturna ekvivalencija najbliže se definira kao:
  1. jednakost ukupnog broja dolaznih veza
  2. identičan obrazac veza prema istim drugim čvorovima
  3. pripadnost istoj jako povezanoj komponenti
  4. sudjelovanje u istim trijadama posredovanja
  1. Jaka povezana komponenta (SCC) u usmjerenoj mreži označava skup čvorova:
  1. koji imaju isti broj dolaznih i odlaznih veza
  2. među kojima postoji put u oba smjera između svakog para
  3. koji pripadaju istoj k-core jezgri
  4. koji nemaju recipročnih veza
  1. Kondenzacija mreže znači:
  1. uklanjanje svih ciklusa iz mreže
  2. zamjenu svake jake komponente jednim super-čvorom
  3. spajanje svih perifernih čvorova u jedan blok
  4. transformaciju usmjerene mreže u neusmjerenu
  1. Usmjerena aciklička mreža (DAG) karakterizira se:
  1. visokom gustoćom i potpunom povezanošću
  2. odsutnošću recipročnih veza
  3. nemogućnošću povratka u isti čvor slijedeći smjer veza
  4. jednakim brojem dolaznih i odlaznih veza
  1. Recipročnost u usmjerenoj mreži mjeri:
  1. udio veza koje postoje u oba smjera
  2. udio čvorova s jednakim indegree i outdegree
  3. broj jako povezanih komponenti
  4. gustoću mreže bez self-loopova
  1. k-core metoda koristi se za:
  1. pronalaženje automorfnih orbita
  2. aproksimaciju kohezivne jezgre mreže
  3. detekciju trijada posredovanja
  4. izračun reciprociteta
  1. Blok-gustoća između dviju pozicija računa se kao:
  1. broj veza unutar bloka
  2. broj veza između blokova
  3. omjer ostvarenih i mogućih veza između skupina
  4. prosječni stupanj čvorova u bloku
  1. Matrica slike (image matrix) predstavlja:
  1. matricu susjedstva mreže
  2. binariziranu matricu blok-gustoća
  3. matricu najkraćih putova
  4. matricu recipročnosti
  1. Core–Periphery struktura idealno implicira:
  1. visoku gustoću unutar periferije
  2. potpunu odsutnost veza između blokova
  3. kohezivnu jezgru i rijetku periferiju
  4. simetričnu gustoću između svih blokova
  1. Gould–Fernandez koordinator je akter koji:
  1. posreduje između dviju različitih skupina
  2. prenosi informacije iz svoje skupine prema van
  3. posreduje unutar iste skupine
  4. kontrolira ulaz informacija iz druge skupine
  1. Gatekeeper uloga podrazumijeva:
  1. prijenos informacija iz svoje skupine prema drugoj
  2. kontrolu ulaza informacija u vlastitu skupinu
  3. posredovanje između dviju skupina kojima ne pripada
  4. koordinaciju unutar iste skupine
  1. Liaison uloga definira aktera koji:
  1. posreduje između dviju skupina kojima sam ne pripada
  2. ima najveći indegree u mreži
  3. pripada najvećoj jako povezanoj komponenti
  4. ima maksimalni k-core indeks
  1. Authority u HITS modelu označava čvor koji:
  1. šalje velik broj veza prema hubovima
  2. prima veze od čvorova s visokim hub-scoreom
  3. ima najveći ukupni stupanj
  4. pripada jezgri k-core
  1. Hub u HITS modelu označava čvor koji:
  1. prima veze od važnih autoriteta
  2. šalje veze prema čvorovima s visokim authority-scoreom
  3. ima najveći indegree
  4. ima najkraće prosječne putove
  1. Projekcija bipartitne mreže osoba–kolegij u mrežu osoba–osoba znači:
  1. zadržavanje samo formalnih veza
  2. povezivanje osoba koje dijele isti kolegij
  3. uklanjanje svih kolegija iz analize
  4. pretvaranje mreže u DAG
  1. Dualnost čvor–veza podrazumijeva:
  1. mogućnost modeliranja veza kao čvorova i obratno
  2. istovremenu prisutnost usmjerenih i neusmjerenih veza
  3. istovremenu analizu jezgre i periferije
  4. simetričnost matrice susjedstva
  1. Trokutastost matrice slike ukazuje na:
  1. modularnu strukturu bez hijerarhije
  2. hijerarhijski poredak pozicija
  3. potpunu recipročnost među blokovima
  4. odsutnost blokovske strukture
  1. Connectedness prema Krackhardtu mjeri:
  1. udio recipročnih veza
  2. dostižnost između parova čvorova
  3. razinu blokovske modularnosti
  4. razinu automorfne simetrije
  1. Ako je reciprocity = 0.92 u usmjerenoj mreži, najispravnije tumačenje je:
  1. mreža ima strogu hijerarhiju bez ciklusa
  2. većina veza postoji u oba smjera
  3. mreža je aciklička
  4. mreža ima nisku gustoću
  1. Ako is_dag(g) vraća FALSE, to znači da:
  1. mreža ima barem jedan ciklus
  2. mreža nema recipročnih veza
  3. mreža nije povezana
  4. mreža ima samo jednu komponentu
  1. Ako velika većina čvorova pripada SCC > 1, to sugerira:
  1. izrazitu hijerarhijsku strukturu
  2. opsežnu međusobnu dostižnost u oba smjera
  3. strogu core–periphery podjelu
  4. nisku reciprocitet
  1. Ako nakon kondenzacije mreža postaje DAG s 9 čvorova, to znači da:
  1. originalna mreža ima 9 čvorova
  2. postoji 9 jakih komponenti
  3. mreža nema recipročnih veza
  4. jezgra ima 9 članova
  1. Ako je blok-gustoća Core→Core najveća, a Periphery→Periphery niska, najispravnije je reći:
  1. struktura je konzistentna s jezgra–periferija modelom
  2. mreža je potpuno modularna
  3. mreža je aciklička
  4. periferija dominira mrežom
  1. Ako matrica slike ima jedinice samo na dijagonali, to sugerira:
  1. čistu hijerarhiju razina
  2. modularnu strukturu s dominantnim intra-blok vezama
  3. potpunu recipročnost među blokovima
  4. odsutnost blokova
  1. Ako je indeks trokutastosti jednak 0, to sugerira:
  1. simetričnu raspodjelu veza među pozicijama
  2. potpunu hijerarhiju
  3. odsutnost blokovske strukture
  4. potpunu modularnost
  1. Ako je Krackhardt hierarchy vrlo nizak, to je konzistentno s:
  1. visokom recipročnosti
  2. odsutnošću ciklusa
  3. potpunom acikličnosti
  4. strogo vertikalnom strukturom
  1. Ako je efficiency blizu 1, to znači da:
  1. mreža ima minimalan broj veza za održavanje povezanosti
  2. mreža je potpuno aciklička
  3. mreža je potpuno modularna
  4. mreža ima maksimalnu gustoću
  1. Ako je lubness = 1, to sugerira:
  1. postojanje jedinstvenog nadređenog za parove čvorova
  2. potpunu recipročnost
  3. odsutnost jakih komponenti
  4. modularnu strukturu
  1. Ako u HITS analizi isti čvor ima najviši authority i najviši hub score, to sugerira:
  1. da je čvor izoliran
  2. da je čvor centralan u dvosmjernim tokovima
  3. da čvor nema recipročnih veza
  4. da pripada periferiji
  1. Ako projekcija bipartitne mreže značajno poveća prosječni stupanj, to znači:
  1. da su nastale nove formalne veze
  2. da zajedničko sudjelovanje generira mnoge indirektne veze
  3. da je mreža postala aciklička
  4. da je smanjen broj čvorova
  1. Ako dvije pozicije imaju uzajamne jedinice u matrici slike (P3↔︎P7), to sugerira:
  1. strogu hijerarhiju
  2. recipročan međublok odnos
  3. potpunu izolaciju blokova
  4. odsutnost veze
  1. Ako je jedna pozicija potpuno nula u matrici slike, to znači da:
  1. nema nijednu vezu prema drugim blokovima iznad praga
  2. nema nijedan čvor
  3. ima najveću gustoću
  4. je dio jezgre
  1. Ako se jezgra definirana k-core metodom slabo preklapa s top 10% po degree, to sugerira:
  1. da su jezgra i centralnost identični pojmovi
  2. da je jezgra pozicijski, a ne samo kvantitativni koncept
  3. da mreža nema hijerarhiju
  4. da nema jakih komponenti
  1. Ako su intra-blok gustoće znatno veće od međublok gustoća, najispravnije je reći:
  1. mreža pokazuje modularnu strukturu
  2. mreža je strogo hijerarhijska
  3. mreža je potpuno aciklička
  4. mreža je homogena
  1. Ako reciprocity i SCC udio upućuju na snažnu cikličnost, to je tipično za:
  1. komunikacijske mreže
  2. stroge vojne hijerarhije
  3. DAG strukture
  4. stabla odlučivanja
  1. Ako je blok Core→Periphery znatno veći od Periphery→Core, to može sugerirati:
  1. broadcasting ili koordinacijsku dominaciju jezgre
  2. potpunu recipročnost
  3. izolaciju jezgre
  4. acikličnost mreže
  1. Ako je image matrix bliska idealu 1110, to znači:
  1. snažan jezgra–periferija obrazac
  2. potpunu modularnost
  3. odsutnost hijerarhije
  4. potpunu recipročnost
  1. Ako različite particije (formalna vs. pozicijska) daju različite brokerage rang-liste, to znači:
  1. da je brokerage ovisan o načinu grupiranja
  2. da su rezultati pogrešni
  3. da mreža nema strukturu
  4. da su authority i hub jednaki



Korištena literatura

Barabasi, A. L. (2022). Network Science. Cambridge University Pr.(2016). URL: https://www. ebook. de/de/product/24312547/albert_laszlo_barabasi_network_science. html.

Barabási, A. L., & Albert, R. (1999). Emergence of scaling in random networks. science, 286(5439), 509-512.

Bojanowski, M. (2022). intergraph: Coercion routines for network data objects (R package). Comprehensive R Archive Network (CRAN). https://CRAN.R-project.org/package=intergraph

Borgatti, S. P., & Everett, M. G. (2006). A graph-theoretic perspective on centrality. Social networks, 28(4), 466-484.

Breiger, R. L. (1974). The duality of persons and groups. Social forces, 53(2), 181-190.

Burris, V. (2004). The academic caste system: Prestige hierarchies in PhD exchange networks. American sociological review, 69(2), 239-264.

Butts, C. T. (2008). Social network analysis with sna. Journal of statistical software, 24, 1-51.

Butts, C. T. (2023). network: Classes for relational data (R package). Comprehensive R Archive Network (CRAN). https://CRAN.R-project.org/package=network

Butts, C. T. (2023). sna: Tools for social network analysis (R package). Comprehensive R Archive Network (CRAN). https://CRAN.R-project.org/package=sna

Csardi, G., & Nepusz, T. (2006). The igraph software. Complex syst, 1695, 1-9.

Gould, R. V. (2003). Collision of wills: How ambiguity about social rank breeds conflict. University of Chicago Press.

Jackson, M. O. (2008). Social and Economic Networks. Princeton University Press.

Jurca, G., Addam, O., Rokne, J., & Alhajj, R. (2018). Social network based big data analysis and applications. In M. Kaya et al. (Eds.), Lecture notes in social networks. Springer.

Kleinberg, J. M. (1999). Authoritative sources in a hyperlinked environment. Journal of the ACM (JACM), 46(5), 604-632.

Knoke, D., & Yang, S. (2019). Social Network Analysis (3. izd.). SAGE Publications.

Kostelić, K., & Turk, M. (2021). Topology of the world tourism web. Applied Sciences, 11(5), 2253.

Krackhardt, D. (2014). Graph theoretical dimensions of informal organizations. U K. M. Carley & M. J. Prietula (Ur.), Computational Organization Theory (str. 107–130). Psychology Press.

Lamba, M., & Madhusudhan, M. (2022). Text mining for information professionals. An Uncharted Territoriy. Cham.

McFarland, D. A. (2001). Student resistance: How the formal and informal organization of classrooms facilitate everyday forms of student defiance. American journal of Sociology, 107(3), 612-678.

Nobari, S., Lu, X., Karras, P., & Bressan, S. (2011, March). Fast random graph generation. In Proceedings of the 14th international conference on extending database technology (pp. 331-342).

Ooms, J. (2023). gifski: Highest quality GIF encoder (R package). Comprehensive R Archive Network (CRAN). https://CRAN.R-project.org/package=gifski

Padgett, J. F., & Ansell, C. K. (1993). Robust Action and the Rise of the Medici, 1400-1434. American journal of sociology, 98(6), 1259-1319.

Rawlings, C. M., Smith, J. A., Moody, J., & McFarland, D. A. (2023). Network analysis: integrating social network theory, method, and application with R. Cambridge University Press.

Van Steen, M. (2010). Graph Theory and Complex Networks: An Introduction.

Wasserman, S., & Faust, K. (1994). Social network analysis: Methods and applications.

Wickham, H., François, R., Henry, L., & Müller, K. (2023). dplyr: A grammar of data manipulation (R package). Comprehensive R Archive Network (CRAN). https://CRAN.R-project.org/package=dplyr




Ključ odgovora

  1. b

  2. b

  3. b

  4. b

  5. b

  6. c

  7. a

  8. b

  9. c

  10. b

  11. c

  12. c

  13. b

  14. a

  15. b

  16. b

  17. b

  18. a

  19. b

  20. b

  21. b

  22. a

  23. b

  24. b

  25. a

  26. b

  27. a

  28. a

  29. a

  30. a

  31. b

  32. b

  33. b

  34. a

  35. b

  36. a

  37. a

  38. a

  39. a

  40. a

sessionInfo()
## R version 4.4.2 (2024-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 10 x64 (build 19045)
## 
## Matrix products: default
## 
## 
## locale:
## [1] LC_COLLATE=Croatian_Croatia.utf8  LC_CTYPE=Croatian_Croatia.utf8   
## [3] LC_MONETARY=Croatian_Croatia.utf8 LC_NUMERIC=C                     
## [5] LC_TIME=Croatian_Croatia.utf8    
## 
## time zone: Europe/Zagreb
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices datasets  utils     methods   base     
## 
## other attached packages:
##  [1] intergraph_2.0-4      ggalluvial_0.12.6     tidyr_1.3.2          
##  [4] purrr_1.2.1           stringr_1.6.0         dplyr_1.2.0          
##  [7] igraphdata_1.0.1      sna_2.8               network_1.20.0       
## [10] statnet.common_4.13.0 ggraph_2.2.2          ggplot2_4.0.2        
## [13] tidygraph_1.3.1       igraph_2.2.1         
## 
## loaded via a namespace (and not attached):
##  [1] viridis_0.6.5      utf8_1.2.6         sass_0.4.10        generics_0.1.4    
##  [5] renv_1.1.1         stringi_1.8.7      lattice_0.22-6     digest_0.6.39     
##  [9] magrittr_2.0.4     evaluate_1.0.5     grid_4.4.2         RColorBrewer_1.1-3
## [13] fastmap_1.2.0      jsonlite_2.0.0     ggrepel_0.9.6      gridExtra_2.3     
## [17] viridisLite_0.4.3  scales_1.4.0       tweenr_2.0.3       jquerylib_0.1.4   
## [21] cli_3.6.5          rlang_1.1.7        graphlayouts_1.2.2 polyclip_1.10-7   
## [25] withr_3.0.2        cachem_1.1.0       yaml_2.3.12        tools_4.4.2       
## [29] memoise_2.0.1      coda_0.19-4.1      vctrs_0.7.1        R6_2.6.1          
## [33] lifecycle_1.0.5    MASS_7.3-61        pkgconfig_2.0.3    pillar_1.11.1     
## [37] bslib_0.10.0       gtable_0.3.6       glue_1.8.0         Rcpp_1.1.1        
## [41] ggforce_0.5.0      xfun_0.56          tibble_3.3.1       tidyselect_1.2.1  
## [45] rstudioapi_0.18.0  knitr_1.51         farver_2.1.2       htmltools_0.5.9   
## [49] labeling_0.4.3     rmarkdown_2.30     compiler_4.4.2     S7_0.2.1