Semiring

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)