Example #1
0
def test_permute():
    """
    Test permuting a graph to be equal to another, or permuting back and forth
    to stay equal to itself.
    """
    g1 = tg.TinyGraph(5,
                      np.int32,
                      vp_types={'color': np.int32},
                      ep_types={'color2': np.int32})
    g2 = tg.TinyGraph(5,
                      np.int32,
                      vp_types={'color': np.int32},
                      ep_types={'color2': np.int32})
    g1[0, 1] = 5
    g2[3, 4] = 5
    g1[2, 3] = 1
    g2[1, 2] = 1
    g1.v['color'][0] = 10
    g2.v['color'][4] = 10
    g1.e['color2'][2, 3] = 4
    g2.e['color2'][2, 1] = 4

    pG11 = permute(g1, [3, 4, 1, 2, 0])
    pG12 = permute(g1, [4, 3, 1, 2, 0])
    pG13 = permute(pG11, [4, 2, 3, 0, 1])

    assert not graph_equality(g2, pG11)
    assert graph_equality(g2, pG12)
    assert graph_equality(g1, pG13)
Example #2
0
def test_merge_empty():
    """Merge two empty graphs"""
    g1 = tg.TinyGraph(0, np.bool)
    g2 = tg.TinyGraph(0, np.bool)

    gg = merge(g1, g2)
    gg2 = merge(g2, g1)

    assert 0 == gg.vert_N
    assert 0 == gg2.vert_N
Example #3
0
def test_merge_prop_types():
    """
    Check for desired behavior in case of mismatched property types
    (both for global types and vertex/edge proprty types)
    """
    g1 = tg.TinyGraph(2,
                      np.int32,
                      vp_types={'name': np.dtype('<U10')},
                      ep_types={'length': np.double})
    g1.v['name'][:] = ['aaa', 'baa']
    g1.props['name'] = 'base'
    g1[0, 1] = 1
    g1.e['length'][0, 1] = 2.2

    g2 = tg.TinyGraph(2,
                      np.double,
                      vp_types={},
                      ep_types={'length': np.double})
    with pytest.raises(TypeError):
        merge(g1, g2)

    g3 = tg.TinyGraph(2, np.int32, vp_types={}, ep_types={'length': np.int})
    g3.props['name'] = 'secondary'
    g3[0, 1] = 2
    g3.e['length'][0, 1] = 4
    with pytest.raises(TypeError):
        merge(g1, g3)

    g4 = tg.TinyGraph(2, np.int32, vp_types={}, ep_types={'length': np.double})
    g4.props['name'] = 'secondary'
    g4[0, 1] = 2
    g4.e['length'][0, 1] = 4.0
    with pytest.warns(UserWarning):
        gg = merge(g1, g4)
        assert np.array_equal(gg.v['name'], ['aaa', 'baa', '', ''])

    g5 = tg.TinyGraph(2,
                      np.int32,
                      vp_types={'name': np.dtype('<U10')},
                      ep_types={'length': np.double})
    g5.props['name'] = 'secondary'
    g5.v['name'][:] = ['hello', 'world']
    g5[0, 1] = 2
    g5.e['length'][0, 1] = 4.0

    gh = merge(g1, g5)
    assert gh.props['name'] == 'base'
    assert np.array_equal(gh.v['name'], ['aaa', 'baa', 'hello', 'world'])
    assert gh.e['length'][0, 1] == g1.e['length'][0, 1]
    assert gh.e['length'][2, 3] == g5.e['length'][0, 1]
