import numpy as np
import networkx as nx
from functools import reduce
import matplotlib.pyplot as plt

connect_graph = np.array([[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1],
[0, 0, 1, 0, 0]])

def ring_add(a, b):
return a or b
def ring_multi(a, b):
return a and b
def dot_product(i, j):
row = connect_graph[i]
column = connect_graph[:,j]
return reduce(ring_add, [ring_multi(a, b) for a, b in zip(row, column)])

def next_generation(connect_graph):
candidate_number = connect_graph.shape[0]
new_connect_graph = np.zeros((candidate_number, candidate_number))
for i in range(candidate_number):
for j in range(candidate_number):
new_connect_graph[i][j] = dot_product(i,j)
return new_connect_graph

new_connect_graph = next_generation(connect_graph)

def draw_graph(connect_graph):
G = nx.DiGraph()
candidate_number = connect_graph.shape[0]
node_name = list(range(candidate_number))
G.add_nodes_from(node_name)
for i in range(candidate_number):
for j in range(candidate_number):
if connect_graph[i][j]:
G.add_edge(i, j)
nx.draw(G, with_labels=True)
plt.show()

draw_graph(new_connect_graph)