Creating a graph with multi-edge - python

I am using NetworkX to create a multi-edge graph in Python,
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
Nodes = [0, 1]
G.add_nodes_from(Nodes)
Edges = [(0,1)]
#Edges =[(0, 1, 0), (0, 1, 1), (0, 1, 2)]
G.add_edges_from(Edges)
nx.draw(G)
plt.savefig("path.png")
For a simple graph , defining Edges = [(0,1)] allows me to use G.add_edges_from. But, when multiple edges are defined between the nodes 0 and 1 Edges =[(0, 1, 0), (0, 1, 1), (0, 1, 2)] I couldn't use G.add_edges_from to add edges.
I would like to ask for suggestions on how to create a graph with multi-edges.

Changing G = nx.Graph() to G = nx.MultiGraph() helps in resolving the error.

Related

How to use correctly the method nx.check_planarity of networkx?

What I Want?
I have a Graph with a lot of vertices and a lot of edges. The vertices are coordinated.
I am tring to check the planarity of the graph and I always get True as an answer.
Exmple
Here is a small exmple:
pos = {1: (0, 0), 2: (0, 1), 3: (1, 1), 4: (1, 0)}
G = nx.Graph().to_undirected()
G.add_nodes_from(pos)
G.add_edge(1, 3, weight=1)
G.add_edge(2, 4, weight=1)
G.add_edge(2, 3, weight=1)
print(nx.check_planarity(G, False))
nx.draw_networkx(G, with_labels=True, pos=pos)
plt.show()
the output is:
(True, <networkx.algorithms.planarity.PlanarEmbedding object at 0x07CD3E30>)
As you can see clearly the graph is not planarity, however the result is still True
What am I doing worng?
Note that a graph is planar if it can be drawn in the Euclidean plane without any edge intersections.
In your case your graph is planar, as it is enough to swap nodes 1 and 4 to avoid edge intersections.
However, if you consider a complete graph (a complete graph Kn is planar only for n ≤ 4) you can see the difference.
>>> K4 = nx.complete_graph(4)
>>> nx.check_planarity(K4)
(True, <networkx.algorithms.planarity.PlanarEmbedding object at 0x1035df1d0>)
>>> K5 = nx.complete_graph(5)
>>> nx.check_planarity(K5)
(False, None)
You may use the answer of check_planarity to draw a possible planar layout.
import networkx as nx
import matplotlib.pyplot as plt
pos = {1: (0, 0), 2: (0, 1), 3: (1, 1), 4: (1, 0)}
G = nx.Graph().to_undirected()
G.add_nodes_from(pos)
G.add_edge(1, 3, weight=1)
G.add_edge(2, 4, weight=1)
G.add_edge(2, 3, weight=1)
is_planar, G2 = nx.check_planarity(G, False)
print(is_planar)
# plotting
fig = plt.figure()
ax = fig.add_subplot(121)
ax = plt.gca()
ax.margins(0.20)
nx.draw_networkx(G, with_labels=True, pos=pos)
ax = fig.add_subplot(122)
ax = plt.gca()
ax.margins(0.20)
nx.draw_networkx(G2, with_labels=True)
plt.show()

NetworkX add node after spring_layout to the graph

Having the following code:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_nodes_from(range(1, 10))
G.add_edges_from([(1, 3), (2, 4), (3, 4), (2,6), (1, 2), (4, 9), (9, 1)])
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True)
plt.show()
G.add_node(10)
nx.draw(G, pos, with_labels=True) # this gives the error
plt.show()
How can I add node 10 to the graph at a random position?
The error I'm actually getting is:
NetworkXError: Node 10 has no position.
How can I include the newly created node to the graph already built spring_layout?
The problem (as already noted by others) is that pos is a dict which assigns a position to each node. But when you've added a node, it doesn't update pos.
The following will find a good position for new node 10 given the existing position of all the other nodes. Basically, it calls spring_layout again, but holds all of the existing nodes in place. I've got node 10 connected to node 9.
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_nodes_from(range(1, 10))
G.add_edges_from([(1, 3), (2, 4), (3, 4), (2,6), (1, 2), (4, 9), (9, 1)])
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True)
plt.show()
G.add_node(10)
G.add_edge(9,10) #So node 10 should be close to node 9
oldnodes = list(G.nodes())
oldnodes.remove(10)
pos = nx.spring_layout(G, pos=pos, fixed=oldnodes)
nx.draw(G, pos, with_labels=True)
plt.show()
The output from spring layout is a dictionary mapping nodes to positions
{nodeid:[x,y]}. To place the new node randomly, you have to give it a random position in the pos dictionary.
Here is an example that finds the bounding box and then picks a random point somewhere inside.
import numpy as np
bounds = np.zeros((2,2)) # xy min, xymax
for pt in pos.values():
bounds[0] = np.min([bounds[0],pt], axis=0) # compare point to bounds and take the lower value
bounds[1] = np.max([bounds[1],pt], axis=0) # compare point to bounds and take the highest value
pos[10] = (bounds[1] - bounds[0]) * np.random.random(2) + bounds[0]