Example #4
0
def test_misbehavior():
    """
    Tests for illegal behavior handling
    """
    g = tg.TinyGraph(3,vp_types = {"color": np.int32},\
                        ep_types = {"width": np.int32})
    with pytest.raises(KeyError,match='Expecting exactly two endpoints.'):
        g[0] = 3
    with pytest.raises(KeyError, match='Expecting exactly two endpoints.'):
        g[0,1,2] = 3
    with pytest.raises(IndexError, match='Self-loops are not allowed.'):
        g[1,1] = 3
    with pytest.raises(KeyError,match='Expecting exactly two endpoints.'):
        e = g[0]
    with pytest.raises(KeyError, match='Expecting exactly two endpoints.'):
        e = g[0,1,2]
    with pytest.raises(KeyError,match='Expecting exactly two endpoints.'):
        g.e['width'][0] = 3
    with pytest.raises(KeyError, match='Expecting exactly two endpoints.'):
        g.e['width'][0,1,2] = 3
    with pytest.raises(KeyError,match='Expecting exactly two endpoints.'):
        e = g.e["width"][0]
    with pytest.raises(KeyError, match='Expecting exactly two endpoints.'):
        e = g.e['width'][0,1,2]
    with pytest.raises(IndexError):
        g.v['color'][0,2] = 1
    with pytest.raises(IndexError):
        v = g.v['color'][0,2]
def test_edges():
    """
    Simple test of getting edge properties.
    """
    g = tg.TinyGraph(5, np.int32, ep_types = {'color': np.int32,
                                                'elem': np.bool})
    g[0,4] = 10
    g[1,0] = 20
    g[2,1] = 30
    g[3,2] = 40
    g[4,3] = 50
    g.e['color'][0,1] = 3
    g.e['color'][1,2] = 4
    g.e['color'][2,3] = 5
    g.e['color'][3,4] = 6
    g.e['color'][4,0] = 1
    g.e['elem'][4,0] = True
    g.e['elem'][0,1] = False
    g.e['elem'][1,2] = True
    g.e['elem'][2,3] = False
    g.e['elem'][3,4] = True
    weights = {(0,4):10,(0,1):20,(1,2):30,(2,3):40,(3,4):50}
    elem = {(0,4):True,(0,1):False,(1,2):True,(2,3):False,(3,4):True}
    assert len(g.edges(edge_props={})[0]) == 3
    for i, j, w in g.edges(weight = True):
        assert w == weights[(i,j)]
    for i, j, d in g.edges(edge_props = ['elem']):
        assert len(d) == 1
        assert d['elem'] == elem[(i,j)]
def test_cycles_empty():
    """
    An empty graph has no vertices to be in cycles.
    """
    g = tg.TinyGraph(0)

    assert algs.get_min_cycles(g) == []
def test_remove_edge():
    """
    Simple test of removing edges.
    """
    g = tg.TinyGraph(5, np.int32, ep_types = {'color': np.int32,
                                                'elem': np.bool})
    g[0,4] = 10
    g[1,0] = 20
    g[2,1] = 30
    g[3,2] = 40
    g[4,3] = 50
    g.e['color'][0,1] = 3
    g.e['color'][1,2] = 4
    g.e['color'][2,3] = 5
    g.e['color'][3,4] = 6
    g.e['color'][4,0] = 1
    g[0,4] = 0
    g[1,0] = 0
    with pytest.raises(IndexError, match='No such edge'):
        g.e['color'][1,4] = 6
    with pytest.raises(IndexError, match='No such edge.'):
        g.e['color'][0,1]
    assert g.e['color'][1,2] == 4
    assert g.e['color'][2,3] == 5
    assert g.e['color'][3,4] == 6
    with pytest.raises(IndexError, match='No such edge.'):
        g.e['color'][4,0]
