def to_graph_decomposition(H): """Returns a DirectedHypergraph object that has the same nodes (and corresponding attributes) as the given hypergraph, except that for all hyperedges in the given hypergraph, each node in the tail of the hyperedge is pairwise connected to each node in the head of the hyperedge in the new hypergraph. Said another way, each of the original hyperedges are decomposed in the new hypergraph into fully-connected bipartite components. :param H: the hypergraph to decompose into a graph. :returns: DirectedHypergraph -- the decomposed hypergraph. :raises: TypeError -- Transformation only applicable to directed hypergraphs """ if not isinstance(H, DirectedHypergraph): raise TypeError("Transformation only applicable to \ directed hypergraphs") G = DirectedHypergraph() nodes = [(node, H.get_node_attributes(node_attributes)) for node in G.node_iterator()] G.add_nodes(nodes) edges = [([tail_node], [head_node]) for hyperedge_id in H.hyperedge_id_iterator() for tail_node in H.get_hyperedge_tail(hyperedge_id) for head_node in H.get_hyperedge_head(hyperedge_id)] G.add_hyperedges(edges) return G
def test_raises_exception_if_k_not_integer(self): H = DirectedHypergraph() source, destination = 1, 2 H.add_nodes([source, destination]) self.assertRaises(TypeError, ksh.k_shortest_hyperpaths, H, source, destination, 0.1)
def test_add_nodes(): node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} node_d = 'D' attrib_d = {'label': 'black', 'sink': True} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': False}), (node_c, attrib_c), (node_d, attrib_d)] # Test adding unadded nodes with various attribute settings H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) assert node_a in H._node_attributes assert H._node_attributes[node_a] == common_attrib assert node_b in H._node_attributes assert H._node_attributes[node_b]['source'] is False assert node_c in H._node_attributes assert H._node_attributes[node_c]['alt_name'] == 1337 assert node_d in H._node_attributes assert H._node_attributes[node_d]['label'] == 'black' assert H._node_attributes[node_d]['sink'] is True node_set = H.get_node_set() assert node_set == set(['A', 'B', 'C', 'D']) assert len(node_set) == len(node_list) for node in H.node_iterator(): assert node in node_set
def to_graph_decomposition(H): """Returns a DirectedHypergraph object that has the same nodes (and corresponding attributes) as the given hypergraph, except that for all hyperedges in the given hypergraph, each node in the tail of the hyperedge is pairwise connected to each node in the head of the hyperedge in the new hypergraph. Said another way, each of the original hyperedges are decomposed in the new hypergraph into fully-connected bipartite components. :param H: the hypergraph to decompose into a graph. :returns: DirectedHypergraph -- the decomposed hypergraph. :raises: TypeError -- Transformation only applicable to directed hypergraphs """ if not isinstance(H, DirectedHypergraph): raise TypeError("Transformation only applicable to \ directed hypergraphs") G = DirectedHypergraph() nodes = [(node, H.get_node_attributes(node_attributes)) for node in G.node_iterator()] G.add_nodes(nodes) edges = [([tail_node], [head_node]) for hyperedge_id in H.hyperedge_id_iterator() for tail_node in H.get_hyperedge_tail(hyperedge_id) for head_node in H.get_hyperedge_head(hyperedge_id)] G.add_hyperedges(edges) return G
def test_raises_exception_if_H_not_B_hypegraph(self): H = DirectedHypergraph() H.add_nodes([1, 2, 3]) H.add_hyperedge([1], [2, 3]) source, destination = 1, 2 self.assertRaises(TypeError, ksh.k_shortest_hyperpaths, H, source, destination, 1)
def test_raises_exception_if_H_not_B_hypegraph(self): H = DirectedHypergraph() H.add_nodes([1, 2, 3]) H.add_hyperedge([1], [2, 3]) source, destination = 1, 2 self.assertRaises(TypeError, ksh.k_shortest_hyperpaths, H, source, destination, 1)
def get_hypertree_from_predecessors(H, Pv, source_node, node_weights=None, attr_name="weight"): """Gives the hypertree (i.e., the subhypergraph formed from the union of the set of paths from an execution of, e.g., the SBT algorithm) defined by Pv beginning at a source node. Returns a dictionary mapping each node to the ID of the hyperedge that preceeded it in the path (i.e., a Pv vector). Assigns the node weights (if provided) as attributes of the nodes (e.g., the rank of that node in a specific instance of the SBT algorithm, or the cardinality of that node in a B-Visit traversal, etc.). :note: The IDs of the hyperedges in the subhypergraph returned may be different than those in the original hypergraph (even though the tail and head sets are identical). :param H: the hypergraph which the path algorithm was executed on. :param Pv: dictionary mapping each node to the ID of the hyperedge that preceeded it in the path. :param source_node: the root of the executed path algorithm. :param node_weights: [optional] dictionary mapping each node to some weight measure. :param attr_name: key into the nodes' attribute dictionaries for their weight values (if node_weights is provided). :returns: DirectedHypergraph -- subhypergraph induced by the path algorithm specified by the predecessor vector (Pv) from a source node. :raises: TypeError -- Algorithm only applicable to directed hypergraphs """ if not isinstance(H, DirectedHypergraph): raise TypeError("Algorithm only applicable to directed hypergraphs") sub_H = DirectedHypergraph() # If node weights are not provided, simply collect all the nodes that are # will be in the hypertree if node_weights is None: nodes = [node for node in Pv.keys() if Pv[node] is not None] nodes.append(source_node) # If node weights are provided, collect all the nodes that will be in the # tree and pair them with their corresponding weights else: nodes = [(node, { attr_name: node_weights[node] }) for node in Pv.keys() if Pv[node] is not None] nodes.append((source_node, {attr_name: node_weights[source_node]})) # Add the collected elements to the hypergraph sub_H.add_nodes(nodes) # Add all hyperedges, specified by Pv, to the hypergraph hyperedges = [(H.get_hyperedge_tail(hyperedge_id), H.get_hyperedge_head(hyperedge_id), H.get_hyperedge_attributes(hyperedge_id)) for hyperedge_id in Pv.values() if hyperedge_id is not None] sub_H.add_hyperedges(hyperedges) return sub_H
def test_raises_exception_if_k_not_positive(self): H = DirectedHypergraph() source, destination = 1, 2 H.add_nodes([source, destination]) self.assertRaises(ValueError, ksh.k_shortest_hyperpaths, H, source, destination, -4) self.assertRaises(ValueError, ksh.k_shortest_hyperpaths, H, source, destination, 0)
def test_raises_exception_if_all_nodes_have_predecessors(self): s1, s2, s3 = 1, 2, 3 H = DirectedHypergraph() H.add_nodes([s1, s2, s3]) e1 = H.add_hyperedge([s1], [s2]) T = {s1: e1, s2: e1, s3: e1} self.assertRaises(ValueError, directed_paths.get_hyperpath_from_predecessors, H, T, s1, s2)
def test_raises_exception_if_all_nodes_have_predecessors(self): s1, s2, s3 = 1, 2, 3 H = DirectedHypergraph() H.add_nodes([s1, s2, s3]) e1 = H.add_hyperedge([s1], [s2]) T = {s1: e1, s2: e1, s3: e1} self.assertRaises(ValueError, directed_paths.get_hyperpath_from_predecessors, H, T, s1, s2)
def test_raises_exception_if_values_of_function_are_not__in_hypergraph( self): s1, s2, s3 = 1, 2, 3 H = DirectedHypergraph() H.add_nodes([s1, s2]) e1 = H.add_hyperedge([s1], [s2]) T = {s1: None, s2: 'e2'} self.assertRaises(KeyError, directed_paths.get_hyperpath_from_predecessors, H, T, s1, s2)
def test_raises_exception_if_values_of_function_are_not__in_hypergraph( self): s1, s2, s3 = 1, 2, 3 H = DirectedHypergraph() H.add_nodes([s1, s2]) e1 = H.add_hyperedge([s1], [s2]) T = {s1: None, s2: 'e2'} self.assertRaises(KeyError, directed_paths.get_hyperpath_from_predecessors, H, T, s1, s2)
def test_raises_exception_if_k_not_positive(self): H = DirectedHypergraph() source, destination = 1, 2 H.add_nodes([source, destination]) self.assertRaises(ValueError, ksh.k_shortest_hyperpaths, H, source, destination, -4) self.assertRaises(ValueError, ksh.k_shortest_hyperpaths, H, source, destination, 0)
def get_hypertree_from_predecessors(H, Pv, source_node, node_weights=None, attr_name="weight"): """Gives the hypertree (i.e., the subhypergraph formed from the union of the set of paths from an execution of, e.g., the SBT algorithm) defined by Pv beginning at a source node. Returns a dictionary mapping each node to the ID of the hyperedge that preceeded it in the path (i.e., a Pv vector). Assigns the node weights (if provided) as attributes of the nodes (e.g., the rank of that node in a specific instance of the SBT algorithm, or the cardinality of that node in a B-Visit traversal, etc.). :note: The IDs of the hyperedges in the subhypergraph returned may be different than those in the original hypergraph (even though the tail and head sets are identical). :param H: the hypergraph which the path algorithm was executed on. :param Pv: dictionary mapping each node to the ID of the hyperedge that preceeded it in the path. :param source_node: the root of the executed path algorithm. :param node_weights: [optional] dictionary mapping each node to some weight measure. :param attr_name: key into the nodes' attribute dictionaries for their weight values (if node_weights is provided). :returns: DirectedHypergraph -- subhypergraph induced by the path algorithm specified by the predecessor vector (Pv) from a source node. :raises: TypeError -- Algorithm only applicable to directed hypergraphs """ if not isinstance(H, DirectedHypergraph): raise TypeError("Algorithm only applicable to directed hypergraphs") sub_H = DirectedHypergraph() # If node weights are not provided, simply collect all the nodes that are # will be in the hypertree if node_weights is None: nodes = [node for node in Pv.keys() if Pv[node] is not None] nodes.append(source_node) # If node weights are provided, collect all the nodes that will be in the # tree and pair them with their corresponding weights else: nodes = [(node, {attr_name: node_weights[node]}) for node in Pv.keys() if Pv[node] is not None] nodes.append((source_node, {attr_name: node_weights[source_node]})) # Add the collected elements to the hypergraph sub_H.add_nodes(nodes) # Add all hyperedges, specified by Pv, to the hypergraph hyperedges = [(H.get_hyperedge_tail(hyperedge_id), H.get_hyperedge_head(hyperedge_id), H.get_hyperedge_attributes(hyperedge_id)) for hyperedge_id in Pv.values() if hyperedge_id is not None] sub_H.add_hyperedges(hyperedges) return sub_H
def test_returns_hyperpath_for_simple_tree(self): s1, s2, s3, s4 = 1, 2, 3, 4 H = DirectedHypergraph() H.add_nodes([s1, s2, s3, s4]) e1 = H.add_hyperedge([s1], [s2]) e2 = H.add_hyperedge([s1], [s3]) e3 = H.add_hyperedge([s3], [s4]) T = {s4: e3, s3: e2, s2: e1, s1: None} path = directed_paths.get_hyperpath_from_predecessors(H, T, s1, s4) # validate nodes self.assertEqual(path.get_node_set(), {s1, s3, s4}) # validate hyperedges self.assertEqual(len(path.get_hyperedge_id_set()), 2) self.assertTrue(path.get_hyperedge_id([1], [3])) self.assertTrue(path.get_hyperedge_id([3], [4]))
def test_returns_hyperpath_for_simple_tree(self): s1, s2, s3, s4 = 1, 2, 3, 4 H = DirectedHypergraph() H.add_nodes([s1, s2, s3, s4]) e1 = H.add_hyperedge([s1], [s2]) e2 = H.add_hyperedge([s1], [s3]) e3 = H.add_hyperedge([s3], [s4]) T = {s4: e3, s3: e2, s2: e1, s1: None} path = directed_paths.get_hyperpath_from_predecessors(H, T, s1, s4) # validate nodes self.assertEqual(path.get_node_set(), {s1, s3, s4}) # validate hyperedges self.assertEqual(len(path.get_hyperedge_id_set()), 2) self.assertTrue(path.get_hyperedge_id([1], [3])) self.assertTrue(path.get_hyperedge_id([3], [4]))
def test_copy(): node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] node_d = 'D' H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) tail1 = set([node_a, node_b]) head1 = set([node_c, node_d]) frozen_tail1 = frozenset(tail1) frozen_head1 = frozenset(head1) tail2 = set([node_b, node_c]) head2 = set([node_d, node_a]) frozen_tail2 = frozenset(tail2) frozen_head2 = frozenset(head2) attrib = {'weight': 6, 'color': 'black'} common_attrib = {'sink': False} hyperedges = [(tail1, head1, attrib), (tail2, head2)] hyperedge_names = \ H.add_hyperedges(hyperedges, common_attrib, color='white') new_H = H.copy() assert new_H._node_attributes == H._node_attributes assert new_H._hyperedge_attributes == H._hyperedge_attributes assert new_H._backward_star == H._backward_star assert new_H._forward_star == H._forward_star assert new_H._successors == H._successors assert new_H._predecessors == H._predecessors
def test_copy(): node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] node_d = 'D' H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) tail1 = set([node_a, node_b]) head1 = set([node_c, node_d]) frozen_tail1 = frozenset(tail1) frozen_head1 = frozenset(head1) tail2 = set([node_b, node_c]) head2 = set([node_d, node_a]) frozen_tail2 = frozenset(tail2) frozen_head2 = frozenset(head2) attrib = {'weight': 6, 'color': 'black'} common_attrib = {'sink': False} hyperedges = [(tail1, head1, attrib), (tail2, head2)] hyperedge_names = \ H.add_hyperedges(hyperedges, common_attrib, color='white') new_H = H.copy() assert new_H._node_attributes == H._node_attributes assert new_H._hyperedge_attributes == H._hyperedge_attributes assert new_H._backward_star == H._backward_star assert new_H._forward_star == H._forward_star assert new_H._successors == H._successors assert new_H._predecessors == H._predecessors
def test_returns_hyperpath_for_tree_with_multiple_nodes_in_tail(self): s1, s2, s3 = 1, 2, 3 s4, s5, s6 = 4, 5, 6 H = DirectedHypergraph() H.add_nodes([s1, s2, s3, s4, s5, s6]) e1 = H.add_hyperedge([s1], [s2]) e2 = H.add_hyperedge([s1], [s3]) e3 = H.add_hyperedge([s1], [s4]) e4 = H.add_hyperedge([s2, s3], [s5]) e5 = H.add_hyperedge([s5], [s6]) T = {s6: e5, s5: e4, s4: e3, s3: e2, s2: e1, s1: None} path = directed_paths.get_hyperpath_from_predecessors(H, T, s1, s6) # validate nodes self.assertEqual(path.get_node_set(), {s1, s2, s3, s5, s6}) # validate hyperedges self.assertEqual(len(path.get_hyperedge_id_set()), 4) self.assertTrue(path.get_hyperedge_id([5], [6])) self.assertTrue(path.get_hyperedge_id([2, 3], [5])) self.assertTrue(path.get_hyperedge_id([1], [3])) self.assertTrue(path.get_hyperedge_id([1], [2]))
def test_returns_hyperpath_for_tree_with_multiple_nodes_in_tail(self): s1, s2, s3 = 1, 2, 3 s4, s5, s6 = 4, 5, 6 H = DirectedHypergraph() H.add_nodes([s1, s2, s3, s4, s5, s6]) e1 = H.add_hyperedge([s1], [s2]) e2 = H.add_hyperedge([s1], [s3]) e3 = H.add_hyperedge([s1], [s4]) e4 = H.add_hyperedge([s2, s3], [s5]) e5 = H.add_hyperedge([s5], [s6]) T = {s6: e5, s5: e4, s4: e3, s3: e2, s2: e1, s1: None} path = directed_paths.get_hyperpath_from_predecessors(H, T, s1, s6) # validate nodes self.assertEqual(path.get_node_set(), {s1, s2, s3, s5, s6}) # validate hyperedges self.assertEqual(len(path.get_hyperedge_id_set()), 4) self.assertTrue(path.get_hyperedge_id([5], [6])) self.assertTrue(path.get_hyperedge_id([2, 3], [5])) self.assertTrue(path.get_hyperedge_id([1], [3])) self.assertTrue(path.get_hyperedge_id([1], [2]))
def test_add_node(): node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} node_d = 'D' attrib_d = {'label': 'black', 'sink': True} # Test adding unadded nodes with various attribute settings H = DirectedHypergraph() H.add_node(node_a) H.add_node(node_b, source=True) H.add_node(node_c, attrib_c) H.add_node(node_d, attrib_d, sink=False) assert node_a in H._node_attributes assert H._node_attributes[node_a] == {} assert node_b in H._node_attributes assert H._node_attributes[node_b]['source'] is True assert node_c in H._node_attributes assert H._node_attributes[node_c]['alt_name'] == 1337 assert node_d in H._node_attributes assert H._node_attributes[node_d]['label'] == 'black' assert H._node_attributes[node_d]['sink'] is False # Test adding a node that has already been added H.add_nodes(node_a, common=False) assert H._node_attributes[node_a]['common'] is False # Pass in bad (non-dict) attribute try: H.add_node(node_a, ["label", "black"]) assert False except AttributeError: pass except BaseException as e: assert False, e
def test_add_node(): node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} node_d = 'D' attrib_d = {'label': 'black', 'sink': True} # Test adding unadded nodes with various attribute settings H = DirectedHypergraph() H.add_node(node_a) H.add_node(node_b, source=True) H.add_node(node_c, attrib_c) H.add_node(node_d, attrib_d, sink=False) assert node_a in H._node_attributes assert H._node_attributes[node_a] == {} assert node_b in H._node_attributes assert H._node_attributes[node_b]['source'] is True assert node_c in H._node_attributes assert H._node_attributes[node_c]['alt_name'] == 1337 assert node_d in H._node_attributes assert H._node_attributes[node_d]['label'] == 'black' assert H._node_attributes[node_d]['sink'] is False # Test adding a node that has already been added H.add_nodes(node_a, common=False) assert H._node_attributes[node_a]['common'] is False # Pass in bad (non-dict) attribute try: H.add_node(node_a, ["label", "black"]) assert False except AttributeError: pass except BaseException as e: assert False, e
def test_add_nodes(): node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} node_d = 'D' attrib_d = {'label': 'black', 'sink': True} common_attrib = {'common': True, 'source': False} node_list = [ node_a, (node_b, { 'source': False }), (node_c, attrib_c), (node_d, attrib_d) ] # Test adding unadded nodes with various attribute settings H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) assert node_a in H._node_attributes assert H._node_attributes[node_a] == common_attrib assert node_b in H._node_attributes assert H._node_attributes[node_b]['source'] is False assert node_c in H._node_attributes assert H._node_attributes[node_c]['alt_name'] == 1337 assert node_d in H._node_attributes assert H._node_attributes[node_d]['label'] == 'black' assert H._node_attributes[node_d]['sink'] is True node_set = H.get_node_set() assert node_set == set(['A', 'B', 'C', 'D']) assert len(node_set) == len(node_list) for node in H.node_iterator(): assert node in node_set
def test_get_node_attribute(): node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] # Test adding unadded nodes with various attribute settings H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) assert H.get_node_attribute(node_a, 'common') is True assert H.get_node_attribute(node_a, 'source') is False assert H.get_node_attribute(node_b, 'common') is True assert H.get_node_attribute(node_b, 'source') is True assert H.get_node_attribute(node_c, 'alt_name') == 1337 # Try requesting an invalid node try: H.get_node_attribute("D", 'common') assert False except ValueError: pass except BaseException as e: assert False, e # Try requesting an invalid attribute try: H.get_node_attribute(node_a, 'alt_name') assert False except ValueError: pass except BaseException as e: assert False, e
def test_get_node_attribute(): node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] # Test adding unadded nodes with various attribute settings H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) assert H.get_node_attribute(node_a, 'common') is True assert H.get_node_attribute(node_a, 'source') is False assert H.get_node_attribute(node_b, 'common') is True assert H.get_node_attribute(node_b, 'source') is True assert H.get_node_attribute(node_c, 'alt_name') == 1337 # Try requesting an invalid node try: H.get_node_attribute("D", 'common') assert False except ValueError: pass except BaseException as e: assert False, e # Try requesting an invalid attribute try: H.get_node_attribute(node_a, 'alt_name') assert False except ValueError: pass except BaseException as e: assert False, e
def test_check_hyperedge_attributes_consistency(): # make test hypergraph node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] node_d = 'D' H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) tail1 = set([node_a, node_b]) head1 = set([node_c, node_d]) frozen_tail1 = frozenset(tail1) frozen_head1 = frozenset(head1) tail2 = set([node_b, node_c]) head2 = set([node_d, node_a]) frozen_tail2 = frozenset(tail2) frozen_head2 = frozenset(head2) attrib = {'weight': 6, 'color': 'black'} common_attrib = {'sink': False} hyperedges = [(tail1, head1, attrib), (tail2, head2)] hyperedge_names = \ H.add_hyperedges(hyperedges, common_attrib, color='white') # This should not fail H._check_consistency() # The following consistency checks should fail # Check 1.1 new_H = H.copy() del new_H._hyperedge_attributes["e1"]["weight"] try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.2 new_H = H.copy() new_H._hyperedge_attributes["e1"]["tail"] = head1 try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.3 new_H = H.copy() new_H._hyperedge_attributes["e1"]["head"] = tail1 try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.4 new_H = H.copy() del new_H._successors[frozen_tail1] try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.5 new_H = H.copy() del new_H._predecessors[frozen_head1] try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.6 new_H = H.copy() new_H._forward_star["A"].pop() try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.7 new_H = H.copy() new_H._backward_star["C"].pop() try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e
def test_read_and_write(): # Try writing the following hypergraph to a file node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] node_d = 'D' H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) tail1 = set([node_a, node_b]) head1 = set([node_c, node_d]) frozen_tail1 = frozenset(tail1) frozen_head1 = frozenset(head1) tail2 = set([node_b, node_c]) head2 = set([node_d, node_a]) frozen_tail2 = frozenset(tail2) frozen_head2 = frozenset(head2) attrib = {'weight': 6, 'color': 'black'} common_attrib = {'sink': False} hyperedges = [(tail1, head1, attrib), (tail2, head2)] hyperedge_names = \ H.add_hyperedges(hyperedges, common_attrib, color='white') H.write("test_directed_read_and_write.txt") # Try reading the hypergraph that was just written into a new hypergraph new_H = DirectedHypergraph() new_H.read("test_directed_read_and_write.txt") assert H._node_attributes.keys() == new_H._node_attributes.keys() for new_hyperedge_id in new_H.get_hyperedge_id_set(): new_hyperedge_tail = new_H.get_hyperedge_tail(new_hyperedge_id) new_hyperedge_head = new_H.get_hyperedge_head(new_hyperedge_id) new_hyperedge_weight = new_H.get_hyperedge_weight(new_hyperedge_id) found_matching_hyperedge = False for hyperedge_id in H.get_hyperedge_id_set(): hyperedge_tail = H.get_hyperedge_tail(hyperedge_id) hyperedge_head = H.get_hyperedge_head(hyperedge_id) hyperedge_weight = H.get_hyperedge_weight(hyperedge_id) if new_hyperedge_tail == hyperedge_tail and \ new_hyperedge_head == hyperedge_head and \ new_hyperedge_weight == hyperedge_weight: found_matching_hyperedge = True continue assert found_matching_hyperedge remove("test_directed_read_and_write.txt") # Try reading an invalid hypergraph file invalid_H = DirectedHypergraph() try: invalid_H.read("tests/data/invalid_directed_hypergraph.txt") assert False except IOError: pass except BaseException as e: assert False, e
def test_raises_exception_if_source_not_in_graph(self): H = DirectedHypergraph() source, destination = 1, 2 H.add_nodes([source, destination]) self.assertRaises(ValueError, ksh.k_shortest_hyperpaths, H, 3, destination, 1)
def test_raises_exception_if_k_not_integer(self): H = DirectedHypergraph() source, destination = 1, 2 H.add_nodes([source, destination]) self.assertRaises(TypeError, ksh.k_shortest_hyperpaths, H, source, destination, 0.1)
def test_check_node_consistency(): # make test hypergraph node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] node_d = 'D' H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) tail1 = set([node_a, node_b]) head1 = set([node_c, node_d]) frozen_tail1 = frozenset(tail1) frozen_head1 = frozenset(head1) tail2 = set([node_b, node_c]) head2 = set([node_d, node_a]) frozen_tail2 = frozenset(tail2) frozen_head2 = frozenset(head2) attrib = {'weight': 6, 'color': 'black'} common_attrib = {'sink': False} hyperedges = [(tail1, head1, attrib), (tail2, head2)] hyperedge_names = \ H.add_hyperedges(hyperedges, common_attrib, color='white') # This should not fail H._check_consistency() # Check 5.1 new_H = H.copy() new_H._forward_star["X"] = {} try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.2 new_H = H.copy() new_H._backward_star["X"] = {} try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.3.1 new_H = H.copy() new_H.add_hyperedge("X", "Y") del new_H._node_attributes["X"] del new_H._forward_star["X"] del new_H._forward_star["Y"] del new_H._backward_star["X"] del new_H._backward_star["Y"] try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.3.2 new_H = H.copy() new_H.add_hyperedge("X", "Y") del new_H._node_attributes["Y"] del new_H._forward_star["X"] del new_H._forward_star["Y"] del new_H._backward_star["X"] del new_H._backward_star["Y"] try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.4 new_H = H.copy() new_H._predecessors[frozenset("X")] = {} try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.5 new_H = H.copy() new_H._successors[frozenset("X")] = {} new_H._predecessors[frozenset("X")] = {} try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e
def test_raises_exception_if_source_not_in_graph(self): H = DirectedHypergraph() source, destination = 1, 2 H.add_nodes([source, destination]) self.assertRaises(ValueError, ksh.k_shortest_hyperpaths, H, 3, destination, 1)
def test_check_node_consistency(): # make test hypergraph node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] node_d = 'D' H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) tail1 = set([node_a, node_b]) head1 = set([node_c, node_d]) frozen_tail1 = frozenset(tail1) frozen_head1 = frozenset(head1) tail2 = set([node_b, node_c]) head2 = set([node_d, node_a]) frozen_tail2 = frozenset(tail2) frozen_head2 = frozenset(head2) attrib = {'weight': 6, 'color': 'black'} common_attrib = {'sink': False} hyperedges = [(tail1, head1, attrib), (tail2, head2)] hyperedge_names = \ H.add_hyperedges(hyperedges, common_attrib, color='white') # This should not fail H._check_consistency() # Check 5.1 new_H = H.copy() new_H._forward_star["X"] = {} try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.2 new_H = H.copy() new_H._backward_star["X"] = {} try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.3.1 new_H = H.copy() new_H.add_hyperedge("X", "Y") del new_H._node_attributes["X"] del new_H._forward_star["X"] del new_H._forward_star["Y"] del new_H._backward_star["X"] del new_H._backward_star["Y"] try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.3.2 new_H = H.copy() new_H.add_hyperedge("X", "Y") del new_H._node_attributes["Y"] del new_H._forward_star["X"] del new_H._forward_star["Y"] del new_H._backward_star["X"] del new_H._backward_star["Y"] try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.4 new_H = H.copy() new_H._predecessors[frozenset("X")] = {} try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 5.5 new_H = H.copy() new_H._successors[frozenset("X")] = {} new_H._predecessors[frozenset("X")] = {} try: new_H._check_node_consistency() assert False except ValueError: pass except BaseException as e: assert False, e
def test_read_and_write(): # Try writing the following hypergraph to a file node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] node_d = 'D' H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) tail1 = set([node_a, node_b]) head1 = set([node_c, node_d]) frozen_tail1 = frozenset(tail1) frozen_head1 = frozenset(head1) tail2 = set([node_b, node_c]) head2 = set([node_d, node_a]) frozen_tail2 = frozenset(tail2) frozen_head2 = frozenset(head2) attrib = {'weight': 6, 'color': 'black'} common_attrib = {'sink': False} hyperedges = [(tail1, head1, attrib), (tail2, head2)] hyperedge_names = \ H.add_hyperedges(hyperedges, common_attrib, color='white') H.write("test_directed_read_and_write.txt") # Try reading the hypergraph that was just written into a new hypergraph new_H = DirectedHypergraph() new_H.read("test_directed_read_and_write.txt") assert H._node_attributes.keys() == new_H._node_attributes.keys() for new_hyperedge_id in new_H.get_hyperedge_id_set(): new_hyperedge_tail = new_H.get_hyperedge_tail(new_hyperedge_id) new_hyperedge_head = new_H.get_hyperedge_head(new_hyperedge_id) new_hyperedge_weight = new_H.get_hyperedge_weight(new_hyperedge_id) found_matching_hyperedge = False for hyperedge_id in H.get_hyperedge_id_set(): hyperedge_tail = H.get_hyperedge_tail(hyperedge_id) hyperedge_head = H.get_hyperedge_head(hyperedge_id) hyperedge_weight = H.get_hyperedge_weight(hyperedge_id) if new_hyperedge_tail == hyperedge_tail and \ new_hyperedge_head == hyperedge_head and \ new_hyperedge_weight == hyperedge_weight: found_matching_hyperedge = True continue assert found_matching_hyperedge remove("test_directed_read_and_write.txt") # Try reading an invalid hypergraph file invalid_H = DirectedHypergraph() try: invalid_H.read("tests/data/invalid_directed_hypergraph.txt") assert False except IOError: pass except BaseException as e: assert False, e
def test_check_hyperedge_attributes_consistency(): # make test hypergraph node_a = 'A' node_b = 'B' node_c = 'C' attrib_c = {'alt_name': 1337} common_attrib = {'common': True, 'source': False} node_list = [node_a, (node_b, {'source': True}), (node_c, attrib_c)] node_d = 'D' H = DirectedHypergraph() H.add_nodes(node_list, common_attrib) tail1 = set([node_a, node_b]) head1 = set([node_c, node_d]) frozen_tail1 = frozenset(tail1) frozen_head1 = frozenset(head1) tail2 = set([node_b, node_c]) head2 = set([node_d, node_a]) frozen_tail2 = frozenset(tail2) frozen_head2 = frozenset(head2) attrib = {'weight': 6, 'color': 'black'} common_attrib = {'sink': False} hyperedges = [(tail1, head1, attrib), (tail2, head2)] hyperedge_names = \ H.add_hyperedges(hyperedges, common_attrib, color='white') # This should not fail H._check_consistency() # The following consistency checks should fail # Check 1.1 new_H = H.copy() del new_H._hyperedge_attributes["e1"]["weight"] try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.2 new_H = H.copy() new_H._hyperedge_attributes["e1"]["tail"] = head1 try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.3 new_H = H.copy() new_H._hyperedge_attributes["e1"]["head"] = tail1 try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.4 new_H = H.copy() del new_H._successors[frozen_tail1] try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.5 new_H = H.copy() del new_H._predecessors[frozen_head1] try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.6 new_H = H.copy() new_H._forward_star["A"].pop() try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e # Check 1.7 new_H = H.copy() new_H._backward_star["C"].pop() try: new_H._check_consistency() assert False except ValueError: pass except BaseException as e: assert False, e