Generating graphs for given degree sequence in Python or R - python

I am trying to learn if in Python or R, there exist within the graph-theory related modules features that would enable one to start from a degree distribution (or expressed as a sequence once we set the number of vertices), and generate (random) graphs that satisfy the prescribed degree sequence.
As an example, we might be given the following distribution: p=(0.179,0.49,0.34) which are the probabilities of degree values 1,2 and 3 respectively. So we can set the number of vertices, n=500, map p to a degree sequence deseq list: filled with 0.179*n times of 1, and so on for the rest.
Any pointers towards previously discussed cases for such problems or library suggestions would be very helpful.

Here's an attempt to answer my own question after having learned how to use igraph in R and Python for generating the desired type of graphs.
In R:
For the purposes of this example, let's suppose the following degree sequence: total nodes n=20, 5,10 and 5 nodes with degrees 1,2, and 3 respectively. We create the degree sequence using c() and rep(). Then we'll use sample_degseq() from igraph to generate a graph corresponding to the above degree sequence. Then we'll draw its degree histogram to sanity check.
First install and call the igraph module in the R console using:
install.packages("igraph")
library(igraph)
Now we can proceed as described:
degreels <- c(rep(1,5),rep(2,10),rep(3,5))
graph <- sample_degseq(degreels, method="simple")
degreehist <- hist(degree(graph))
is.connected(graph)
In Python:
Now let's do the exact same thing with the igraph module in Python:
To install see here.
import igraph as ig
import matplotlib.pyplot as plt
degcounts = [5,10,5]
degreels = []
for i in range(len(degcounts)):
degreels += degcounts[i]*[i+1]
graph = ig.GraphBase.Degree_Sequence(degreels,method="simple")
plt.hist(graph.degree())
plt.show()
and the obtained histogram:

I don't know how much have you already researched on the topic but there is a pretty wellknown package in R and module in Python called igraph. It might have what you seek for.