Example #8
0
def test_permute_error_handling():
    """Demonstrate behavior in case not handed a proper permutation"""
    g1 = tg.TinyGraph(5,
                      np.int32,
                      vp_types={'color': np.int32},
                      ep_types={'color2': np.int32})
    g1[0, 1] = 5
    g1[1, 3] = 3
    g1[2, 3] = 1
    g1[0, 4] = 2
    g1.v['color'][0] = 10
    g1.e['color2'][2, 3] = 4

    bad_perm_1 = [0]
    bad_perm_2 = [1, 3, 3, 4, 4]
    bad_perm_3 = [1, 3, 3, 4, 4, 2, 2, 1]
    bad_perm_4 = [-5, 0, 3, 3, 4, 6]

    # Is this behavior we want?
    with pytest.raises(IndexError):
        bg1 = permute(g1, bad_perm_1)

    with pytest.raises(IndexError):
        bg2 = permute(g1, bad_perm_2)

    with pytest.raises(IndexError):
        bg3 = permute(g1, bad_perm_3)

    with pytest.raises(IndexError):
        bg4 = permute(g1, bad_perm_4)
Example #9
0
def test_merge_simple():
    """Merge two graphs, each with two vertices and no properties"""
    g1 = tg.TinyGraph(2)
    g1[0, 1] = 2
    g2 = tg.TinyGraph(2)
    g2[0, 1] = 3

    gg = merge(g1, g2)

    result = np.zeros((4, 4), dtype=np.int32)
    result[0, 1] = 2
    result[1, 0] = 2
    result[2, 3] = 3
    result[3, 2] = 3

    assert gg.vert_N == 4
    assert np.array_equal(gg.adjacency, result)
Example #10
0
def test_graph_props():
    """
    Simple tests of per-graph properties

    """
    
    g1 = tg.TinyGraph(10)
    g1.props['foo'] = 'bar'

    g2 = tg.TinyGraph(10)
    g2.props['foo'] = 'bar'

    assert tg.util.graph_equality(g1, g2)

    g2.props['baz'] = 7
    
    assert not tg.util.graph_equality(g1, g2)
Example #11
0
def test_cc_empty():
    """
    Empty graph has no connected components.
    """
    g = tg.TinyGraph(0)

    assert algs.get_connected_components(g) == []
    assert algs.is_connected(g) == False
Example #12
0
def test_bad_edge_subset():
    g = tg.TinyGraph(2, vp_types={'color': np.int})
    with pytest.raises(KeyError):
        ng = tg.io.to_nx(g,
                         weight_prop='weight',
                         name_prop='name',
                         vp_subset=['color'],
                         ep_subset=['friends'])  # no friends :/
Example #13
0
def test_bad_vertex_subset():
    """Ensure a KeyError is raised on an invalid subset request"""
    t = tg.TinyGraph(3, ep_types={'weight': np.int})
    t[0, 1] = 2
    t[1, 2] = 4

    with pytest.raises(KeyError):
        ng = tg.io.to_nx(t, vp_subset=['color'])
Example #14
0
def test_vanishing_edge():
    """Current behavior is for 0-weighted edges to vanish"""
    t = tg.TinyGraph(2)
    t[0, 1] = 0
    ng = tg.io.to_nx(t)
    t2 = tg.io.from_nx(ng)

    assert np.all(t2.adjacency == 0)
