Keeping the orientation same of graphs in Networkx - python

I am generating a graph with 12 nodes and the adjacency matrix. However, with every run, I see a different orientation though the adjacency matrix is the same. I want to have the same orientation (with the same adjacency matrix ofcourse!) in every run. I present the current and expected output.
import networkx as nx
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
N = 2
def pos():
x, y = 1, N + 3 - 1
for _ in range(2 * N * (N + 1)):
yield (x, y)
y -= (x + 2) // (N + 3)
x = (x + 2) % (N + 3)
G = nx.Graph()
it_pos = pos()
for u in range(2 * N * (N + 1)):
G.add_node(u + 1, pos=next(it_pos))
if u % (2 * N + 1) < N:
for v in (u - 2 * N - 1, u - N - 1, u - N):
if G.has_node(v + 1):
G.add_edge(u + 1, v + 1)
elif u % (2 * N + 1) == N:
G.add_edge(u + 1, u - N + 1)
elif u % (2 * N + 1) < 2 * N:
for v in (u - 1, u - N - 1, u - N):
G.add_edge(u + 1, v + 1)
else:
for v in (u - 1, u - N - 1):
G.add_edge(u + 1, v + 1)
nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold')
D=len(G.nodes)
print(D)
fig, ax = plt.subplots(1, 1)
P=np.array([[1.00000000e-04, 1.90053824e-05, 3.70041863e-05, 5.50029902e-05,
7.30017941e-05, 8.20011961e-05, 1.00059804e-05, 9.10005980e-05,
2.80047843e-05, 1.00657843e-06, 4.60035882e-05, 1.01000000e-04]])
D=nx.draw(G, with_labels=True, node_color=[P], node_size=1000, cmap='Blues')
# -------------------------------------
norm = matplotlib.colors.Normalize(vmin=np.min(P), vmax=np.max(P))
sm = plt.cm.ScalarMappable(cmap='Blues', norm=norm)
sm.set_array([])
clb=fig.colorbar(sm)
clb.set_label('r (m)',labelpad=-50, y=1.1, rotation=0)
# -------------------------------------
plt.show()
The current output is
The expected output is

You are plotting twice with nx.draw, the first time with the node positions specified (correctly), the second time without specifying the node positions.
Presumably, you are only saving (and hence seeing) the second plot.
Delete the first call to nx.draw and substitute the second call (D=nx.draw(...)) with:
nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold', node_color=[P], cmap='Blues')

Related

Generating a computationally efficient adjacency matrix using Networkx

I am generating an adjacency matrix using networkx. For N=10, the elapsed time is 0.1 seconds. Is there a more efficient way to do it? I present the current and expected outputs of elapsed times.
import networkx as nx
import time
N=10
def TicTocGenerator():
# Generator that returns time differences
ti = 0 # initial time
tf = time.time() # final time
while True:
ti = tf
tf = time.time()
yield tf-ti # returns the time difference
TicToc = TicTocGenerator() # create an instance of the TicTocGen generator
# This will be the main function through which we define both tic() and toc()
def toc(tempBool=True):
# Prints the time difference yielded by generator instance TicToc
tempTimeInterval = next(TicToc)
if tempBool:
print( "Elapsed time: %f seconds.\n" %tempTimeInterval )
def tic():
# Records a time in TicToc, marks the beginning of a time interval
toc(False)
t = time.time()
tic()
################################################################
def pos():
x, y = 1, N + 3 - 1
for _ in range(2 * N * (N + 1)):
yield (x, y)
y -= (x + 2) // (N + 3)
x = (x + 2) % (N + 3)
G = nx.Graph()
it_pos = pos()
for u in range(2 * N * (N + 1)):
G.add_node(u+1, pos=next(it_pos))
if u % (2 * N + 1) < N:
for v in (u - 2 * N - 1, u - N - 1, u - N):
if G.has_node(v + 1):
G.add_edge(u + 1, v + 1)
elif u % (2 * N + 1) == N:
G.add_edge(u + 1, u - N + 1)
elif u % (2 * N + 1) < 2 * N:
for v in (u - 1, u - N - 1, u - N):
G.add_edge(u + 1, v + 1)
else:
for v in (u - 1, u - N - 1):
G.add_edge(u + 1, v + 1)
nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold')
################################################################
toc()
The current output is
Elapsed time: 0.10 seconds.
The expected output is
Elapsed time: 0.000001 seconds.

Arrows on edges in a graph using Networkx

