예제 #1
0
파일: eppstein.py 프로젝트: BIGtigr/xgcode
def get_tree_type(V, U):
    max_degree = graph.g_to_max_degree(V, U)
    if max_degree < 3:
        return TREE_TYPE_PATH
    elif max_degree == 3:
        nd = graph.g_to_nd(V, U)
        edge_to_max_degree = get_subtree_max_degree_map(V, U)
        # Count the number of vertices
        # that see a degree three vertex in three directions.
        ncenters = 0
        for v, neighbors in nd.items():
            nvisible = 0
            for w in neighbors:
                if edge_to_max_degree[(v, w)] == 3:
                    nvisible += 1
            if nvisible == 3:
                ncenters += 1
        if ncenters == 0:
            return TREE_TYPE_RAKE
        elif ncenters == 1:
            return TREE_TYPE_TRIPLE_RAKE
        else:
            return TREE_TYPE_OTHER
    else:
        return TREE_TYPE_OTHER
예제 #2
0
def get_tree_type(V, U):
    max_degree = graph.g_to_max_degree(V, U)
    if max_degree < 3:
        return TREE_TYPE_PATH
    elif max_degree == 3:
        nd = graph.g_to_nd(V, U)
        edge_to_max_degree = get_subtree_max_degree_map(V, U)
        # Count the number of vertices
        # that see a degree three vertex in three directions.
        ncenters = 0
        for v, neighbors in nd.items():
            nvisible = 0
            for w in neighbors:
                if edge_to_max_degree[(v, w)] == 3:
                    nvisible += 1
            if nvisible == 3:
                ncenters += 1
        if ncenters == 0:
            return TREE_TYPE_RAKE
        elif ncenters == 1:
            return TREE_TYPE_TRIPLE_RAKE
        else:
            return TREE_TYPE_OTHER
    else:
        return TREE_TYPE_OTHER
예제 #3
0
파일: mrate.py 프로젝트: BIGtigr/xgcode
def R_to_distn_nonspectral(R):
    """
    The rate matrix must be irreducible and reversible.
    It is not necessarily symmetric.
    If the rate matrix is symmetric then this function is overkill
    because the stationary distribution would be uniform.
    """
    nstates = len(R)
    V = set(range(nstates))
    E = set()
    for i in range(nstates):
        for j in range(i):
            if R[i, j]:
                if not R[j, i]:
                    raise MatrixUtil.MatrixError(
                        'the matrix is not reversible')
                edge = frozenset((i, j))
                E.add(edge)
    nd = graph.g_to_nd(V, E)
    # construct an arbitrary rooted spanning tree of the states
    V_component, D_component = graph.nd_to_dag_component(nd, 0)
    if V_component != V:
        raise MatrixUtil.MatrixError('the matrix is not irreducible')
    # compute the stationary probabilities relative to the first state
    weights = [None] * nstates
    v_to_children = graph.dag_to_cd(V_component, D_component)
    preorder_states = graph.topo_sort(V_component, D_component)
    weights[preorder_states[0]] = 1.0
    for parent in preorder_states:
        for child in v_to_children[parent]:
            ratio = R[parent, child] / R[child, parent]
            weights[child] = weights[parent] * ratio
    total = sum(weights)
    return np.array(weights) / total
예제 #4
0
파일: mrate.py 프로젝트: argriffing/xgcode
def R_to_distn_nonspectral(R):
    """
    The rate matrix must be irreducible and reversible.
    It is not necessarily symmetric.
    If the rate matrix is symmetric then this function is overkill
    because the stationary distribution would be uniform.
    """
    nstates = len(R)
    V = set(range(nstates))
    E = set()
    for i in range(nstates):
        for j in range(i):
            if R[i, j]:
                if not R[j, i]:
                    raise MatrixUtil.MatrixError('the matrix is not reversible')
                edge = frozenset((i,j))
                E.add(edge)
    nd = graph.g_to_nd(V, E)
    # construct an arbitrary rooted spanning tree of the states
    V_component, D_component = graph.nd_to_dag_component(nd, 0)
    if V_component != V:
        raise MatrixUtil.MatrixError('the matrix is not irreducible')
    # compute the stationary probabilities relative to the first state
    weights = [None] * nstates
    v_to_children = graph.dag_to_cd(V_component, D_component)
    preorder_states = graph.topo_sort(V_component, D_component)
    weights[preorder_states[0]] = 1.0
    for parent in preorder_states:
        for child in v_to_children[parent]:
            ratio = R[parent, child] / R[child, parent]
            weights[child] = weights[parent] * ratio
    total = sum(weights)
    return np.array(weights) / total
예제 #5
0
def assert_symmetric_irreducible(M):
    assert_symmetric(M)
    V = set(range(len(M)))
    E = set()
    for i in range(len(M)):
        for j in range(i):
            if M[i, j]:
                edge = frozenset((i, j))
                E.add(edge)
    nd = graph.g_to_nd(V, E)
    V_component, D_component = graph.nd_to_dag_component(nd, 0)
    if V_component != V:
        raise MatrixError('the matrix is not irreducible')
