'Sort a given set of nodes from a graph based on the following rules:
# - if A -> B and not B -> A, then we have A < B
# - if A -> B and B -> A, then the ordering is undefined
Following the above rules gives us a quasi-topological sorting of nodes in the graph. It also works for cyclic
graphs.
:param networkx.DiGraph graph: A local transition graph of the function.
:param iterable nodes: A list of nodes to sort. None if you want to sort all nodes inside the graph.
:return: A list of ordered nodes.
:rtype: list'

@staticmethod
def quasi_topological_sort_nodes(graph, nodes=None):

    if (graph.number_of_nodes() == 1):
        return graph.nodes()
    graph_copy = networkx.DiGraph()
    sccs = [scc for scc in networkx.strongly_connected_components(graph) if (len(scc) > 1)]
    for (src, dst) in graph.edges_iter():
        scc_index = CFGUtils._components_index_node(sccs, src)
        if (scc_index is not None):
            src = SCCPlaceholder(scc_index)
        scc_index = CFGUtils._components_index_node(sccs, dst)
        if (scc_index is not None):
            dst = SCCPlaceholder(scc_index)
        if (isinstance(src, SCCPlaceholder) and isinstance(dst, SCCPlaceholder) and (src == dst)):
            continue
        if (src == dst):
            continue
        graph_copy.add_edge(src, dst)
    tmp_nodes = networkx.topological_sort(graph_copy)
    ordered_nodes = []
    for n in tmp_nodes:
        if isinstance(n, SCCPlaceholder):
            CFGUtils._append_scc(graph, ordered_nodes, sccs[n.scc_id])
        else:
            ordered_nodes.append(n)
    if (nodes is None):
        return ordered_nodes
    nodes = set(nodes)
    ordered_nodes = [n for n in ordered_nodes if (n in nodes)]
    return ordered_nodes