Example #15
0
def test_paths_fully_connected_with_path():
    """
    Test shortest paths on a fully connected graph.
    """
    g = tg.TinyGraph(5)
    g[0, 1] = 1
    g[1, 2] = 1
    g[2, 3] = 1
    g[3, 4] = 1
    g[4, 0] = 1

    dists, next = algs.get_shortest_paths(g, True, True)
    paths = algs.construct_all_shortest_paths(next)
    for i in paths:
        for j in i:
            print(list(j))

    np.testing.assert_equal(dists,\
                            np.array([[0,1,2,2,1],\
                                    [1,0,1,2,2],\
                                    [2,1,0,1,2],\
                                    [2,2,1,0,1],\
                                    [1,2,2,1,0]],dtype=np.float64))

    np.testing.assert_equal(next,\
                            np.array([[0,1,1,4,4],\
                                    [0,1,2,2,0],\
                                    [1,1,2,3,3],\
                                    [4,2,2,3,4],\
                                    [0,0,3,3,4]],dtype=np.float64))

    np.testing.assert_equal(paths,\
                            np.array([[[0,np.inf,np.inf,np.inf,np.inf],\
                                    [0,1,np.inf,np.inf,np.inf],\
                                    [0,1,2,np.inf,np.inf],\
                                    [0,4,3,np.inf,np.inf],\
                                    [0,4,np.inf,np.inf,np.inf]],\
                                    [[1,0,np.inf,np.inf,np.inf],\
                                    [1,np.inf,np.inf,np.inf,np.inf],\
                                    [1,2,np.inf,np.inf,np.inf],\
                                    [1,2,3,np.inf,np.inf],\
                                    [1,0,4,np.inf,np.inf]],\
                                    [[2,1,0,np.inf,np.inf],\
                                    [2,1,np.inf,np.inf,np.inf],\
                                    [2,np.inf,np.inf,np.inf,np.inf],\
                                    [2,3,np.inf,np.inf,np.inf],\
                                    [2,3,4,np.inf,np.inf]],\
                                    [[3,4,0,np.inf,np.inf],\
                                    [3,2,1,np.inf,np.inf],\
                                    [3,2,np.inf,np.inf,np.inf],\
                                    [3,np.inf,np.inf,np.inf,np.inf],\
                                    [3,4,np.inf,np.inf,np.inf]],\
                                    [[4,0,np.inf,np.inf,np.inf],\
                                    [4,0,1,np.inf,np.inf],\
                                    [4,3,2,np.inf,np.inf],\
                                    [4,3,np.inf,np.inf,np.inf],\
                                    [4,np.inf,np.inf,np.inf,np.inf]]],dtype=np.float64))
Example #16
0
def test_merge_identity():
    """Merge with an empty graph"""
    g1 = graph_test_suite.gen_random(5, np.bool, [True], 0.5)
    g2 = tg.TinyGraph(0, np.bool)

    gg = merge(g1, g2)
    gh = merge(g2, g1)

    assert graph_equality(g1, gg)
    assert graph_equality(g1, gh)
Example #17
0
def test_items():
    t = tg.TinyGraph(3, vp_types={'name': np.str})

    t.v['name'][0] = 'a'
    t.v['name'][1] = 'b'
    t.v['name'][2] = 'c'

    assert(t.v['name'][0] == 'a')
    assert(t.v['name'][1] == 'b')
    assert(t.v['name'][2] == 'c')
Example #18
0
def test_subgraph_error():
    """Check error-handling for out-of-bounds stuff"""
    vertices = set([0, 1, 12])
    g = tg.TinyGraph(5)
    with pytest.raises(IndexError):
        sg = subgraph(g, vertices)

    vertices2 = set([-1, 0, 3, 4])
    with pytest.raises(IndexError):
        sg2 = subgraph(g, vertices2)
Example #19
0
def test_create_graphs_types():
    """
    Simple tests to try creating graphs of various dtypes
    """

    g1_bool = tg.TinyGraph(5, np.bool)
    g1_bool[3, 2] = True
    assert g1_bool[2, 3] == True
    assert g1_bool[3, 2] == True

    g1_int32 = tg.TinyGraph(5, np.int32)
    g1_int32[3, 2] = 7
    assert g1_int32[3, 2] == 7
    assert g1_int32[2, 3] == 7


    g1_float64 = tg.TinyGraph(5, np.float64)
    g1_float64[3, 2] = 3.14
    assert g1_float64[3, 2] == 3.14
    assert g1_float64[2, 3] == 3.14
Example #20
0
def test_paths_empty():
    """
    Test shortest paths on an empty graph.
    """
    g = tg.TinyGraph(0, adj_type=np.bool)

    with pytest.raises(TypeError, match='Graph weights are not numbers.'):
        algs.get_shortest_paths(g, True)

    np.testing.assert_equal(algs.get_shortest_paths(g, False),
                            np.zeros((0, 0), dtype=np.float64))