I have a graph with nodes and edges. The code colors the array Edges with the array Weights as shown in the current output. Is it possible to put arrows on the array elements in Edges as displayed in the expected output? I want arrows on specific edges according to Edges, not all.
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.cm import ScalarMappable
N = 1
def pos():
x, y = 1, N + 3 - 1
for _ in range(2 * N * (N + 1)):
yield (x, y)
y -= (x + 2) // (N + 3)
x = (x + 2) % (N + 3)
G = nx.Graph()
it_pos = pos()
for u in range(2 * N * (N + 1)):
G.add_node(u + 1, pos=next(it_pos))
if u % (2 * N + 1) < N:
for v in (u - 2 * N - 1, u - N - 1, u - N):
if G.has_node(v + 1):
G.add_edge(u + 1, v + 1)
elif u % (2 * N + 1) == N:
G.add_edge(u + 1, u - N + 1)
elif u % (2 * N + 1) < 2 * N:
for v in (u - 1, u - N - 1, u - N):
G.add_edge(u + 1, v + 1)
else:
for v in (u - 1, u - N - 1):
G.add_edge(u + 1, v + 1)
nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold')
Edges=np.array([[1,2],[1,3],[1,4]])
Weights=np.array([[1.7],[2.9],[8.6]])
flat_weights = Weights.flatten()
weights_normalized = [x / max(flat_weights) for x in flat_weights]
edge_weight_map = dict(zip([tuple(e) for e in Edges.tolist()],weights_normalized))
my_cmap = plt.cm.get_cmap('Oranges')
colors = my_cmap([edge_weight_map.get(tuple(e), 0) for e in Edges.tolist()])
pos = nx.get_node_attributes(G, 'pos')
sm = ScalarMappable(cmap=my_cmap, norm=plt.Normalize(0,max(flat_weights)))
nx.draw_networkx_edges(G, pos, edge_color=colors,
edgelist=[tuple(e) for e in Edges.tolist()],
width=5);
plt.colorbar(sm)
The current output is
The expected output is
You are almost there.
First, you will need to create a directed graph instead of an undirected graph:
G = nx.DiGraph()
Second, DiGraph objects are plotted with arrow heads by default, so you need to specify arrows=False in the call to nx.draw(...).
nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold', arrows=False)
If you now plot your selected edges separately, they come with arrow heads (per default).

Adjusting node numbering in Networkx

The following code generate adjacency matrix of a specific network. However, I want the node numbering to occur in a certain way and remain fixed and not fluctuate with every run. I present the current and expected output.
import matplotlib.pyplot as plt
import networkx as nx
N = 2
G = nx.Graph()
for u in range(2 * N * (N + 1)):
if u % (2 * N + 1) < N:
for v in (u - 2 * N - 1, u - N - 1, u - N):
if G.has_node(v):
G.add_edge(u, v)
elif u % (2 * N + 1) == N:
G.add_edge(u, u - N)
elif u % (2 * N + 1) < 2 * N:
for v in (u - 1, u - N - 1, u - N):
G.add_edge(u, v)
else:
for v in (u - 1, u - N - 1):
G.add_edge(u, v)
A=nx.adjacency_matrix(G).todense()
print([A])
nx.draw(G,with_labels=True, font_weight='bold')
The current output is
The expected output is
Here is a possible solution:
import networkx as nx
N = 2
def pos():
x, y = 1, N + 3 - 1
for _ in range(2 * N * (N + 1)):
yield (x, y)
y -= (x + 2) // (N + 3)
x = (x + 2) % (N + 3)
G = nx.Graph()
it_pos = pos()
for u in range(2 * N * (N + 1)):
G.add_node(u + 1, pos=next(it_pos))
if u % (2 * N + 1) < N:
for v in (u - 2 * N - 1, u - N - 1, u - N):
if G.has_node(v + 1):
G.add_edge(u + 1, v + 1)
elif u % (2 * N + 1) == N:
G.add_edge(u + 1, u - N + 1)
elif u % (2 * N + 1) < 2 * N:
for v in (u - 1, u - N - 1, u - N):
G.add_edge(u + 1, v + 1)
else:
for v in (u - 1, u - N - 1):
G.add_edge(u + 1, v + 1)
nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold')
This is the result of the code above:
Here I've used the pos() function to generate each node position. These positions are saved as tuples (x, y) within each node as a label. And they're eventually used to draw the graph.

Plot the multiple values returned by a function