예제 #6
0
def assert_symmetric_irreducible(M):
    assert_symmetric(M)
    V = set(range(len(M)))
    E = set()
    for i in range(len(M)):
        for j in range(i):
            if M[i, j]:
                edge = frozenset((i,j))
                E.add(edge)
    nd = graph.g_to_nd(V, E)
    V_component, D_component = graph.nd_to_dag_component(nd, 0)
    if V_component != V:
        raise MatrixError('the matrix is not irreducible')
예제 #7
0
파일: eppstein.py 프로젝트: BIGtigr/xgcode
def get_triple_rake_short_path_count(V, U):
    """
    @return: the number of short paths either 0, 1, 2, or 3
    """
    nd = graph.g_to_nd(V, U)
    edge_to_max_degree = get_subtree_max_degree_map(V, U)
    # Look for the vertex that sees a degree three vertex in three directions.
    vertex_to_nvisible = dict((v, 0) for v in V)
    for v, neighbors in nd.items():
        for w in neighbors:
            if edge_to_max_degree[(v, w)] == 3:
                vertex_to_nvisible[v] += 1
        if vertex_to_nvisible[v] == 3:
            center = v
예제 #8
0
def get_triple_rake_short_path_count(V, U):
    """
    @return: the number of short paths either 0, 1, 2, or 3
    """
    nd = graph.g_to_nd(V, U)
    edge_to_max_degree = get_subtree_max_degree_map(V, U)
    # Look for the vertex that sees a degree three vertex in three directions.
    vertex_to_nvisible = dict((v, 0) for v in V)
    for v, neighbors in nd.items():
        for w in neighbors:
            if edge_to_max_degree[(v, w)] == 3:
                vertex_to_nvisible[v] += 1
        if vertex_to_nvisible[v] == 3:
            center = v
예제 #9
0
파일: eppstein.py 프로젝트: BIGtigr/xgcode
def get_subtree_max_degree_map(V, U):
    """
    @param V: vertices
    @param U: undirected edges
    @return: a map from a directed edge to a max vertex degree
    """
    nd = graph.g_to_nd(V, U)
    dp_edges = get_dp_edges(V, U)
    edge_to_max_degree = dict()
    for a, b in reversed(dp_edges):
        neighbors = nd[b]
        degrees = set([len(neighbors)])
        for c in neighbors:
            if c != a:
                degrees.add(edge_to_max_degree[(b, c)])
        edge_to_max_degree[(a, b)] = max(degrees)
    return edge_to_max_degree
예제 #10
0
def get_subtree_max_degree_map(V, U):
    """
    @param V: vertices
    @param U: undirected edges
    @return: a map from a directed edge to a max vertex degree
    """
    nd = graph.g_to_nd(V, U)
    dp_edges = get_dp_edges(V, U)
    edge_to_max_degree = dict()
    for a, b in reversed(dp_edges):
        neighbors = nd[b]
        degrees = set([len(neighbors)])
        for c in neighbors:
            if c != a:
                degrees.add(edge_to_max_degree[(b, c)])
        edge_to_max_degree[(a, b)] = max(degrees)
    return edge_to_max_degree
예제 #11
0
파일: eppstein.py 프로젝트: BIGtigr/xgcode
def get_subtree_type_map(V, U):
    """
    @param V: vertices
    @param U: undirected edges
    @return: a map from a directed edge to a subtree type
    """
    nd = graph.g_to_nd(V, U)
    dp_edges = get_dp_edges(V, U)
    edge_to_type = dict()
    for a, b in reversed(dp_edges):
        neighbors = nd[b]
        if len(neighbors) == 1:
            # an edge leading to a leaf is a path
            edge_to_type[(a, b)] = SUBTREE_PATH
        elif len(neighbors) == 2:
            # an extra edge at the root of a subtree does not change the type
            for c in neighbors:
                if c != a:
                    edge_to_type[(a, b)] = edge_to_type[(b, c)]
        elif len(neighbors) == 3:
            # trifurcations are the interesting case
            typecount = defaultdict(int)
            for c in neighbors:
                if c != a:
                    typecount[edge_to_type[(b, c)]] += 1
            if SUBTREE_OTHER in typecount:
                t = SUBTREE_OTHER
            elif SUBTREE_RAKE in typecount:
                if typecount[SUBTREE_RAKE] > 1:
                    t = SUBTREE_OTHER
                else:
                    t = SUBTREE_RAKE
            elif typecount[SUBTREE_PATH] > 1:
                t = SUBTREE_RAKE
            else:
                t = SUBTREE_PATH
            edge_to_type[(a, b)] = t
        else:
            # multifurcations of high degree imply neither path nor rake
            edge_to_type[(a, b)] = SUBTREE_OTHER
    return edge_to_type
