def test_single_edge():
    # create a graph consisting of a single edge
    graph = Graph([(0, 1)], directed=True)
    graph.es['type'] = ['up']

    node = most_detrimental(graph, 0, 1)
    assert node is None
def test_two_options():
    # create a graph consisting of four nodes connected in sequence
    graph = Graph([(0, 1), (1, 2), (2, 3)], directed=True)
    graph.es['type'] = ['up'] * 3

    node = most_detrimental(graph, 0, 3)
    assert node in (1, 2)
示例#3
0
def test_not_connected():
    # create a graph with two unconnected edges
    graph = Graph([(0, 1), (2, 3)], directed=True)
    graph.es['type'] = ['up', 'up']

    node = most_detrimental(graph, 0, 3)
    assert node is None
def test_example():
    # create a graph consisting of three nodes connected in sequence
    # every edge will be upregulating
    graph = Graph.Formula('A->B->C')
    graph.es['type'] = ['up'] * 2
    # the most detrimental node should be B
    node = most_detrimental(graph, 'A', 'C')
    assert node == 'B'
def test_stray_edge_source():
    # create a graph consisting of three nodes connected in sequence, plus an extra
    # edge pointing out from the source
    graph = Graph([(0, 1), (1, 2), (0, 3)], directed=True)
    graph.es['type'] = ['up'] * 3

    node = most_detrimental(graph, 0, 2)
    assert node == 1
def test_two_paths_by_len_and_color():
    # create a graph with two possible paths to the source
    # where the best path isn't clear and depends on alpha
    graph = Graph([(0, 1), (1, 4), (0, 2), (2, 3), (3, 4)], directed=True)
    graph.es['type'] = ['up', 'down', 'up', 'up', 'up']

    # case 1: alpha == 1 (the default)
    node = most_detrimental(graph, 0, 4)
    # any of the intermediate nodes could be most detrimental
    assert node in (1, 2, 3)

    # also check that it calculated the correct damages
    # they should all be the same (ie 0)
    damages = damage(graph, 0, 4)
    assert damages.get(1, 0) == 0
    assert damages.get(2, 0) == 0
    assert damages.get(3, 0) == 0

    # case 2: alpha == 1/2
    node = most_detrimental(graph, 0, 4, alpha=0.5)
    # the path that passes through node 1 is better
    assert node == 1

    # what are the influences of the two possible paths?
    influences = [
        influence(graph.es['type'][:2], alpha=0.5),
        influence(graph.es['type'][2:], alpha=0.5)
    ]
    # also check that it calculated the correct damages
    damages = damage(graph, 0, 4, alpha=0.5)
    assert damages.get(node, 0) == (influences[1] - influences[0])

    # case 3: alpha == 2
    node = most_detrimental(graph, 0, 4, alpha=2)
    # the path that passes through nodes 2 and 3 is better
    assert node in (2, 3)

    # what are the influences of the two possible paths?
    influences = [
        influence(graph.es['type'][:2], alpha=2),
        influence(graph.es['type'][2:], alpha=2)
    ]
    # also check that it calculated the correct damages
    damages = damage(graph, 0, 4, alpha=2)
    assert damages.get(node, 0) == (influences[0] - influences[1])
示例#7
0
def test_two_paths_no_node():
    # create a graph consisting of three nodes
    # where the other two nodes are pointing towards the middle one:
    # 0->1<-2
    graph = Graph([(0, 1), (2, 1), (0, 2)], directed=True)
    graph.es['type'] = ['up'] * 3

    node = most_detrimental(graph, 0, 1)
    assert node is None
def test_example_other_types():
    for edge_types in (('up', 'down'), (0, 1), ('activates', 'inactivates'),
                       (100, -200)):
        # create a graph consisting of three nodes connected in sequence
        # every edge will be upregulating
        graph = Graph.Formula('A->B->C')
        graph.es['type'] = edge_types
        # the most detrimental node should be B
        node = most_detrimental(graph, 'A', 'C')
        assert node == 'B', 'Failed with edge types {} and {}'.format(
            *edge_types)
def test_all_same_damages():
    graph = Graph([(0,1), (0,2), (2,3), (1,3), (1,4), (3,5), (4,5)], directed=True)
    graph.es['type'] = ['up', 'up', 'down', 'down', 'down', 'down', 'down']

    node = most_detrimental(graph, 0, 5)
    assert node in (1, 2, 3, 4)

    # also check that each node's damage comes out to 0, as desired
    damages = damage(graph, 0, 5)
    for node in (1, 2, 3, 4):
        assert damages.get(node, 0) == 0
def test_two_paths_by_color():
    # create a graph with two possible paths to the source
    # where the best path is solely determined by the color
    graph = Graph([(0, 1), (1, 3), (0, 2), (2, 3)], directed=True)
    graph.es['type'] = ['up'] * 3 + ['down']

    node = most_detrimental(graph, 0, 3)
    assert node == 1

    # what are the influences of the two possible paths?
    influences = [
        influence(graph.es['type'][:2]),
        influence(graph.es['type'][2:])
    ]

    # also check that it calculated the correct damages
    damages = damage(graph, 0, 3)
    assert damages.get(node, 0) == (influences[1] - influences[0])