My function returns 2 different values which I want to utilise in 2 different graphs using Matplotlib. How can I achieve it?
def option_value_european_put(T, m, r, sigma, mu, E):
cost_value_at_initial_t_put = []
portfolio_payoff_put = []
for e in E:
delta_t = T / m
u = (1 + (sigma * math.sqrt(delta_t)) * (math.sqrt(1 + ((mu ** 2) * delta_t) / math.pow(sigma, 2))))
v = 2 - u
option_stock_price_matrix_put = np.zeros((m + 1, m + 1))
sum = 0
k = m
start = m
for i in range(m + 1):
option_stock_price_matrix_put[i][start] = max(
(e - stock_price_binomial_model(
mu, sigma, T, m,
S
)[i][start], 0)
)
for j in range(m - 1, -1, -1):
for i in range(0, j + 1):
v_plus = option_stock_price_matrix_put[i][j + 1]
v_minus = option_stock_price_matrix_put[i + 1][j + 1]
v_t = ((((v_plus - v_minus) / (u - v)) * (1 + r * delta_t)) + (u * v_minus - v * v_plus) / (u - v)) / (
1 + r * delta_t)
option_stock_price_matrix_put[i][j] = v_t
cost_value_at_initial_t_put.append(option_stock_price_matrix_put[0][0])
for i in range(0, m+1):
sum = sum + option_stock_price_matrix_put[k][i]
portfolio_return_average = math.average(sum)
portfolio_payoff_put.append(portfolio_return_average-option_stock_price_matrix_put[0][0] )
return cost_value_at_initial_t_put, portfolio_payoff_put
I want to use cost_value_at_initial_t_put in 1 Matplotlib plot and the other value in another plot. How can I use it?
Supposing that cost_value_at_initial_t_put and portfolio_payoff_cut are both lists you can create subplots:
import matplotlib.pyplot as plt
fig, (ax_cost, ax_payoff) = plt.subplots(nrows=2)
ax_cost.plot(cost_value_at_initial_t_put)
ax_payoff.plot(portfolio_payoff_cut)

Overflow and Invalid Values encountered in double scalars - Nonlinear PDE Solving

I am seeking to find a finite difference solution to the 1D Nonlinear PDE
u_t = u_xx + u(u_x)^2
Code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import math
'''
We explore three different numerical methods for solving the PDE, with solution u(x, t),
u_t = u_xx + u(u_x)^2
for (x, t) in (0, 1) . (0, 1/5)
u(x, 0) = 40 * x^2 * (1 - x) / 3
u(0, t) = u(1, t) = 0
'''
M = 30
dx = 1 / M
r = 0.25
dt = r * dx**2
N = math.floor(0.2 / dt)
x = np.linspace(0, 1, M + 1)
t = np.linspace(0, 0.2, N + 1)
U = np.zeros((M + 1, N + 1)) # Initial array for solution u(x, t)
U[:, 0] = 40 * x**2 * (1 - x) / 3 # Initial condition (: for the whole of that array)
U[0, :] = 0 # Boundary condition at x = 0
U[-1, :] = 0 # Boundary condition at x = 1 (-1 means end of the array)
'''
Explicit Scheme - Simple Forward Difference Scheme
'''
for q in range(0, N - 1):
for p in range(0, M - 1):
b = 1 / (1 - 2 * r)
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
U[p, q + 1] = b * (U[p, q] + r * (U[p + 1, q + 1] + U[p - 1, q + 1]) - C)
T, X = np.meshgrid(t, x)
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(T, X, U)
#fig.colorbar(surf, shrink=0.5, aspect=5) # colour bar for reference
ax.set_xlabel('t')
ax.set_ylabel('x')
ax.set_zlabel('u(x, t)')
plt.tight_layout()
plt.savefig('FDExplSol.png', bbox_inches='tight')
plt.show()
The code I use produces the following error:
overflow encountered in double_scalars
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
invalid value encountered in double_scalars
U[p, q + 1] = b * (U[p, q] + r * (U[p + 1, q + 1] + U[p - 1, q + 1]) - C)
invalid value encountered in double_scalars
C = r * U[p, q] * (U[p + 1, q] - U[p, q])**2
Z contains NaN values. This may result in rendering artifacts.
surf = ax.plot_surface(T, X, U)
I've looked up these errors and I assume that the square term generates values too small for the dtype. However when I try changing the dtype to account for a larger range of numbers (np.complex128) I get the same error.
The resulting plot obviously has most of its contents missing. So, my question is, what do I do?
Discretisation expression was incorrect.
Should be
for q in range(0, N - 1):
for p in range(0, M - 1):
U[p, q + 1] = r * (U[p + 1, q] - 2 * U[p, q] + U[p - 1, q]) + r * U[p, q] * (U[p + 1, q] - U[p, q])

Categories

Resources