Integer divisors

This Jupyter notebook provides an example of using the Python package gravis. The .ipynb file can be found here.

It demonstrates how natural numbers (positive integers) and their divisibility relations can be represented as a directed graph.

References

Data generation

A graph of integers and their divisibility relation can be created from following basic ideas

  • Each integer (up to some maximum) is represented by a node.

  • If an integer is divisible (without remainder) by another integer, an edge is drawn from the smaller to the larger integer to represent their divisibility relation. Prime numbers are only divisible by 1 and themselves, hence they have zero incoming edges if these trivial cases are excluded, i.e. using integers from 2 upwards and not testing if an integer can be divided by itself.

  • Different integers have quite different numbers of divisors. The number of divisors for a certain integer can be represented by node size (=more incoming edges means more divisors, shown by a larger node size) and additionally by node colors (a certain number of incoming edges is shown by a certain color).

[1]:
import networkx as nx
import gravis as gv
[2]:
start = 2
end = 100

# Create the graph: assign edges between divisible integers
graph = nx.DiGraph()
for i in range(start, end+1):
    graph.add_node(i)
    for j in range(start, i):
        if i % j == 0:
            graph.add_edge(j, i)

# Assign node properties: size, color, position
degree_to_color_map = {0: '#df4828', 1: '#6059a0', 2: '#69b190', 3: '#ddaa3c', 4: '#a6be54'}
for i in graph.nodes:
    node = graph.nodes[i]
    in_degree = graph.in_degree(i)
    node['size'] = 10 + in_degree * 5
    node['x'] = -2500 + i * 50
    node['y'] = -i ** 1.618 + 1000
    #node['y'] = node['size'] / 2
    node['color'] = degree_to_color_map.get(in_degree, 'black')
    node['hover'] = '{} has divisors'.format(i)

# Assign edge properties: color (from source node)
for e in graph.edges:
    i, j = e
    graph.edges[e]['color'] = graph.nodes[i]['color']
    graph.nodes[j]['hover'] += ' {}'.format(i)

graph.graph['edge_opacity'] = 0.6
[3]:
gv.d3(graph, node_hover_neighborhood=True, edge_curvature=0.75, zoom_factor=0.15, use_centering_force=False)
[3]:
Details for selected element
General
App state
Display mode
Export
Data selection
Graph
Node label text
Edge label text
Node size
Minimum
Maximum
Edge size
Minimum
Maximum
Nodes
Visibility
Size
Scaling factor
Position
Drag behavior
Hover behavior
Node images
Visibility
Size
Scaling factor
Node labels
Visibility
Size
Scaling factor
Rotation
Angle
Edges
Visibility
Size
Scaling factor
Form
Curvature
Hover behavior
Edge labels
Visibility
Size
Scaling factor
Rotation
Angle
Layout algorithm
Simulation
Many-body force
Strength
Theta
Min
Max
Links force
Collision force
Radius
Strength
x-positioning force
Strength
y-positioning force
Strength
Centering force