import networkx as nx

import matplotlib.pyplot as plt

import numpy as np

import pandas as pd

names = ["Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace"]

adjacency_matrix = np.array([[0, 1, 1, 0, 0, 0, 0],

[1, 0, 0, 1, 0, 0, 0],

[1, 0, 0, 1, 0, 0, 0],

[0, 1, 1, 0, 1, 0, 0],

[0, 0, 0, 1, 0, 1, 1],

[0, 0, 0, 0, 1, 0, 1],

[0, 0, 0, 0, 1, 1, 0]])


df_adj = pd.DataFrame(adjacency_matrix, index=names, columns=names)

print("Adjacency Matrix:")

print(df_adj)


G = nx.from_pandas_adjacency(df_adj)

G = nx.relabel_nodes(G, {i: name for i, name in enumerate(names)})


plt.figure(figsize=(8,6))

nx.draw(G, with_labels=True, node_color='lightblue', edge_color='gray', node_size=2000, font_size=12)

plt.show()

Find the most central individuals.

# Find the maximum closeness centrality value

max_closeness_value = max(closeness_centrality.values())


# Find all individuals with the maximum closeness centrality

max_closeness_centrality_nodes = [node for node, value in closeness_centrality.items() if value == max_closeness_value]


print(f"Individuals with highest Closeness Centrality: {', '.join(max_closeness_centrality_nodes)}")


# Plot Closeness Centrality

plt.figure(figsize=(8,6))

node_size_closeness = [v * 10000 for v in closeness_centrality.values()]

nx.draw(G, with_labels=True, node_size=node_size_closeness, node_color='lightgreen', font_size=12, edge_color='gray')

plt.title("Social Network Graph - Closeness Centrality")

plt.show()

Identify the most crucial individual in terms of information flow between different parts of the network

# Find the maximum betweenness centrality value

max_betweenness_value = max(betweenness_centrality.values())


# Find all individuals with the maximum betweenness centrality

max_betweenness_centrality_nodes = [node for node, value in betweenness_centrality.items() if value == max_betweenness_value]


print(f"Individuals with highest Betweenness Centrality: {', '.join(max_betweenness_centrality_nodes)}")


# Plot Betweenness Centrality

plt.figure(figsize=(8,6))

node_size_betweenness = [v * 10000 for v in betweenness_centrality.values()]

nx.draw(G, with_labels=True, node_size=node_size_betweenness, node_color='lightcoral', font_size=12, edge_color='gray')

plt.title("Social Network Graph - Betweenness Centrality")

plt.show()

Centrality Measures

Centrality measures help determine important nodes in a network.

  • Degree Centrality: Measures the number of direct connections a node has.

    • A higher degree means a node is more connected.

    • Computed as the fraction of total possible connections.

  • Closeness Centrality: Measures how close a node is to all other nodes.

    • A higher value means a node can quickly reach others.

    • Computed as the reciprocal of the average shortest path distance.

  • Betweenness Centrality: Measures how often a node appears on shortest paths.

    • A higher value indicates a node acts as a bridge between others.

    • Computed by counting the shortest paths passing through a node.

# Degree Centrality

degree_centrality = nx.degree_centrality(G)

print("Degree Centrality:")

for node, value in degree_centrality.items():

print(f"{node}: {value:.2f}")


# Closeness Centrality

closeness_centrality = nx.closeness_centrality(G)

print("\nCloseness Centrality:")

for node, value in closeness_centrality.items():

print(f"{node}: {value:.2f}")


# Betweenness Centrality

betweenness_centrality = nx.betweenness_centrality(G)

print("\nBetweenness Centrality:")

for node, value in betweenness_centrality.items():

print(f"{node}: {value:.2f}")

Find the most connected people.

# Find the maximum degree centrality value

max_degree_value = max(degree_centrality.values())


# Find all individuals with the maximum degree centrality

max_degree_centrality_nodes = [node for node, value in degree_centrality.items() if value == max_degree_value]


print(f"Individuals with highest Degree Centrality: {', '.join(max_degree_centrality_nodes)}")


# Plot Degree Centrality

plt.figure(figsize=(8,6))

node_size_degree = [v * 10000 for v in degree_centrality.values()]

nx.draw(G, with_labels=True, node_size=node_size_degree, node_color='lightblue', font_size=12, edge_color='gray')

plt.title("Social Network Graph - Degree Centrality")

plt.show()

from networkx.algorithms.community import girvan_newman

def get_communities(G):

communities = next(girvan_newman(G))

return [list(c) for c in communities]


communities = get_communities(G)

print("Communities detected:", communities)


# Visualizing the communities


plt.figure(figsize=(8, 6))

pos = nx.spring_layout(G) # Positioning nodes with a layout

colors = plt.colormaps.get_cmap('tab10')


for i, community in enumerate(communities):

nx.draw_networkx_nodes(G, pos, nodelist=community, node_color=[colors(i)], node_size=2000)


nx.draw_networkx_edges(G, pos, edge_color='gray')


nx.draw_networkx_labels(G, pos, font_size=12)


plt.title("Community Detection Using Girvan-Newman Algorithm")


plt.show()

Compute Link Prediction for the social network graph in Exercise 1 using Common Neighbors Method.

# Function to calculate Common Neighbors score for each pair of unconnected nodes

def common_neighbors_score(G):

scores = []

for node1 in G.nodes():

for node2 in G.nodes():

if node1 < node2 and not G.has_edge(node1, node2): # Ensuring node1 < node2 to avoid duplicates

# Calculate the common neighbors

common_neighbors = set(G.neighbors(node1)) & set(G.neighbors(node2))

scores.append(((node1, node2), len(common_neighbors)))

return scores


# Get common neighbors score for all node pairs

common_neighbors_scores = common_neighbors_score(G)


# Sort pairs by their score (higher score means more likely to form a link)

common_neighbors_scores.sort(key=lambda x: x[1], reverse=True)


# Print the top 3 pairs with the highest common neighbors

print("Link Prediction:")

for pair, score in common_neighbors_scores[:3]:

if score > 0:

print(f"Nodes {pair[0]} and {pair[1]} with score {score}")