For Python, the networkx package also provides what you are looking for.
In particular, the functionalities regarding random graphs from degree sequences (e.g. configuration_model with the idea from #Alex_6's comment) might be helpful.

Related

Problems re-implementing the fipy mesh20x20 example from my own IDE

I am currently using fipy but am still relatively new to the nuiances associated with the package. While I have been able to regenerate the desired heatmap from the examples folder in for the mesh20x20 diffusion example using the command line, I have struggled to replicate it within a Spyder IDE. I am using python version 3.8 . It is simple enough to generate it using the "examples" folder from the command line the command line image generated, however, when I attempt to "re-program" it I end up with iterations of the following. the following result. I am hoping to be able to regenerate the smooth color transition from the examples folder, as opposed to the discrete dichromatic option that I have been limited to at present. I believe there is some issues with the viewer in some capacity I believe some related issues may have cropped up in the past for others, potentially as it relates to colorbar reformatting, though I have not yet been capable of effectively implementing these workarounds to generate the desired imagery. datamin and datamax in Viewer() did not work
I would be greatly indebted for any assitance the community could provide.
from fipy.terms.transientTerm import TransientTerm
from fipy.terms.implicitDiffusionTerm import ImplicitDiffusionTerm
from fipy.terms.explicitDiffusionTerm import ExplicitDiffusionTerm
from fipy.meshes.nonUniformGrid2D import NonUniformGrid2D
from fipy.variables.cellVariable import CellVariable
from fipy.viewers.matplotlibViewer.matplotlib2DViewer import Matplotlib2DViewer
####
#Global Inputs
D=1
steps=10
#Dimensional Inputs
nx=20
dx=1
ny=20
dy=1
L=dx*nx
#Temporal Inputs
#nt=20
#dt=1
#cell variable initial values
value=0
#construct mesh from dimensional pts
mesh=NonUniformGrid2D(nx=nx, dx=dx, ny=ny, dy=dy)
#construct term variables phi with name, mesh design
phi=CellVariable(name="solutionvariable", mesh=mesh, value=0)
#construct boundary conditions
#dirichlet ---> we can an automatic application of neumann to top right and bottom left
valueTopLeft=0
valueBottomRight=1
#assign boundary conditions to a face or cell
X, Y=mesh.faceCenters
facesTopLeft=((mesh.facesLeft & (Y > L/2 )) | (mesh.facesTop &( X < L/2)))
facesBottomRight=((mesh.facesRight & (Y < L/2)) | (mesh.facesBottom & (X > L/2)))
#constrain variables
phi.constrain(valueTopLeft, facesTopLeft)
phi.constrain(valueBottomRight, facesBottomRight)
#equation construction
eq=TransientTerm()==ExplicitDiffusionTerm(coeff=D)
#equation solving and either viewing and/or extraction
timestepduration=0.9 *(dx**2)/(2*D)
for step in range(steps):
eq.solve(var=phi, dt=timestepduration)
print(phi[step])
viewer=Matplotlib2DViewer(vars=phi, datamin=0, datamax=1)
viewer.axes.set_title("Solutionvbl(Step %d)" % (step+1,))
Figured it out I think. I was using ExplicitDiffusion and the example utilizes ImplicitDiffusion. When I tried this all I got back was a blank monochromatic image (and returned zeros for my phi[step] at the end. I am happy to report that once a "kickstart" value is provided in the value section for cellVariable (I used 0.001), and utilized in conjunction with ImplicitDiffusion, and the timestepduration is increased from its limit of 0.9x**2/2D to the utilized 9x**2/2D used in the example documentation it more or less adheres to the image generated when run from the command line. Grateful to have this sorted. Hope this provides assistance to anyone else who might run into a similar problem.

How to classify the points by a specific polylline

There is a boundary inside China, which divide the region as North-South. I have drawn this boundary as a polyline format shapefile Download link.
I want to divide those points in the following figures into "North" and "South". Is there any useful function in Python can achieve this.
fiona has point.within function to test points within/out a polygon, but I have not searched a suitable function to divide multiple points by polyline.
Any advices or tips would be appreciated!
updated
According to the valuable suggestion made by Prune, I worked it out. The codes are provided as follows:
from shapely.geometry import shape
from shapely.geometry import LineString
# loading the boundary layer
import fiona
fname = './N-S_boundary.shp'
line1 = fiona.open(fname)
line1 = shape(line1.next()['geometry'])
# set a end point which is the southernmost for all stations.
end_point = (dy[dy['lat']==dy['lat'].min()]['lon'].values[0],dy[dy['lat']==dy['lat'].min()]['lat'].values[0])
# loop all monitoring stations for classification
dy['NS']= np.nan
for i in range(0,len(dy),1):
start_point = (dy['lon'].iloc[i],dy['lat'].iloc[i])
line2 = LineString([start_point, end_point])
if line1.intersection(line2).is_empty:
dy["NS"].iloc[i]='S'
else:
dy["NS"].iloc[i]='N'
color_dict= {'N':'steelblue','S':'r'}
dy['site_color']=dy['NS'].map(color_dict)
You can apply a simple property from topology.
First, make sure that your boundary partitions the universe (all available points you're dealing with). You may need to extend the boundary through the ocean to finish this.
Now, pick any reference point that is labeled as to the region -- to define "North" and "South", you must have at least one such point. w.l.o.g. assume it's a "South" point called Z.
Now, for each point A you want to classify, draw a continuous path (a straight one is usually easiest, but not required) from A to Z. Find the intersections of this path with the boundary. If you have an even quantity of intersections, then A is in the same class ("South") as Z; other wise, it's in the other class ("North").
Note that this requires a topological property of "partition" -- there are no tangents to the boundary line: if your path touches the boundary, it must cross completely.

Difference between Matlab delaunayn and Scipy Delaunay

I'm trying to replicate an N dimensional Delaunay triangulation that is performed by the Matlab delaunayn function in Python using the scipy.spatial.Delaunay function. However, while the Matlab function gives me the result I want and expect, scipy is giving me something different. I find this odd considering both are wrappers of the QHull library. I assume Matlab is implicitly setting different parameters in its call. The situation I'm trying to replicate between the two of them is found in Matlab's documentation.
The set up is to have a cube with a point in the center as below. The blue lines I provided to help visualize the shape, but they serve no purpose or meaning for this problem.
The triangulation I expect from this results in 12 simplices (listed in the Matlab example) and looks like the following.
However this python equivalent produces "extra" simplices.
x = np.array([[-1,-1,-1],[-1,-1,1],[-1,1,-1],[1,-1,-1],[1,1,1],[1,1,-1],[1,-1,1],[-1,1,1],[0,0,0]])
simp = scipy.spatial.Delaunay(x).simplices
The returned variable simp should be an M x N array where M is the number of simplices found (should be 12 for my case) and N is the number of points in the simplex. In this case, each simplex should be a tetrahedron meaning N is 4.
What I'm finding though is that M is actually 18 and that the extra 6 simplices are not tetrahedrons, but rather the 6 faces of the cube.
What's going on here? How can I limit the returned simplices to only be tetrahedrons? I used this simple case to demonstrate the problem so I'd like a solution that isn't tailored to this problem.
EDIT
Thanks to an answer by Amro, I was able to figure this out and I can get a match in simplices between Matlab and Scipy. There were two factors in play. First, as pointed out, Matlab and Scipy use different QHull options. Second, QHull returns simplices with zero volume. Matlab removes these, Scipy doesn't. That was obvious in the example above because all 6 extra simplices were the zero-volume coplanar faces of the cube. These can be removed, in N dimensions, with the following bit of code.
N = 3 # The dimensions of our points
options = 'Qt Qbb Qc' if N <= 3 else 'Qt Qbb Qc Qx' # Set the QHull options
tri = scipy.spatial.Delaunay(points, qhull_options = options).simplices
keep = np.ones(len(tri), dtype = bool)
for i, t in enumerate(tri):
if abs(np.linalg.det(np.hstack((points[t], np.ones([1,N+1]).T)))) < 1E-15:
keep[i] = False # Point is coplanar, we don't want to keep it
tri = tri[keep]
I suppose the other conditions should be addressed, but I'm guaranteed that my points contain no duplicates already, and the orientation condition appears to have no affect on the outputs that I can discern.
Some notes comparing MATLAB and SciPy functions:
According to MATLAB docs, by default it uses Qt Qbb Qc Qhull options for 3-dimensional input, while SciPy uses Qt Qbb Qc Qz.
not sure if it matters, but your NumPy array is not in the same order as the points created with ndgrid in MATLAB.
In fact if you look at the MATLAB code in edit delaunayn.m, you can see three extra steps performed:
first it merges duplicate points mergeDuplicatePoints (this is not an issue in your case)
then it enforces an orientation convention for the points (see the code)
finally after getting the result from Qhull (implemented as a MEX-function qhullmx), there is the following comment above a few lines of code:
Strip the zero volume simplices that may have been created by the presence of degeneracy.
Since the file is copyrighted, I won't post the code here, but you can check it on your end.

How do I find the number of vertices in a graph created by iGraph in python?

I'm writing a function that receives a graph as input.
The very first thing I need to do is determine the order of the graph (that is, the number of vertices in the graph).
I mean, I could use g.summary() (which returns a string that includes the number of vertices), but then I'd have parse the string to get at the number of vertices -- and that's just nasty.
To get the number of edges I'm using len(g.get_edgelist()), which works. But there is no g.get_vertexlist(), so I can't use the same method.
Surely there is an easy way to do this that doesn't involve parsing strings.
g.vcount() is a dedicated function in igraph that returns the number of vertices. Similarly, g.ecount() returns the number of edges, and it is way faster than len(g.get_edgelist()) as it does not have to construct the full edge list in advance.
As some functions in igraph have been renamed in meantime, I found the answers here out of date. What the docs suggest now is calling
gorder(g)
which works for me. Analogy for ecount is
gsize(g) # vcount(g) still works, but not g.vcount()
It's useful to note that help pages are cleverly redirected, so
?vcount
brings you to gorder docs etc.
g.vs should return the sequence of vertices as an igraph.VertexSeq object:
>>> from igraph import Graph
>>> g = Graph.Formula("A-B")
>>> g.vs["name"]
['A', 'B']
>>> len(g.vs)
2
>>> g.vcount()
2
Edit: As #Tamas mentions below, g.vcount() will also return the number of vertices. Example edited to account for this.

How can I visualize a Graph in (interactive) 3D with Python?

I have a Graph in Python like this one:
# Each element is a tuple with coordinates (x,y,z).
# The index is the id of the vertex
vertexList = [(0,0,0),(1,0,0),(1,1,0),(0,1,0),
(0,0,1),(1,0,1),(1,1,1),(0,1,1)]
# Each element is a tuple with the vertex-ids and a weight (vertexId1, vertexId2, weight)
edgeList = [(0,1,1), (1,2,1), (2,3,1), (3,0,1),
(0,4,1),
(4,5,1), (5,6,1), (6,7,1), (7,4,1)]
graph = (vertexList, edgeList)
This is a small example. The application I wrote uses graphs with about 100 vertexes and 300 edges.
I would like to visualize this with python, preferably with a library which is available for Ubuntu. It would be great if it were possible to move the graph in the 3D-visualisation.
What I've done so far
At the moment I use UBIGRAPH. The visualization and interaction is very good, but I can't specify coordinates for the vertexes:
def visulizeGraph(Graph):
vertexList, edgeList = Graph
server_url = 'http://127.0.0.1:20738/RPC2'
server = xmlrpclib.Server(server_url)
G = server.ubigraph;
G.clear()
for identifier, vertex in enumerate(vertexList):
G.new_vertex_w_id(identifier)
for vertex1, vertex2, weight in edgeList:
x1, y1, z1 = vertexList[vertex1]
x2, y2, z2 = vertexList[vertex2]
G.new_edge(vertex1, vertex2)
matplot
I've found matplotlib, but its very big. I didn't find an example which does what I like, but I might have missed it. Its available for Ubuntu.
vtk
The same problem as with matplot. If you could give me some working examples it might be the best solution.
When you looked at matplotlib, did you see mplot3d? This may be what you require.
MPlot3D
If not, I'm sorry I probably can't help any more than that.
I've not used this myself yet (beyond running example scripts) but mayavi2 looks promising. It comes bundled with the enthought python distribution.
Also, a little of topic as it's not in your question, but networkx is pretty nice if your working with graphs in python.
Hope this helps a bit.

Categories