Example #21
0
def _subgraph_relabel(g, vert_iter):
    """
    Helper function to perform the work of permute and subgraph. Not intended 
    for use by end-users. See instead functions permute and subgraph below.

    Returns the subgraph of g induced by vert_iter (as the set of vertices), 
    maintaining the ordering of vert_iter in constructing the new subgraph.

    Inputs:
        g (TinyGraph): Original Tinygraph

        vert_iter (iterable): iterable containing indices of vertices to take as
            the vertices of the subgraph. Contrary to permute(), here we expect
                vert_iter[new_vertex] = old_vertex
            to support dropping (and possibly duplicating) old vertices.

    Outputs:
        sg (TinyGraph): subgraph with vertices in the same order as vert_iter.
    """
    N = len(vert_iter)
    new_g = tg.TinyGraph(N, g.adjacency.dtype,
                         {p: val.dtype
                          for p, val in g.v.items()},
                         {p: val.dtype
                          for p, val in g.e.items()})
    # Copy graph props
    # new_g.props = {k:v for k, v in g.props.items()}
    new_g.props = deepcopy(g.props)

    if N == 0:
        # Weird things happen if we keep going ;_;
        return new_g

    # Magic index converter eliminates python-for-loops
    # at the expense of ignoring sparsity (moves everything)
    new_list = np.arange(N)  # list of the new vertices
    #vert_iter is a list of old vertices ordered by destination indices
    old_indices = (np.repeat(new_list, N), np.tile(new_list, N))
    new_indices = (np.repeat(vert_iter, N), np.tile(vert_iter, N))

    # Copy edge values
    new_g.adjacency[old_indices] = g.adjacency[new_indices]

    # Copy vertex properties
    for prop in g.v.keys():
        new_g.v[prop][:] = g.v[prop][vert_iter]

    # Copy edge properties
    for prop in g.e.keys():
        new_g.e_p[prop][old_indices] = g.e_p[prop][new_indices]

    return new_g
Example #22
0
def test_permute_dict():
    """Pass the permutation as a dictionary and ensure the permutation
    operates in the desired direction"""
    perm = [2, 3, 1, 0]
    # perm_dict = dict(zip(range(4), perm))
    # purposely written out of order
    perm_dict = {3: 0, 0: 2, 2: 1, 1: 3}
    g = tg.TinyGraph(4, np.bool, vp_types={'name': np.dtype('<U20')})
    g.v['name'][:] = ['a', 'b', 'c', 'd']

    h = permute(g, perm_dict)

    assert list(h.v['name']) == ['d', 'c', 'a', 'b']
Example #23
0
def test_negative_cycles():
    """
    Test shortest path on a graph with a negative cycle (expect raise error).
    """
    g = tg.TinyGraph(3)
    g[0, 1] = 1
    g[1, 2] = -5
    g[2, 0] = 1

    with pytest.raises(Exception, match='Graph has a negative cycle.'):
        algs.get_shortest_paths(g, True)
    assert np.array_equal(
        algs.get_shortest_paths(g, False),
        np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]], dtype=np.float64))
Example #24
0
def test_cc_one_comp():
    """
    Test graph with one connected component.
    """
    g = tg.TinyGraph(5)
    g[0, 1] = 1
    g[0, 2] = 1
    g[2, 3] = 1
    g[3, 4] = 1

    assert algs.get_connected_components(g) == [
        set(range(5)),
    ]
    assert algs.is_connected(g) == True