Networkx: how to change a color and size of same edges?

I generated a graph using networkx
import networkx as nx
G = nx.grid_graph(dim=[5,5])
nx.draw(G);
Then I compute the minimal path between two nodes using the astar algorithm
def dist(a, b):
(x1, y1) = a
(x2, y2) = b
return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5
nodes = list(G.nodes)
tmp = nx.astar_path(G,nodes[3],nodes[14],dist)
Now I would like to to modify the color and the size of the edges of the path between the nodes, where the nodes are defined by tmp
tmp
[(0, 3), (1, 3), (2, 3), (2, 4)]
You need to plot each of the network's components with its own commands. Here is a working code that demonstrates how to achieve such a plot.
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
# only relevant part is treated here
G = nx.grid_graph(dim=[5,5])
node_list = [(0, 3), (1, 3), (2, 3), (2, 4)]
edge_list = [[(0, 3), (1, 3)], [(1, 3), (2, 3)], [(2, 3), (2, 4)]]
pos = nx.spring_layout(G)
nx.draw(G, pos=pos, with_labels=True)
# draw selected nodes in green with triangle shape
nx.draw_networkx_nodes(G, pos=pos, nodelist=node_list, node_size=300, node_color='g', node_shape='^')
# draw selected edges in blue with solid line
nx.draw_networkx_edges(G, pos=pos, edgelist=edge_list, width=3.0, edge_color='blue', style='solid')
The output plot:

Color a subgraph

I have a complete graph (all nodes are directly connected by an edge), and I want to color a subset of nodes and edges over the same graph. The complete graph for N=5 is this.
N=5 COMPLETE GRAPH
Now I want to color, for example, the next subset of edges: [(0, 3), (1, 0), (2, 1), (3, 4), (4, 2)] in blue. How can I do that over the same graph?.
Thanks in advance.
If you use the draw_networkx_* functions to separately draw each part of the graph (nodes, node labels, edges, edge labels), you have fine control of what is rendered. The main trick is to produce the positions dictionary and then reuse it for each drawing function.
import networkx as nx
import itertools
import matplotlib.pyplot as plt
# produce a degree-5 complete directed graph
G = nx.DiGraph()
edges = itertools.permutations(xrange(5), 2) # see https://stackoverflow.com/a/10651524/1643946
G.add_edges_from(edges)
# specific path to highlight
elist = [(0, 3), (1, 0), (2, 1), (3, 4), (4, 2)]
# set up layout
pos = nx.circular_layout(G)
# draw it
nx.draw_networkx_nodes(G, pos)
nx.draw_networkx_labels(G, pos)
nx.draw_networkx_edges(G, pos, edge_color='k', width=0.5) # show all edges, thin lines
nx.draw_networkx_edges(G, pos, edgelist=elist, edge_color='b', width=2) # highlight elist
# turn off axis markings
plt.axis('off')
Produces a graph like this:

3D surface not transparent inspite of setting alpha

I am trying to create a 3D surface with transparency. When I try the following code below, I expect to get two semi-transparent faces of a cube. However, both the faces are opaque inspite of supplying the alpha=0.5 argument. Any pointer on why this is happening and how to fix it ? I am using Python 3.3 (IPython notebook with the QT backend)and Matplotlib 1.3.1.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.mplot3d as mp3d
bot = [(0, 0, 0),
(1, 0, 0),
(1, 1, 0),
(0, 1, 0),
]
top = [(0, 0, 1),
(1, 0, 1),
(1, 1, 1),
(0, 1, 1),
]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
face1 = mp3d.art3d.Poly3DCollection([bot], alpha=0.5, linewidth=1)
face2 = mp3d.art3d.Poly3DCollection([top], alpha=0.5, linewidth=1)
ax.add_collection3d(face1)
ax.add_collection3d(face2)
Based on David Zwicker's input, I was able to get transparency working by setting the facecolor directly as a 4-tuple with alpha.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.mplot3d as mp3d
bot = [(0, 0, 0),
(1, 0, 0),
(1, 1, 0),
(0, 1, 0),
]
top = [(0, 0, 1),
(1, 0, 1),
(1, 1, 1),
(0, 1, 1),
]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
face1 = mp3d.art3d.Poly3DCollection([bot], alpha=0.5, linewidth=1)
face2 = mp3d.art3d.Poly3DCollection([top], alpha=0.5, linewidth=1)
# This is the key step to get transparency working
alpha = 0.5
face1.set_facecolor((0, 0, 1, alpha))
face2.set_facecolor((0, 0, 1, alpha))
ax.add_collection3d(face1)
ax.add_collection3d(face2)

Categories