Esempio n. 1
0
def enum_Steiner_only(n, steiner_ids=None):
    '''Enumerate all representative trees.

    This considers only the trees interconnecting the Steiner nodes
    for full Steiner trees of n terminals.

    Following "Fampa et al.: A specialized branch-and-bound algorithm
    for the Euclidean Steiner tree problem in n-space", algorithm 1.
    '''
    # optional node IDs for Steiner nodes
    if steiner_ids is None:
        steiner_ids = default_steiner_ids(n)
    assert len(steiner_ids) == n - 2

    # resulting data structures
    nclasses = {}  # key: number of Steiner nodes
    reprtree = {}  # key: (number of Steiner nodes, class id)

    # initialize with single representative for 1 Steiner node
    cur_nodes = steiner_ids[:1]
    cur_edges = []
    nclasses[1] = 1
    reprtree[1, 0] = Net(cur_nodes, cur_edges)

    # incrementally add another Steiner node
    for j in range(2, n - 2 + 1):
        nclasses[j] = 0
        cur_nodes.append(steiner_ids[j - 1])

        # for each (smaller) representative tree
        for k in range(nclasses[j - 1]):
            # for each possible connection point
            for i in range(1, j):
                # enforce maximum degree of 3
                if reprtree[j - 1, k].get_degree(steiner_ids[i - 1]) == 3:
                    continue

                # tentatively build new representative
                new_edge = (steiner_ids[i - 1], steiner_ids[j - 1])
                cur_edges = reprtree[j - 1, k].get_arcs() + [new_edge]
                cur_tree = Net(cur_nodes, cur_edges)

                # skip tree if isomorphic to other representative
                if any(
                        are_isomorphic(cur_tree, reprtree[j, l])
                        for l in range(nclasses[j])):
                    continue

                # add representative for new class
                reprtree[j, nclasses[j]] = cur_tree
                nclasses[j] += 1

    return nclasses, reprtree
Esempio n. 2
0
def test_imbalance():
    '''Check exception for unbalanced data'''
    net = Net('ab', ['ab'])
    demand = {'a':4}
    with pytest.raises(AssertionError) as e:
        flows = find_arc_flow(net, demand)
    assert 'flow not balanced' in str(e.value)
Esempio n. 3
0
def test_treeflow():
    '''Check that (unique) flow values are computed correctly.'''
    nodes = 'abcdef'
    arcs = ['ac', 'bc', 'cd', 'de', 'df']
    net = Net(nodes, arcs)

    demand = {'a': -7, 'b': -5, 'e':12}

    flows = find_arc_flow(net, demand)

    assert flows['a', 'c'] == 7
    assert flows['b', 'c'] == 5
    assert flows['c', 'd'] == 12
    assert flows['d', 'e'] == 12
    assert flows['d', 'f'] == 0
Esempio n. 4
0
def test_Net():
    nodes = ['a', 'b', 'c', 'd']
    arcs = [('a', 'b'), ('b', 'c'), ('c', 'd'), ('a', 'c')]

    net = Net(nodes, arcs)
    assert set(net.get_nodes()) == set(nodes)
    assert set(net.get_arcs()) == set(arcs)

    assert net.get_degree('a') == 2
    assert net.get_degree('b') == 2
    assert net.get_degree('c') == 3
    assert net.get_degree('d') == 1

    assert set(net.get_neighbors('a')) == set('bc')
    assert set(net.get_neighbors('b')) == set('ac')
    assert set(net.get_neighbors('c')) == set('abd')
    assert set(net.get_neighbors('d')) == set(['c'])
Esempio n. 5
0
 def uppercase(net):
     ucnodes = [n.upper() for n in net.get_nodes()]
     ucarcs = [(t.upper(), h.upper()) for (t, h) in net.get_arcs()]
     return Net(ucnodes, ucarcs)
Esempio n. 6
0
    id4 = default_steiner_ids(4)
    assert len(id4) == 2
    assert sorted(id4) == id4
    assert len(set(id4)) == len(id4)

    id5 = default_steiner_ids(5)
    assert len(id5) == 3
    assert sorted(id5) == id5
    assert len(set(id5)) == len(id5)


# tests for are_isomorphic

graphs = [
    Net([], []),
    Net('a', []),
    Net('ab', []),
    Net('ab', [('a', 'b')]),
    Net('abc', [('a', 'b')]),
    Net('abc', [('a', 'b'), ('a', 'c')]),
    Net('abcd', [('a', 'b'), ('c', 'd')]),
    Net('abcd', [('a', 'b'), ('b', 'c'), ('c', 'd')]),
    Net('abcd', [('a', 'b'), ('a', 'c'), ('a', 'd')]),
    Net('abcde', [('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')]),
    Net('abcde', [('a', 'b'), ('a', 'c'), ('a', 'd'), ('a', 'e')]),
    Net('abcde', [('a', 'b'), ('a', 'c'), ('a', 'e'), ('d', 'e')]),
]


def test_non_isomorphic_cases():
Esempio n. 7
0
def test_equality():
    # testing just Net
    assert Net('', []) == Net('', [])
    assert not Net('', []) != Net('', [])

    assert Net('a', []) == Net('a', [])
    assert Net('a', []) != Net('', [])
    assert Net('a', []) != Net('A', [])

    assert Net('abc', ['ab']) == Net('abc', ['ab'])
    assert Net('abc', ['ab']) == Net('cba', ['ab'])
    assert Net('abc', ['ab']) != Net('abc', ['ba'])
    assert Net('abc', ['ab']) != Net('abc', ['bc'])
    assert Net('abc', ['ab', 'bc']) == Net('abc', ['bc', 'ab'])

    # testing SteinerTree with no terminals
    assert SteinerTree('', [], {}) == SteinerTree('', [], {})
    assert not SteinerTree('', [], {}) != SteinerTree('', [], {})

    assert SteinerTree('a', [], {}) == SteinerTree('a', [], {})
    assert SteinerTree('a', [], {}) != SteinerTree('', [], {})
    assert SteinerTree('a', [], {}) != SteinerTree('A', [], {})

    assert SteinerTree('abc', ['ab'], {}) == SteinerTree('abc', ['ab'], {})
    assert SteinerTree('abc', ['ab'], {}) == SteinerTree('cba', ['ab'], {})
    assert SteinerTree('abc', ['ab'], {}) != SteinerTree('abc', ['ba'], {})
    assert SteinerTree('abc', ['ab'], {}) != SteinerTree('abc', ['bc'], {})
    assert SteinerTree('abc', ['ab', 'bc'],
                       {}) == SteinerTree('abc', ['bc', 'ab'], {})

    # testing SteinerTree with terminals
    assert SteinerTree('abc', ['ab'],
                       {'a': 0}) == SteinerTree('abc', ['ab'], {'a': 0})
    assert not SteinerTree('abc', ['ab'], {'a': 0}) != SteinerTree(
        'abc', ['ab'], {'a': 0})
    assert SteinerTree('abc', ['ab'], {'a': 0}) != SteinerTree(
        'abc', ['ab'], {})
    assert SteinerTree('abc', ['ab'], {'a': 0}) != SteinerTree(
        'abc', ['ab'], {'a': 1})