Example #25
0
def test_cycles_medium():
    """
    Test some medium sized graphs with various sized cycles.
    """
    g1 = tg.TinyGraph(6)
    g1[0, 1] = 1
    g1[0, 2] = 1
    g1[1, 2] = 1
    g1[0, 3] = 1
    g1[0, 5] = 1
    g1[3, 4] = 1
    g1[4, 5] = 1

    assert algs.get_min_cycles(g1) == [{0, 1, 2}, {0, 1, 2}, {0, 1, 2},\
                                        {0, 3, 4, 5},{0, 3, 4, 5},{0, 3, 4, 5}]

    g2 = tg.TinyGraph(9)
    g2[0, 8] = 1
    g2[7, 8] = 1
    g2[6, 8] = 1
    g2[3, 7] = 1
    g2[3, 6] = 1
    g2[2, 3] = 1
    g2[5, 6] = 1
    g2[1, 2] = 1
    g2[1, 4] = 1
    g2[4, 5] = 1

    assert algs.get_min_cycles(g2) == [set(), \
                                        {1, 2, 3, 4, 5, 6}, \
                                        {1, 2, 3, 4, 5, 6}, \
                                        {3, 7, 8, 6}, \
                                        {1, 2, 3, 4, 5, 6}, \
                                        {1, 2, 3, 4, 5, 6}, \
                                        {3, 7, 8, 6}, \
                                        {3, 7, 8, 6}, \
                                        {3, 7, 8, 6} ]
Example #26
0
def test_cc_multi_comp():
    """
    Test graph with mulitple connected components.
    """
    g = tg.TinyGraph(6)
    g[0, 1] = 1
    g[0, 2] = 1
    g[1, 2] = 1
    g[3, 4] = 1
    g[4, 5] = 1

    assert algs.get_connected_components(g) == [
        set(range(3)), set(range(3, 6))
    ]
    assert algs.is_connected(g) == False
Example #27
0
def test_triangle():
    """Makes a cycle graph and checks for perservation of the adjacency matrix"""
    t = tg.TinyGraph(3, vp_types={'name': np.str})
    t[0, 1] = 1
    t[1, 2] = 1.1
    t[2, 0] = 3

    t.v['name'][0] = 'a'
    t.v['name'][1] = 'b'
    t.v['name'][2] = 'c'

    ng = tg.io.to_nx(t, weight_prop='weight')
    t2 = tg.io.from_nx(ng, weight_prop='weight', vp_types={'name': np.str})

    assert tg.util.graph_equality(t, t2)
Example #28
0
def test_permute_path():
    """Another case to ensure permutations work in the expected direction"""
    g = tg.TinyGraph(4, np.bool, vp_types={'name': np.dtype('<U20')})
    perm = [2, 3, 1, 0]
    inv_perm = np.argsort(perm)  # [3, 2, 0, 1]
    assert np.array_equal(inv_perm, [3, 2, 0, 1])
    g.v['name'][:] = ['a', 'b', 'c', 'd']
    g[0, 1] = 1
    g[1, 2] = 1
    g[2, 3] = 1

    h = permute(g, perm)
    assert list(h.v['name']) == ['d', 'c', 'a', 'b']
    gp = permute(h, inv_perm)
    assert graph_equality(g, gp)
Example #29
0
def gen_random(N, dtype, edge_weights, prob_edge, rng=None):
    """
    Generate a random graph of the given dtype with 
    a fixed edge probability. 0 = empty graph, 1.0 = full graph, 
    possible edge weight values from edge_weights

    """
    if rng is None:
        rng = np.random.RandomState()

    g = tg.TinyGraph(N, dtype)
    for i in range(N):
        for j in range(i + 1, N):
            if rng.rand() < prob_edge:
                g[i, j] = rng.choice(edge_weights)
    return g
Example #30
0
def test_permute_identity():
    """Ensure that the identity permutation preserves graph equality"""
    g1 = tg.TinyGraph(5,
                      np.int32,
                      vp_types={'color': np.int32},
                      ep_types={'color2': np.int32})
    g1[0, 1] = 5
    g1[1, 3] = 3
    g1[2, 3] = 1
    g1[0, 4] = 2
    g1.v['color'][0] = 10
    g1.e['color2'][2, 3] = 4

    g2 = permute(g1, [0, 1, 2, 3, 4])

    assert graph_equality(g1, g2)