HW-2: Network modeling and simulations
NAME: INSERT_YOUR NAME NETID: INSERT_YOUR_NETID Instructions:
Copy the HW folder from shared box to your local machine (DO NOT WORK IN THE 645 SHARED BOX FOLDER)
Complete this .ipynb file, either in VS code or Jupyter notebook. SUBMISSION:
HW-2.1: Project checkpoint (group work)
As a group, write an INITIAL DRAFT including the following sections of your project paper. Aim for around 2000 to 3000 words in total. Note: These sections can all change later on, however, do your best to provide a reasonably polished initial draft.
Title+Authors: With institution affiliation as footnotes
Abstract: A "teaser" paragraphs summarizing the work (see below for more detail).
The work isn't finished so this can just be an initial draft
An abstract is a 150 to 250-word paragraph that provides readers with a quick overview of your essay or report and its organization. It should express your thesis (or central idea) and your key points; it should also suggest any implications or applications of the research you discuss in the paper.
The function of an abstract is to describe, not to evaluate or defend, the paper.
The abstract should begin with a brief but precise statement of the problem or issue, followed by a description of the research method and design, the major findings, and the conclusions reached.
For more see: https://writingcenter.gmu.edu/guides/writing-an-abstract#:~:text=The%20function%20of%20an%20abstract,findings%2C%20and%20the%20conclusions%20reached.
Keywords: Provide a list of keywords relevant to your work.
Think of these as "search terms" that other researchers might google to find your paper.
Introduction:
Summary of the topic, why it is important, why the reader should continue, what work has been done in the past by other research groups, what are the “different points of views”/interpretations in the literature, what are you exploring, what questions are you trying to address, what are your goals and hypothesis, etc
Part of the introduction is a concise literature review. Therefore, along with the points mentioned above, make sure to summarize the nine publications (three per person) that you discussed in HW-1.
References:
Make sure to include internal citations to all textbooks and peer-reviewed articles with a list of references at the end.
HW-2.2 Modeling (individual work)
In this section we build on top of the modeling methods discussed in class and in the textbook
First lets start by importing various packages (feel free to add more imports if needed)
import networkx as nx
import numpy as np
import shutil
import matplotlib.pyplot as plt import random
from importlib import reload import os
Now lets create a folder to store the outputs of the code
#WARNING: THIS FUNCTION WILL DELETE AND RECREATE THE SPECIFIED FOLDER
def build_output_folder(out_dir_path): if(os.path.exists(out_dir_path)):
shutil.rmtree(out_dir_path) os.mkdir(out_dir_path)
output_folder="outputs" build_output_folder(output_folder)
HW-2.2.1 : Improve nx_tools.py
Use the provided nx_tools.py as a starting point
Add a new function called "plot_centrality_correlation(G,path="")" which does the following
Uses seaborn to generate a pair plot (with histograms on the main diagonal) for the various nodal centrality vectors
Use nx.is_directed(G) to determine the network type
Un-Directed case: --> degree_centrality, betweenness_centrality, closeness_centrality
Directed case: --> in_degree_centrality, out_degree_centrality, in_closeness_centrality, out_closeness_centrality, betweenness_centrality
see https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.centrality.closeness_centrality.html
For betweenness, just convert the graph to undirected using DiGraph.to_undirected and compute it if path != "" then save the plot to the specified path, otherwise don't save it
In both the save and un-save cases the plot should render inside the .ipynb notebook
see "expected_outputs" for examples, your plots don't have to be identical but should be similar
Also, modify the ave_degree() function so that it prints average degree for un-directed graphs and both average in and out degree for the directed case Add the following functionality to the function plot_degree_distribution
Add a string input argument called "path" to the function plot_degree_distribution()
if path != "" then save the plot to the specified path, otherwise don't save it
In both the save and un-save cases the plot should render inside the .ipynb notebook
Modify plot_degree_distribution() so that it treats directed and un-directed graphs differently
Add a string argument called "type" to specify whether to plot degree, in-degree or out-degree for example
if not nx.is_directed(G): data=G.degree(); type=""
else:
if(type=="in"): data=G.in_degree() if(type=="out"): data=G.out_degree()
see "expected_outputs" for examples, your plots don't have to be identical but should be similar Add a boolean input argument called "fit" to the function plot_degree_distribution()
Add code so that when fit=True, the following occurs;
Use linear regression to fit the PDF and cCDF curves (in log-log space), one at a time, to provide estimates of the power-law coefficient "alpha" Both linear trend-lines should be included on the plot
Run the following code to make sure it works (see expected_outputs for reference)
import nx_tools as nxt reload(nxt)
#PARAM
N=1000
print("\n----------------UNDIRECTED BA MODEL m=3 ----------------") G=nx.barabasi_albert_graph(N,3) nxt.plot_centrality_correlation(G,path=output_folder+"/test-1.pdf") nxt.plot_degree_distribution(G,path=output_folder+"/test-2.pdf",fit=True) nxt.ave_degree(G)
print("\n----------------UNDIRECTED BA MODEL m=6 ----------------") G=nx.barabasi_albert_graph(N,6) nxt.plot_centrality_correlation(G,path=output_folder+"/test-3.pdf") nxt.plot_degree_distribution(G,path=output_folder+"/test-4.pdf",fit=True) nxt.ave_degree(G)
print("\n----------------DIRECTED RANDOM MODEL ---------------") G=nx.gnp_random_graph(N,0.2,directed=True) nxt.plot_centrality_correlation(G,path=output_folder+"/test-5.pdf") nxt.plot_degree_distribution(G,type="in",path=output_folder+"/test-6.pdf",fit=False) nxt.plot_degree_distribution(G,type="out",path=output_folder+"/test-7.pdf",fit=False) nxt.ave_degree(G)
HW-2.2.2 : Network animation
Add a new function called "def animate(networks,pos_type="circular",path="output.gif",plot_every=1):" which does the following
Takes a list called "networks", containing various individual networkX graph objects (either directed or un-directed) Plots each network (i.e. frame) and saves it to a temporary PNG "tmp-1.png, tmp-2.png ..."
directed node_size=in_degree node_color=out_degree
un-directed node_size=node_color=node_degree
use a function argument pos_type="circular" or "random" or "spring" determines which nx positional layout method to use After the loop completes
knits the png's together into a GIF saved in "path" then clean up everything by deleting all the tmp-*.png
The following code can be used to draw a bounding box which makes the transition from one frame to another appear smoother
#INITIALIZE FIGURE AND PLOT fig, ax = plt.subplots() fig.set_size_inches(5, 5)
#GET MIN AND MAX POSITION tmpx=[]; tmpy=[]
for i in pos.keys():
tmpx.append(pos[i][0])
tmpy.append(pos[i][1]) Lxmin=min(tmpx)-0.2; Lxmax=max(tmpx)+0.2 Lymin=min(tmpy)-0.2; Lymax=max(tmpy)+0.2
#DRAW BOX ax.axhline(y=Lymin) ax.axvline(x=Lxmin) ax.axhline(y=Lymax) ax.axvline(x=Lxmax)
NOTE: Given a list of png files in a list called "file_names", the GIF can be created using the following code
import imageio.v2 as imageio
images = list(map(lambda filename: imageio.imread(filename), file_names))
imageio.mimsave(path, images, duration = 10/len(file_names) ) # modify the frame duration as needed
The GIF can be viewed in ".ipynb" using the following code
from IPython.display import display,Image display(Image(data=open(path,'rb').read(), format='png', width=800))
Run the following to make sure your code is working correctly
import nx_tools as nxt reload(nxt)
#UN-DIRECTED
frames=[]
for N in range(3,40):
frames.append(nx.barabasi_albert_graph(N,2)) nxt.animate(frames,pos_type="spring",path=output_folder+"/test-8.gif")
#DIRECTED
frames=[]
for N in range(2,15):
frames.append(nx.gnp_random_graph(N,0.2,directed=True)) nxt.animate(frames,pos_type="circular",path=output_folder+"/test-9.gif")
HW-2.2.3 : Network Models
Use the file network_models.py to code the following models
random network (This is already done for you as an example)
Non-linear Preferential attachment Model (include alpha as an input parameter) Attractiveness Model
Fitness Model
Random Walk Model
Rank model
Optional: Try to develop and implement your own novel network generation model
Some of this was already done in Lab-2.1, you can use those sub-routines as a starting point.
The point of this exercise is to understand how these models work at a fundamental level. Therefore, all models MUST be coded from scratch.
i.e. don't simply return the output of a NetworkX generator
For each model, have an option for the generated model output to be directed or un-directed
Also have an option to return either the final graph, or a sequence of snapshots from the generation process, for animation. When you are done, generate an animation and apply the various analysis tools from above.
See below for an example
#RANDOM NETWORK
import nx_tools as nxt import network_models as nm reload(nxt)
reload(nm)
output_root="random" N=500
#ANIMATE
frames=nm.gnp_random_graph(20,0.2,directed=True,output="snapshots") nxt.animate(frames,pos_type="circular",path=output_folder+"/"+output_root+".gif")
#ANALYZE
G=nm.gnp_random_graph(N,0.2,directed=True,output="graph")
nxt.ave_degree(G)
nxt.network_summary(G) nxt.plot_centrality_correlation(G,path=output_folder+"/"+output_root+"-1.pdf") nxt.plot_degree_distribution(G,type="in",path=output_folder+"/"+output_root+"-2.pdf",fit=False) nxt.plot_degree_distribution(G,type="out",path=output_folder+"/"+output_root+"-3.pdf",fit=False)
Add cells below to test the other models you have coded in "network_models.py"