아래 튜토리얼은 도시·교통 빅데이터(분산처리) 및 네트워크 분석 관점에서, graph-tool 라이브러리의 일부 함수를 직관적으로 보여주고 파이썬 예제 코드를 통해 실제 적용·시각화 방법까지 안내합니다. 특히 add_random_edges, remove_random_edges, generate_triadic_closure 함수들을 중심으로 정성껏 설명하겠습니다.
add_random_edges: 그래프에 무작위로 간선 추가 remove_random_edges: 무작위로 간선 제거 generate_triadic_closure: 삼각(트라이어드) 완성 (Triadic closure) 여기서는 graph-tool 라이브러리의 3가지 함수를 통해 네트워크 상태를 동적으로 변경하고, 그때의 시각화나 분석 아이디어를 소개합니다.
add_random_edges: 그래프에 무작위로 간선 추가add_random_edges(
g, # 그래프 객체
M, # 추가할 간선 수 (정수)
parallel=False, # 평행 간선(=중복 간선) 허용 여부
self_loops=False, # 자기 루프(같은 노드->자기 자신) 허용 여부
weight=None # EdgePropertyMap(정수). 있으면, 이미 존재하는 간선의 weight만 증가
)
M개 추가.False면 (u->v) 같은 간선이 이미 있으면 추가 불가. True면 이미 있는 간선(u->v)와 같은 간선을 또 넣을 수 있음(=복수 개).None이 아니면, 무작위로 뽑힌 간선이 이미 존재할 때, 새로운 간선 추가 대신 weight[e]++ 형태로 처리함. parallel == True일 때: 시간 복잡도 (\mathcal{O}(M + E)) 정도. parallel == False일 때: (\mathcal{O}(M \cdot k)) ((k)는 평균 차수). 도시·교통 해석:
M개만큼 임의로 추가해서 “노드 간 연결 확장” 시나리오. import graph_tool.all as gt
import numpy as np
def demo_add_random_edges():
# 1) 기본 그래프 예: circular_graph(100)
# 원형으로 100개 노드가 순차 연결된 그래프
g = gt.circular_graph(100)
print("Initial edges:", g.num_edges())
# 2) 간선 무작위 추가
M = 30
gt.add_random_edges(
g,
M=M,
parallel=False, # 평행 간선은 허용하지 않음
self_loops=False # 자기 루프 허용하지 않음
)
print("After add_random_edges:", g.num_edges())
# 3) 시각화
# 예: sfdp_layout 등으로 위치 계산
pos = gt.sfdp_layout(g)
gt.graph_draw(
g, pos=pos,
vertex_text=g.vertex_index,
vertex_font_size=10,
output_size=(400, 400),
output="demo_add_random_edges.png"
)
print("Saved demo_add_random_edges.png")
demo_add_random_edges()
실행하면, 원형 그래프(circular) + 임의 30개 간선이 추가되어, 그래프가 더 복잡해집니다.
remove_random_edges: 무작위로 간선 제거remove_random_edges(
g, # 그래프
M, # 제거할 간선 수
weight=None, # (EdgePropertyMap, optional)
counts=True
)
None이면, 진짜로 M개의 간선을 골라 삭제.weight[e] -= 1(counts=True일 때) 식으로 처리 가능 → 중첩/가중치 기반의 그래프에서 “한 겹만 제거”하는 효과.True면 weight[e]가 정수형(간선 중첩 수)으로 간주. False면 weight[e]는 “제거 확률의 스케일”로만 사용.weight=None이면 (\mathcal{O}(M)) ~ (\mathcal{O}(E)) 정도. weight가 있으면 확률적 스케일 계산 추가. fast_edge_removal(True)를 미리 설정하면, 내부 구조 최적화되어 더욱 빨라짐.도시·교통 해석:
weight[e]-- → “해당 구간 운행 횟수 감소”로도 해석 가능.import graph_tool.all as gt
import numpy as np
def demo_remove_random_edges():
# 1) 우선 2D Lattice 그래프 (100x100)
g = gt.lattice([100, 100])
print("Initial edges:", g.num_edges()) # 2D 격자
# 2) 임의로 5000개의 간선 제거
M = 5000
# fast edge removal 모드 활성화(성능 향상)
g.set_fast_edge_removal(True)
gt.remove_random_edges(
g,
M=M,
weight=None,
counts=True
)
print("After remove_random_edges:", g.num_edges())
# 3) 연결성 확인: label_components()
comp_label, comp_count = gt.label_components(g)
print("Number of components:", comp_count)
# => 만약 M이 충분히 크면, 컴포넌트가 많이 분할됨.
# (옵션) 시각화는 거대 그래프(100x100=1만 노드)라 부담.
# 그래도 예시:
# pos = gt.arf_layout(g, max_iter=100) # or sfdp_layout, etc.
# gt.graph_draw(g, pos=pos, output_size=(800,800), output="demo_remove_random_edges.png")
demo_remove_random_edges()
실행 후, 간선 M=5000개가 무작위 제거되어, 더 많은 단절이 발생할 수 있습니다.
generate_triadic_closure: 트라이어드 완성 (Triadic closure)Triadic closure:
generate_triadic_closure(
g,
t,
probs=True,
curr=None,
ego=None
)
VertexPropertyMap 혹은 스칼라(모든 노드 동일).probs=True → t[u]를 0~1 확률로 해석.probs=False → 정수로 해석(“이웃 간 pair 중 몇 개를 고를지”).import graph_tool.all as gt
import numpy as np
def demo_triadic_closure():
# 1) 예시로 'karate' 네트워크를 복사
g = gt.collection.data["karate"].copy()
print("Initial edges:", g.num_edges())
# 2) triadic closure 파라미터
# t[u] = 0.5 (확률)로 하자 (모든 노드 동일)
# (VertexPropertyMap or float)
t_value = 0.5
gt.generate_triadic_closure(
g,
t_value,
probs=True # True => 0.5 확률로 이웃 간 연결
)
print("After triadic_closure:", g.num_edges())
# 3) 시각화
# karate 데이터셋에 pos가 이미 있음 (g.vp.pos)
# 없다면 sfdp_layout or arf_layout 등 수행 가능
pos = None
if "pos" in g.vp: # karate 예시는 pos가 있을 수 있음
pos = g.vp["pos"]
else:
pos = gt.sfdp_layout(g)
gt.graph_draw(
g, pos=pos,
vertex_text=g.vertex_index,
vertex_font_size=10,
output_size=(600,600),
output="demo_triadic_closure.png"
)
print("Saved demo_triadic_closure.png")
demo_triadic_closure()
카메라태 karate network(34노드, 78에지)에 삼각 closure가 추가로 발생 → 간선 수가 증가. 시각화하면, 삼각형(3노드 완전연결)이 많이 늘어나는 걸 확인할 수 있습니다.
무작위 간선 추가(add_random_edges)
무작위 간선 제거(remove_random_edges)
삼각 완성(generate_triadic_closure)
t[u]가 큰 노드 = “그 노드 주변 환승 체계가 활발하게 (서로 연결) 되는 정류장”으로 해석.g.num_vertices(), g.num_edges() 등 비교.label_components나 vertex_average, 지름(diameter), 클러스터링 계수 등 측정.local_clustering(로컬 클러스터링)이 얼마나 증가했는지 확인.add_random_edges / remove_random_edges / generate_triadic_closure는 네트워크를 동적으로 바꾸는 유용한 도구.generation 모듈 참고.fast_edge_removal(True)나 필터링 그래프와 결합하면, 성능 및 특정 부분집합에만 적용하는 등 다양한 확장이 가능.Tip: 예제들에서, 노드가 많으면 시각화가 어려울 수 있으므로 소규모 그래프(예: 30~100 노드)로 개념 시연 후, 대규모 네트워크(수만 노드)에 적용할 때는 분산처리(파이썬 멀티프로세싱 등)나 OpenMP 지원(graph-tool 빌드 시)을 활용하면 좋습니다.
이상으로, add_random_edges, remove_random_edges, generate_triadic_closure의 핵심 개념부터 예제 코드, 그리고 도시·교통 시나리오에서의 해석 방법을 모두 살펴보았습니다.
네트워크를 “동적”으로 수정하고 분석/시각화까지 이어지는 본 튜토리얼이, 도시·교통 빅데이터 연구에 조금이라도 도움이 되길 바랍니다!
아래 튜토리얼은 도시·교통 빅데이터(분산처리) 및 네트워크 분석의 관점에서, Barabási–Albert(BA) / Price 모델(우선순위 연결 첨부, Preferential Attachment)의 개념과, graph_tool 라이브러리에서 이를 구현한 price_network 함수를 다룹니다.
목표:
1. Price/Barabási–Albert(BA) 네트워크가 무엇인지 소개
2. 파라미터(m, c, gamma, 등)별 의미 설명
3. 도시·교통 환경에서 어떻게 해석되는지
4. 파이썬 코드 예시(네트워크 생성, 시각화, 가벼운 분석 아이디어)
이 알고리즘은 “부익부 현상”(도시 내에서 교통량이 많은 곳이 더욱 연결이 생긴다 등)을 모사.
price_network 함수 개요price_network(N, m=1, c=None, gamma=1, directed=True, seed_graph=None):
directed=True이면 1, 무방향이면 0).gamma=1: 전형적 “선호 연결(Preferential Attachment)” → 차수가 큰 정점에 더 많이 연결. gamma != 1이면, 분포가 달라짐(스케일프리 vs 다른 형태).True면 Price 네트워크(방향성), False면 BA(무방향).m > (seed_graph의 최소 차수) 조건을 만족해야 함.directed=True인 경우 1개 노드에서 시작(또는 m≥2일 경우 두 노드에 1간선).시간복잡도: (\mathcal{O}(N)) (내부적으로 효율적으로 구현됨).
directed=True 기본 c=1, “차수가 0인 노드도 약간 확률로 연결될 기회” 부여. c=0이면, 오로지 차수만으로 연결 확률 결정 → 차수 0인 노드가 선택되기 힘듦.=1이면 전형적 선호 연결(“degree가 x배면 연결확률도 x배”). >1 or <1이면 연결 분포가 달라짐. False로 하면 Barabási–Albert(BA). (무방향) 아래에서는 1) 방향 그래프(Price), 2) 무방향 그래프(BA) 두 가지 예를 보이겠습니다.
import graph_tool.all as gt
import matplotlib.pyplot as plt
import numpy as np
def demo_price_directed():
# 1) 파라미터 설정
N = 2000 # 최종 노드 수
m = 2 # 새로 들어오는 노드는 항상 out-degree=2
c = 1.0 # 상수항(기본)
gamma = 1 # 전형적 선호 연결
# 2) 네트워크 생성
g = gt.price_network(
N=N,
m=m,
c=c,
gamma=gamma,
directed=True,
seed_graph=None # 초기 그래프 없음 => 내부 default
)
print("Created Price directed graph. Vertices:", g.num_vertices(),
"Edges:", g.num_edges())
# 3) 시각화
# sfdp_layout 사용 (자유도 높음)
pos = gt.sfdp_layout(g, cooling_step=0.99)
# 4) 그리기
# vertex_fill_color = vertex_index (노드가 추가된 순서)
# edge_pen_width=1
gt.graph_draw(
g,
pos=pos,
vertex_fill_color=g.vertex_index,
vertex_size=3,
vcmap=plt.cm.plasma, # 색상맵
edge_pen_width=1,
output_size=(800,800),
output="price_directed.png"
)
print("Saved 'price_directed.png'.")
demo_price_directed()
N=2000, 각 노드가 들어오면서 기존 노드 2개와 연결. 차수가 큰 노드가 더 많이 연결받아, 방향성이 있는 “허브”가 탄생.import graph_tool.all as gt
import matplotlib.pyplot as plt
import numpy as np
def demo_price_undirected():
# 1) 파라미터
N = 3000
m = 3
c = 0 # 무방향인 경우 기본 0
gamma = 1
# 2) network (Barabási–Albert)
g = gt.price_network(
N=N,
m=m,
c=c,
gamma=gamma,
directed=False # => BA Network
)
print("Created BA(undirected) graph. V=", g.num_vertices(),
"E=", g.num_edges())
# 3) 시각화
pos = gt.sfdp_layout(g, cooling_step=0.99)
gt.graph_draw(
g,
pos=pos,
vertex_fill_color=g.vertex_index,
vertex_size=3,
vcmap=plt.cm.plasma,
edge_pen_width=1,
output_size=(800,800),
output="price_undirected.png"
)
print("Saved 'price_undirected.png'.")
demo_price_undirected()
Price(방향) 모델
c가 커지면 차수 낮은 곳도 약간 혜택.Barabási–Albert(무방향) 모델
seed_graph 옵션으로 “도시 초기 인프라”를 주고, 추가 확장 시 “선호 연결”되는 과정.gamma
=1 → “전형적 스케일프리 분포”. 차수 분포 ~ (k^{-3}) 혹은 (k^{-2-\alpha}) 등. >1 or <1이면, 분포 기울기나 형태가 달라져, “더 심한 부익부” 또는 “부익부 완화” 가능.응용 시:
차수 분포 확인
deg_hist = gt.vertex_hist(g, "out") # 또는 "total" for undirected
# deg_hist[0] = degree 값들, deg_hist[1] = 각 값의 개수
중심성(Betweenness, Closeness, etc.) 재계산
v_bet, e_bet = gt.betweenness(g)
# 허브 노드가 betweenness 높은가 확인
시각화:
vertex_size = (차수 or 중심성)으로 해서 “특정 노드가 허브인지” 직관적으로 관찰.price_network는 Price(방향) / BA(무방향) 모델을 graph-tool에서 손쉽게 생성 가능하도록 한 함수.Tip: 대규모(수십만 노드 이상) 네트워크에도 잘 동작하지만, 시각화 시에는 sampling이나 노드 크기 최소화, 렌더링 옵션 조정이 필요합니다.
추가 참고:
- “dorogovtsev-evolution” 문헌 등에서 BA/Price 모델의 수학적 해석(지수, 분포) 확인.
seed_graph로 초기 도시 맵(소규모) 주고, 나머지 노드를N까지 확장하면, 실제 도시 발전 비슷한 과정 모사 가능.
이상으로 price_network 함수 튜토리얼을 마칩니다.
도시·교통 네트워크 분석에서 “시간이 지남에 따라, 인기 많은 곳이 더 많은 연결을 얻는” 현상을 정량적으로 시뮬레이션하고, 중심성, 차수분포 등을 살펴보는 데 유용합니다.
즐거운 네트워크 분석 되시길 바랍니다!