def colour_node_with_highest_degree(graph, working_graph, colour, visualization=None):
    node = utils.get_node_wih_highest_degree(working_graph, utils.Colours.grey)

    # When all left nodes are already coloured
    if node is None:
        node = utils.get_node_wih_highest_degree(graph, utils.Colours.grey, graph.neighbors(working_graph.nodes()[0]))

        if visualization is not None:
            visualization.snapshot(graph, working_graph)
        graph.node[node]['colour'] = colour

        working_graph.remove_nodes_from(set(working_graph.nodes()).intersection(graph.neighbors(node)))

        if visualization is not None:
            visualization.snapshot(graph, working_graph)
        return

    if visualization is not None:
            working_graph.node[node]['colour'] = utils.Colours.black
            visualization.snapshot(graph, working_graph)
    graph.node[node]['colour'] = colour

    utils.delete_node_and_neighbors(working_graph, node)

    if visualization is not None:
        visualization.snapshot(graph, working_graph)
def simultaneous_greedy(graph, filename=None):
    """
        Solves problem using greedy algorithm, but in contrast to greedy.greedy colouring
        both colours is simultaneous. Returns None if solution does not exist.
        If filename is not None, takes snapshots after each node is coloured and generates visualization.
        Result is saved in <filename>.gif

        :return: networkx.Graph
    """
    # Check if solution exist
    for node in graph.nodes():
        if graph.degree(node) == 0:
            return None

    working_graph_red = graph.copy()
    working_graph_blue = graph.copy()

    # colour node of first degree and thier neighbour
    for node in graph.nodes(data=True):
        node_id = node[0]
        if graph.degree(node_id) == 1:
            neighbour_id = graph.neighbors(node_id)[0]
            if graph.node[neighbour_id]['colour'] == utils.Colours.red:
                graph.node[node_id]['colour'] = utils.Colours.blue
                utils.delete_node_and_neighbors(working_graph_blue, node_id)
            elif graph.node[neighbour_id]['colour'] == utils.Colours.blue:
                graph.node[node_id]['colour'] = utils.Colours.red
                utils.delete_node_and_neighbors(working_graph_red, node_id)
            else:
                graph.node[node_id]['colour'] = utils.Colours.blue
                utils.delete_node_and_neighbors(working_graph_blue, node_id)
                graph.node[neighbour_id]['colour'] = utils.Colours.red
                utils.delete_node_and_neighbors(working_graph_red, neighbour_id)

    visualization = None
    if filename is not None:
        visualization = utils.GraphVisualization(3)
        visualization.snapshot(graph, working_graph_red, working_graph_blue)

    while working_graph_red.number_of_nodes() > 0 or working_graph_blue.number_of_nodes() > 0:
        if working_graph_red.number_of_nodes() > 0:
            colour_node_with_highest_degree(graph, working_graph_blue, working_graph_red, utils.Colours.red, visualization)
        if working_graph_blue.number_of_nodes() > 0:
            colour_node_with_highest_degree(graph, working_graph_red, working_graph_blue, utils.Colours.blue, visualization)

    if visualization is not None:
        visualization.generate_gif(filename)

    return graph