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
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)
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
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'])
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)
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():
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})