def test_two_paths_by_len():
    # create a graph with two possible paths to the source
    # where the best path is solely determined by length
    graph = Graph([(0, 1), (1, 4), (0, 2), (2, 3), (3, 4)], directed=True)
    graph.es['type'] = ['up'] * 5

    # check that it chose the correct path by looking at the most damaging node
    node = most_detrimental(graph, 0, 4)
    assert node == 1

    # what are the influences of the two possible paths?
    influences = [
        influence(graph.es['type'][:2]),
        influence(graph.es['type'][2:])
    ]

    # also check that it calculated the correct damages
    damages = damage(graph, 0, 4)
    assert damages.get(node, 0) == (influences[1] - influences[0])
def test_infinity():
    # create a more complicated graph:
    # All 3 paths must pass through node 1, the first internal node (after the source)
    graph = Graph([(0,1), (1,3), (3,2), (1,2), (1,4), (2,5), (4,5)], directed=True)
    graph.es['type'] = ['up', 'up', 'down', 'down', 'down', 'up', 'down']

    node = most_detrimental(graph, 0, 5)
    assert node == 1

    # also check that the damage comes out to infinity, as desired
    damages = damage(graph, 0, 5)
    assert damages.get(node, 0) == float('inf')

    # check that the damage of node 4 is 1, since the path that passes through node 4
    # is the best one and has influence 4 but there's two more that both have an
    # influence of 5:
    # 5-4 = 1
    assert damages.get(4, 0) == 1

    # the damages of nodes 2 and 3 should be 0, since the most influential path doesn't
    # pass through those nodes
    assert damages.get(2, 0) == 0
    assert damages.get(3, 0) == 0
def test_cycle():
    # This graph consists of four consecutive nodes 0, 1, 2, and 3 and one more extra
    # node 4. A cycle begins at node 2, passes through node 4, and then ends at node 1.
    # All edges have the same color.
    graph = Graph([(0, 1), (1, 2), (2, 3), (2, 4), (4, 1)], directed=True)
    graph.es['type'] = ['up']*5

    # for all values of alpha, the results should be the same
    # so let's test a bunch of them
    for alpha in (1, 2, 100, 0.5, 0.1):
        # Nodes 1 and 2 will be the most detrimental because they are the internal nodes
        # within the path that connects source to sink. The presence of the cycle does
        # not change the fact that they are absolutely required.
        node = most_detrimental(graph, 0, 3, alpha)
        assert node in (1, 2)

        # also check that the most damage comes out to infinity, as desired
        damages = damage(graph, 0, 3, alpha)
        assert damages.get(1, 0) == float('inf')
        assert damages.get(2, 0) == float('inf')

        # and check that the damage of node 4 is 0, since the most influential path
        # should not pass through it!
        assert damages.get(4, 0) == 0
def test_bowtie():
    # This graph has two paths that split from the source and then converge on node 3.
    # The first of the two paths consists of three alternating edges and the second
    # path consists of four non-alternating edges.
    # There's a single edge from node 3 to node 7 and then there are two paths (each of
    # length: 2 edges) that split out from node 7 before converging again on node 9.
    # One of the final two paths has alternating edges while the other does not.

    '''
    graph = Graph([
        (0, 1), (1, 2), (2, 3), (0, 4), (4, 5), (5, 6), (6, 11), (11, 3), (3, 7),
        (7, 8), (8, 9), (7, 10), (10, 9)
    ], directed=True)
    graph.es['type'] = [
        'down', 'up', 'down', 'down', 'down', 'down', 'down', 'down', 'down', 'down',
        'down', 'up', 'down'
    ]
    '''
    graph = Graph([
        (0, 1), (1, 2), (2, 3), (0, 4), (4, 5), (5, 6), (6, 3), (3, 7),
        (7, 8), (8, 9), (7, 10), (10, 9)
    ], directed=True)
    graph.es['type'] = [
        'down', 'up', 'down', 'down', 'down', 'down', 'down', 'down', 'down', 'down',
        'up', 'down'
    ]

    # first, try the pincer
    node = most_detrimental(graph, 0, 7)
    assert node == 3

    # also check that the most damage comes out to infinity, as desired
    damages = damage(graph, 0, 7)
    assert damages.get(node, 0) == float('inf')

    # check that the damages of nodes 4, 5, and 6 is 1 since the best path passes
    # through those nodes and it has an influence of 4, whereas the next best path has
    # an influence of 5 (because it alternates colors, even though it is shorter)
    # 5-4 = 1
    assert damages.get(4, 0) == 1
    assert damages.get(5, 0) == 1
    assert damages.get(6, 0) == 1

    # the damage of the other nodes should be 0, since the most influential path
    # doesn't pass through them
    assert damages.get(1, 0) == 0
    assert damages.get(2, 0) == 0

    # now, let's try the bowtie!
    node = most_detrimental(graph, 0, 9)
    assert node in (3, 7)

    # also check that the most damage comes out to infinity, as desired
    damages = damage(graph, 0, 9)
    assert damages.get(7, 0) == float('inf')

    # check that the damages of node 8 is 1 since the best path passes
    # through that node and it has a total influence of 7, whereas the next best path
    # has an influence of 8 (because it has one alternating node)
    # 8-7 = 1
    assert damages.get(8, 0) == 2

    # the damage of the other node should be 0, since the most influential path
    # doesn't pass it
    assert damages.get(10, 0) == 0

    # just in case, assert that the damages of the other nodes haven't changed
    assert damages.get(1, 0) == 0
    assert damages.get(2, 0) == 0
    assert damages.get(3, 0) == float('inf')
    assert damages.get(4, 0) == 1
    assert damages.get(5, 0) == 1
    assert damages.get(6, 0) == 1