예제 #12
0
def get_subtree_type_map(V, U):
    """
    @param V: vertices
    @param U: undirected edges
    @return: a map from a directed edge to a subtree type
    """
    nd = graph.g_to_nd(V, U)
    dp_edges = get_dp_edges(V, U)
    edge_to_type = dict()
    for a, b in reversed(dp_edges):
        neighbors = nd[b]
        if len(neighbors) == 1:
            # an edge leading to a leaf is a path
            edge_to_type[(a, b)] = SUBTREE_PATH
        elif len(neighbors) == 2:
            # an extra edge at the root of a subtree does not change the type
            for c in neighbors:
                if c != a:
                    edge_to_type[(a, b)] = edge_to_type[(b, c)]
        elif len(neighbors) == 3:
            # trifurcations are the interesting case
            typecount = defaultdict(int)
            for c in neighbors:
                if c != a:
                    typecount[edge_to_type[(b, c)]] += 1
            if SUBTREE_OTHER in typecount:
                t = SUBTREE_OTHER
            elif SUBTREE_RAKE in typecount:
                if typecount[SUBTREE_RAKE] > 1:
                    t = SUBTREE_OTHER
                else:
                    t = SUBTREE_RAKE
            elif typecount[SUBTREE_PATH] > 1:
                t = SUBTREE_RAKE
            else:
                t = SUBTREE_PATH
            edge_to_type[(a, b)] = t
        else:
            # multifurcations of high degree imply neither path nor rake
            edge_to_type[(a, b)] = SUBTREE_OTHER
    return edge_to_type
예제 #13
0
파일: eppstein.py 프로젝트: BIGtigr/xgcode
def get_dp_edges(V, U):
    """
    Return a sequence of directed edges of an unrooted tree.
    The returned sequence of directed edges is sorted for dynamic programming.
    When a directed edge appears in the list,
    all of the directed edges it points towards will have preceded it.
    @param V: vertices
    @param U: undirected edges
    @return: a sequence of directed edges
    """
    V_meta = set()
    D_meta = set()
    nd = graph.g_to_nd(V, U)
    for v, neighbors in nd.items():
        for a in neighbors:
            V_meta.add((a, v))
            V_meta.add((v, a))
            for b in neighbors:
                if a != b:
                    D_meta.add(((a, v), (v, b)))
    return graph.topo_sort(V_meta, D_meta)
예제 #14
0
def get_dp_edges(V, U):
    """
    Return a sequence of directed edges of an unrooted tree.
    The returned sequence of directed edges is sorted for dynamic programming.
    When a directed edge appears in the list,
    all of the directed edges it points towards will have preceded it.
    @param V: vertices
    @param U: undirected edges
    @return: a sequence of directed edges
    """
    V_meta = set()
    D_meta = set()
    nd = graph.g_to_nd(V, U)
    for v, neighbors in nd.items():
        for a in neighbors:
            V_meta.add((a, v))
            V_meta.add((v, a))
            for b in neighbors:
                if a != b:
                    D_meta.add(((a, v), (v, b)))
    return graph.topo_sort(V_meta, D_meta)
예제 #15
0
파일: eppstein.py 프로젝트: BIGtigr/xgcode
def get_high_degree_mst(V, U):
    """
    Get the high degree vertices and the paths connecting them.
    In this context high degree means at least three.
    Every high degree vertex is in this minimum spanning tree.
    Every vertex that sees at least two high degree vertices
    is in this minimum spanning tree.
    @return: V_mst, U_mst
    """
    V_mst = set()
    U_mst = set()
    nd = graph.g_to_nd(V, U)
    edge_to_max_degree = get_subtree_max_degree_map(V, U)
    for v, neighbors in nd.items():
        if len(nd[v]) > 2:
            V_mst.add(v)
        nvisible = 0
        for w in neighbors:
            if edge_to_max_degree[(v, w)] > 2:
                nvisible += 1
        if nvisible > 1:
            V_mst.add(v)
    U_mst = set(u for u in U if u <= V_mst)
    return V_mst, U_mst
예제 #16
0
def get_high_degree_mst(V, U):
    """
    Get the high degree vertices and the paths connecting them.
    In this context high degree means at least three.
    Every high degree vertex is in this minimum spanning tree.
    Every vertex that sees at least two high degree vertices
    is in this minimum spanning tree.
    @return: V_mst, U_mst
    """
    V_mst = set()
    U_mst = set()
    nd = graph.g_to_nd(V, U)
    edge_to_max_degree = get_subtree_max_degree_map(V, U)
    for v, neighbors in nd.items():
        if len(nd[v]) > 2:
            V_mst.add(v)
        nvisible = 0
        for w in neighbors:
            if edge_to_max_degree[(v, w)] > 2:
                nvisible += 1
        if nvisible > 1:
            V_mst.add(v)
    U_mst = set(u for u in U if u <= V_mst)
    return V_mst, U_mst