In [1]:
import matplotlib
import matplotlib.pyplot as plt
import networkx as nx
matplotlib.rcParams['figure.figsize'] = [12., 8.]
log_debug = False
def debug(msg, *args, **kwargs):
if log_debug:
print(msg.format(*args, **kwargs))
In [2]:
G = nx.Graph()
G.add_nodes_from([i for i in range(7)])
G.add_edges_from([(0,1),(0,2),(0,5),(1,3),(1,4),(2,6),(3,5)])
# positions for all nodes
pos = nx.spring_layout(G)
# nodes
nx.draw_networkx_nodes(G, pos, node_size=500, alpha=0.8)
# edges
nx.draw_networkx_edges(G, pos, width=1.0, alpha=0.5)
#labels
nx.draw_networkx_labels(G, pos)
plt.show()
In [3]:
for node in G.nodes():
print('node %d - neighbors: %s' % (node, nx.neighbors(G, node)))
In [4]:
nx.bfs_successors(G, 0)
Out[4]:
In [5]:
nx.bfs_successors(G, 1)
Out[5]:
In [6]:
bfs_tree = nx.bfs_tree(G, 1)
pos = nx.spring_layout(bfs_tree)
nx.draw(bfs_tree,pos)
nx.draw_networkx_labels(bfs_tree,pos)
plt.show()
In [7]:
dfs_tree = nx.dfs_tree(G, 1)
pos = nx.spring_layout(dfs_tree)
nx.draw(dfs_tree, pos)
nx.draw_networkx_labels(dfs_tree, pos)
plt.show()
In [8]:
nx.dfs_successors(G, 0)
Out[8]:
In [9]:
nx.dfs_successors(G, 1)
Out[9]:
In [10]:
def crawl_dfs_iter(graph, root, max_visits=10):
"""Generator der einen Graph anhand seiner Kanten mit Hilfe von
depth first search in iterativer Variante crawlt. Die Id des
besuchten Knoten wird dabei geliefert.
:param edges: Liste mit 2-Tupeln, die alle Kanten des Graphen beinhalten
:param root: Id des Ausgangsknotens
:param max_visits: Anzahl der maximal zu besuchenden Knoten
"""
visited = 0
S = set()
Q = []
Q.append(root)
while Q and visited < max_visits:
node = Q.pop()
yield node
visited += 1
if node not in S and visited < max_visits:
S.add(node)
neighbors = nx.neighbors(graph, node)
# umdrehen der nachbarn, damit diese in der richtigen
# reihenfolge durch pop wieder entnommen werden
neighbors.reverse()
for neighbor in neighbors:
Q.append(neighbor)
In [11]:
nodes = [n for n in crawl_dfs_iter(dfs_tree, 1, len(G.nodes()))]
for i in range(len(nodes)):
print('{:>4d}.: {_id:d}'.format(i + 1, _id=nodes[i]))
In [12]:
nx.bfs_successors(G, 0)
Out[12]:
In [13]:
nx.bfs_successors(G, 1)
Out[13]:
In [14]:
bfs_tree = nx.bfs_tree(G, 1)
pos = nx.spring_layout(bfs_tree)
nx.draw(bfs_tree,pos)
nx.draw_networkx_labels(bfs_tree,pos)
plt.show()
In [15]:
def crawl_bfs_iter(graph, root, max_visits=10):
visited = 0
# Verwendung von Q als Queue (FIFO)
Q = []
S = set()
Q.append(root)
S.add(root)
while Q and visited < max_visits:
node = Q.pop(0)
yield node
visited += 1
neighbors = nx.neighbors(graph, node)
for neighbor in neighbors:
if neighbor not in S:
S.add(neighbor)
Q.append(neighbor)
In [16]:
nodes = [n for n in crawl_bfs_iter(bfs_tree, 1, len(G.nodes()))]
for i in range(len(nodes)):
print('{:>4d}.: {_id:d}'.format(i + 1, _id=nodes[i]))
In [17]:
import random
def random_walk(graph, root, max_visits=10):
"""Generator der einen Graph anhand seiner Kanten mit Hilfe von
random walk in iterativer Variante crawlt. Die Id des
besuchten Knoten wird dabei geliefert.
:param graph: Graph ueber den der random walk ausgefuehrt werden soll
:param root: Id des Ausgangsknotens
:param max_visits: Anzahl der maximal zu besuchenden Knoten
"""
visited = 0
S = set()
# die queue enthaelt im gegensatz zu den anderen implementierungen
# den pfad, der im random walk gelaufen wurde
Q = []
Q.append(root)
debug('{:>10s}: {:s}', 'Q', str(Q))
while Q and visited < max_visits:
node = Q[-1]
debug('{:>10s}: {:d}', 'yield', node)
yield node
visited += 1
if node not in S and visited < max_visits:
S.add(node)
debug('{:>10s}: {:s}', 'S', str(S))
# nachbarn die noch nicht besucht wurden
neighbors = [n for n in nx.neighbors(graph, node) if n not in S]
debug('{:>10s}: {:s}', 'neighbors', str(neighbors))
up = -2
# solange alle nachbarn des gewaehlten knotens besucht wurden
# wird der knoten von der queue entfernt und neue nachbarn
# gesucht
while not neighbors:
node = Q[up]
debug('{:>10s}: {:d}', 'pop to', node)
neighbors = [n for n in nx.neighbors(graph, node) if n not in S]
up -= 1
# ansonsten waehle einen zufaelligen nachbar aus
# und schiebe ihn auf die queue
neighbor = random.choice(neighbors)
debug('{:>10s}: {:d}', 'neighbor', neighbor)
Q.append(neighbor)
debug('{:>10s}: {:s}', 'Q', str(Q))
log_debug = True
nodes = [n for n in random_walk(G, 1, len(G.nodes()))]
for i in range(len(nodes)):
print('{:>4d}.: {_id:d}'.format(i + 1, _id=nodes[i]))
In [18]:
def plot_graph(G, labels=True):
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, node_size=400, alpha=0.8)
nx.draw_networkx_edges(G, pos, width=1.0, alpha=0.5)
if labels:
nx.draw_networkx_labels(G, pos)
plt.show()
def generate_barabasi_albert(N, m):
"""Returns networkx.Graph object. Generates a Barabasi Albert
graph of nx.nodes
"""
graph = nx.Graph()
nodes_to_add = 0
while nodes_to_add < N :
to_connect = [] # List of nodes to connect to newly added
counter = 0
while counter < m : # For each branch to be connected
rnd = random.random() # generate a random number
nodes = nx.nodes_iter(graph) # Iterate over all nodes of the graph
probability = 0.0 # create a temp variable
edges = len(graph.edges())
# Populate to_connect
for node in nodes:
if len(graph.edges()) == 0 :
# If no edge is present in graph, avoid divergence
probability = 1.0
else:
# Otherwise increase value of temp proportionaly
probability += float(len(graph.neighbors(node)))/float(2*edges)
if probability > rnd :
# If temp is larger than rnd, add the BA node
to_connect.append(node)
break
counter += 1
# Connect the new node
graph.add_node(nodes_to_add)
for node in to_connect :
graph.add_edge(node, nodes_to_add)
nodes_to_add += 1
return graph
In [19]:
plot_graph(generate_barabasi_albert(50, 1))
In [20]:
plot_graph(generate_barabasi_albert(50, 2))
In [21]:
plot_graph(generate_barabasi_albert(200, 1), labels=False)