In [1]:
from IPython.display import display
from IPython.html import widgets
from d3networkx import ForceDirectedGraph, EventfulGraph


:0: FutureWarning: IPython widgets are experimental and may change in the future.

Prime Factor Finder

When an eventful graph is created, create a widget to view it.


In [2]:
def create_widget(graph):
    display(ForceDirectedGraph(graph))
EventfulGraph.on_constructed(create_widget)

Code that populates the graph.


In [4]:
BACKGROUND = '#6B8A87'
PARENT_COLOR = '#3E5970'
FACTOR_COLOR = '#424357'
EDGE_COLOR = '#000000'
PRIME_COLOR = '#333241'
CHARGE = -200
MIN_NODE_RADIUS = 15.0
START_NODE_RADIUS = 65.0

is_int = lambda x: int(x) == x
factor = lambda x: [i + 1 for i in range(x-1) if  i != 0 and is_int(x / (float(i) + 1.0))]
calc_node_size = lambda x, start_x: max(float(x)/start_x * START_NODE_RADIUS, MIN_NODE_RADIUS)
calc_edge_length = lambda x, parent_x, start_x: calc_node_size(x, start_x) + calc_node_size(parent_x, start_x)
    
def add_node(graph, value, **kwargs):
    graph.add_node(len(graph.node), charge=CHARGE, strokewidth=0, value=value, label=value, font_size='18pt', dy='8', **kwargs)
    return len(graph.node) - 1
    
def add_child_node(graph, x, number, start_number, parent):
    index = add_node(graph, x, fill=FACTOR_COLOR, r='%.2fpx' % calc_node_size(x, start_number))
    graph.add_edge(index, parent, distance=calc_edge_length(x, number, start_number), stroke=EDGE_COLOR, strokewidth='3px')
    return index

def plot_primes(number, start_number=None, parent=None, graph=None, delay=0.0):
    start_number = start_number or number
    if graph is None:
        graph = EventfulGraph(sleep=delay)
        graph.node.clear()
    parent = parent or add_node(graph, number, fill=PARENT_COLOR, r='%.2fpx' % START_NODE_RADIUS)
    
    factors = factor(number)
    if len(factors) == 0:
        graph.node[parent]['fill'] = PRIME_COLOR
    for x in factors:
        index = add_child_node(graph, x, number, start_number, parent)
        plot_primes(x, start_number, parent=index, graph=graph)

GUI for factoring a number.


In [5]:
box = widgets.VBox()
header = widgets.HTML(value="<h1>Number Factorizer</h1><br>")
number = widgets.IntSlider(description="Number:", value=100)
speed = widgets.FloatSlider(description="Delay:", min=0.0, max=0.2, value=0.1, step=0.01)

subbox = widgets.HBox()
button = widgets.Button(description="Calculate")
subbox.children = [button]

box.children = [header, number, speed, subbox]
display(box)

box._dom_classes = ['well', 'well-small']

def handle_caclulate(sender):
    plot_primes(number.value, delay=speed.value)
button.on_click(handle_caclulate)

In [ ]: