def from_networkx_digraph(nx_digraph):
    """Returns a DirectedHypergraph object that is the graph equivalent of the
    given NetworkX DiGraph object.

    :param nx_digraph: the NetworkX directed graph object to transform.
    :returns: DirectedHypergraph -- hypergraph object equivalent to the
            NetworkX directed graph.
    :raises: TypeError -- Transformation only applicable to directed
            NetworkX graphs

    """
    import networkx as nx

    if not isinstance(nx_digraph, nx.DiGraph):
        raise TypeError("Transformation only applicable to directed \
                        NetworkX graphs")

    G = DirectedHypergraph()

    for node in nx_digraph.nodes_iter():
        G.add_node(node, copy.copy(nx_digraph.node[node]))

    for edge in nx_digraph.edges_iter():
        tail_node = edge[0]
        head_node = edge[1]
        G.add_hyperedge(tail_node,
                        head_node,
                        copy.copy(nx_digraph[tail_node][head_node]))

    return G
def test_stationary_distribution():
    H = DirectedHypergraph()
    H.read("./tests/data/basic_directed_hypergraph.txt")

    # Try random-walking a directed hypergraph with a node
    # with no outgoing hyperedges
    try:
        pi = rw.stationary_distribution(H)
        assert False
    except AssertionError:
        pass
    except BaseException as e:
        assert False, e

    # Try random-walking a valid directed hypergraph
    H.add_hyperedge(["u"], ["u"], weight=1)
    pi = rw.stationary_distribution(H)

    # Correctness tests go here

    # Try partitioning an invalid directed hypergraph
    try:
        pi = rw.stationary_distribution("H")
        assert False
    except TypeError:
        pass
    except BaseException as e:
        assert False, e
 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)
Exemple #4
0
def convert_pnet_to_hypergraph_andgatewayonly(pnet):
    hg = DirectedHypergraph()
    #scan all transitions and create hyperedges
    transitions = get_transitions(pnet)
    for transition in transitions:
        #get all incoming arcs, the source of these become the tail of hyperedge
        inc_arcs = get_incoming_arcs(transition, pnet)
        tail = []
        for inc_arc in inc_arcs:
            source = str(get_arc_source(inc_arc))
            tail.append(source)
        #get all outgoing arcs, the target of these become the head of the hyperedge
        out_arcs = get_outgoing_arcs(transition, pnet)
        head = []
        for out_arc in out_arcs:
            target = str(get_arc_target(out_arc))
            head.append(target)
        name = get_transition_name(transition)
        hg.add_hyperedge(tail,
                         head,
                         name=name,
                         phero=0.5,
                         cost=0.4,
                         avail=0.6,
                         qual=0.2,
                         time=0.99)
    #print the result before exit
    print_hg_std_out_only(hg)
    return hg
def from_networkx_digraph(nx_digraph):
    """Returns a DirectedHypergraph object that is the graph equivalent of the
    given NetworkX DiGraph object.

    :param nx_digraph: the NetworkX directed graph object to transform.
    :returns: DirectedHypergraph -- hypergraph object equivalent to the
            NetworkX directed graph.
    :raises: TypeError -- Transformation only applicable to directed
            NetworkX graphs

    """
    import networkx as nx

    if not isinstance(nx_digraph, nx.DiGraph):
        raise TypeError("Transformation only applicable to directed \
                        NetworkX graphs")

    G = DirectedHypergraph()

    for node in nx_digraph.nodes():
        G.add_node(node, **copy.copy(nx_digraph.nodes[node]))

    for edge in nx_digraph.edges():
        tail_node = edge[0]
        head_node = edge[1]
        G.add_hyperedge(tail_node, head_node,
                        copy.copy(nx_digraph[tail_node][head_node]))

    return G
def reset_pheromone(hg):
    '''
    Reset the pheromone level to a default (0.5)
    :param hg:
    '''
    hg_copy = DirectedHypergraph()
    for edge in hg.get_hyperedge_id_set():
        #hg_copy = hg.copy()
        PHERO_DEFAULT = 0.5
        head_edge = hg.get_hyperedge_head(edge)
        #head_edge = ast.literal_eval(head_edge)
        #print(head_edge)
        for head_node in head_edge:
            #print(head_node)
            attrs = hg.get_node_attributes(head_node)
            hg_copy.add_node(head_node, attrs)
        tail_edge = hg.get_hyperedge_tail(edge)
        #tail_edge = ast.literal_eval(tail_edge)
        for tail_node in tail_edge:
            attrs = hg.get_node_attributes(tail_node)
            hg_copy.add_node(tail_node, attrs)
        hg_copy.add_hyperedge(tail_edge,
                              head_edge,
                              phero=PHERO_DEFAULT,
                              id=edge,
                              name=edge)

    return hg_copy
 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_returns_empty_list_if_no_s_t_path(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'1', '2'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        self.assertEqual(output, [])
    def test_returns_empty_list_if_no_s_t_path(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'1', '2'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        self.assertEqual(output, [])
def test_add_hyperedge():
    node_a = 'A'
    node_b = 'B'
    node_c = 'C'
    node_d = 'D'

    tail = set([node_a, node_b])
    head = set([node_c, node_d])
    frozen_tail = frozenset(tail)
    frozen_head = frozenset(head)

    attrib = {'weight': 6, 'color': 'black'}

    H = DirectedHypergraph()
    H.add_node(node_a, label=1337)
    hyperedge_name = H.add_hyperedge(tail, head, attrib, weight=5)

    assert hyperedge_name == 'e1'

    # Test that all hyperedge attributes are correct
    assert H._hyperedge_attributes[hyperedge_name]['tail'] == tail
    assert H._hyperedge_attributes[hyperedge_name]['head'] == head
    assert H._hyperedge_attributes[hyperedge_name]['weight'] == 5
    assert H._hyperedge_attributes[hyperedge_name]['color'] == 'black'

    # Test that successor list contains the correct info
    assert frozen_head in H._successors[frozen_tail]
    assert hyperedge_name in H._successors[frozen_tail][frozen_head]

    # Test that the precessor list contains the correct info
    assert frozen_tail in H._predecessors[frozen_head]
    assert hyperedge_name in H._predecessors[frozen_head][frozen_tail]

    # Test that forward-stars and backward-stars contain the correct info
    for node in frozen_tail:
        assert hyperedge_name in H._forward_star[node]
    for node in frozen_head:
        assert hyperedge_name in H._backward_star[node]

    # Test that adding same hyperedge will only update attributes
    new_attrib = {'weight': 10}
    H.add_hyperedge(tail, head, new_attrib)
    assert H._hyperedge_attributes[hyperedge_name]['weight'] == 10
    assert H._hyperedge_attributes[hyperedge_name]['color'] == 'black'

    try:
        H.add_hyperedge(set(), set())
        assert False
    except ValueError:
        pass
    except BaseException as e:
        assert False, e
Exemple #11
0
def trim(H, F, e, source, taildistancelist):
    '''
    Takes the edge list F, which is a super path from the source vertex to e and repeatedly removes an edge and checks reachability for each edge in F
    Returns the trimmed edge list and prints that the sink is not reachable from the source if the original edge set is not a superpath
    '''
    sortededges = []
    if e[0] != 'e':
        reachingset = [e]
    else:
        reachingset = H.get_hyperedge_tail(e)

    for f in F:
        sortededges.append((taildistancelist[f], f))
    sortededges.sort()
    justedges = [s[1] for s in sortededges]
    H2 = DirectedHypergraph()
    H2.add_node(source)
    H2edgeids = {}
    for f in justedges:
        newf = H2.add_hyperedge(H.get_hyperedge_tail(f),
                                H.get_hyperedge_head(f))
        H2edgeids[f] = newf
    nodeset, _, __, ___ = b_visit(H2, source)
    isereached = True
    for v in reachingset:
        if v not in nodeset:
            isereached = False
    if isereached == False:
        print('invalid edge set given to trim. Sink not reachable from source')
        print(nodeset)
    F2 = []
    tailedges = []
    for f in justedges:
        H2.remove_hyperedge(H2edgeids[f])
        nodeset, _, __, ___ = b_visit(H2, source)
        isereached = True
        for v in reachingset:
            if v not in nodeset:
                isereached = False
        if isereached == False:
            #This means we cannot remove f
            newf = H2.add_hyperedge(H.get_hyperedge_tail(f),
                                    H.get_hyperedge_head(f))
            H2edgeids[f] = newf
            F2.append(f)
            if e[0] == 'e':
                for v in H.get_hyperedge_tail(e):
                    if v in H.get_hyperedge_head(f):
                        tailedges.append(f)
    if e[0] == 'e':
        F2.append(e)
    return F2, tailedges
def test_add_hyperedge():
    node_a = 'A'
    node_b = 'B'
    node_c = 'C'
    node_d = 'D'

    tail = set([node_a, node_b])
    head = set([node_c, node_d])
    frozen_tail = frozenset(tail)
    frozen_head = frozenset(head)

    attrib = {'weight': 6, 'color': 'black'}

    H = DirectedHypergraph()
    H.add_node(node_a, label=1337)
    hyperedge_name = H.add_hyperedge(tail, head, attrib, weight=5)

    assert hyperedge_name == 'e1'

    # Test that all hyperedge attributes are correct
    assert H._hyperedge_attributes[hyperedge_name]['tail'] == tail
    assert H._hyperedge_attributes[hyperedge_name]['head'] == head
    assert H._hyperedge_attributes[hyperedge_name]['weight'] == 5
    assert H._hyperedge_attributes[hyperedge_name]['color'] == 'black'

    # Test that successor list contains the correct info
    assert frozen_head in H._successors[frozen_tail]
    assert hyperedge_name in H._successors[frozen_tail][frozen_head]

    # Test that the precessor list contains the correct info
    assert frozen_tail in H._predecessors[frozen_head]
    assert hyperedge_name in H._predecessors[frozen_head][frozen_tail]

    # Test that forward-stars and backward-stars contain the correct info
    for node in frozen_tail:
        assert hyperedge_name in H._forward_star[node]
    for node in frozen_head:
        assert hyperedge_name in H._backward_star[node]

    # Test that adding same hyperedge will only update attributes
    new_attrib = {'weight': 10}
    H.add_hyperedge(tail, head, new_attrib)
    assert H._hyperedge_attributes[hyperedge_name]['weight'] == 10
    assert H._hyperedge_attributes[hyperedge_name]['color'] == 'black'

    try:
        H.add_hyperedge(set(), set())
        assert False
    except ValueError:
        pass
    except BaseException as e:
        assert False, e
Exemple #13
0
 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_get_hyperedge_attributes():
    node_a = 'A'
    node_b = 'B'
    node_c = 'C'
    node_d = 'D'

    tail = set([node_a, node_b])
    head = set([node_c, node_d])
    frozen_tail = frozenset(tail)
    frozen_head = frozenset(head)

    attrib = {'weight': 6, 'color': 'black'}

    H = DirectedHypergraph()
    H.add_node(node_a, label=1337)
    hyperedge_name = H.add_hyperedge(tail, head, attrib, weight=5)

    assert H.get_hyperedge_attributes(hyperedge_name) == \
        {'tail': tail, 'head': head, 'weight': 5, 'color': 'black'}

    # Test getting non-existent hyperedge's attributes
    try:
        H.get_hyperedge_attributes("e10")
        assert False
    except ValueError:
        pass
    except BaseException as e:
        assert False, e
def test_get_hyperedge_attributes():
    node_a = 'A'
    node_b = 'B'
    node_c = 'C'
    node_d = 'D'

    tail = set([node_a, node_b])
    head = set([node_c, node_d])
    frozen_tail = frozenset(tail)
    frozen_head = frozenset(head)

    attrib = {'weight': 6, 'color': 'black'}

    H = DirectedHypergraph()
    H.add_node(node_a, label=1337)
    hyperedge_name = H.add_hyperedge(tail, head, attrib, weight=5)

    assert H.get_hyperedge_attributes(hyperedge_name) == \
        {'tail': tail, 'head': head, 'weight': 5, 'color': 'black'}

    # Test getting non-existent hyperedge's attributes
    try:
        H.get_hyperedge_attributes("e10")
        assert False
    except ValueError:
        pass
    except BaseException as e:
        assert False, e
Exemple #17
0
    def test_returns_hyperpath_when_node_is_in_tail_of_two_edges(self):
        s1, s2, s3 = 1, 2, 3
        s4 = 4
        H = DirectedHypergraph()
        e1 = H.add_hyperedge([s1], [s2])
        e2 = H.add_hyperedge([s2], [s3])
        e3 = H.add_hyperedge([s2, 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, s2, s3, s4})
        # validate hyperedges
        self.assertEqual(len(path.get_hyperedge_id_set()), 3)
        self.assertTrue(path.get_hyperedge_id([2, 3], [4]))
        self.assertTrue(path.get_hyperedge_id([2], [3]))
        self.assertTrue(path.get_hyperedge_id([1], [2]))
    def test_returns_hyperpath_when_node_is_in_tail_of_two_edges(self):
        s1, s2, s3 = 1, 2, 3
        s4 = 4
        H = DirectedHypergraph()
        e1 = H.add_hyperedge([s1], [s2])
        e2 = H.add_hyperedge([s2], [s3])
        e3 = H.add_hyperedge([s2, 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, s2, s3, s4})
        # validate hyperedges
        self.assertEqual(len(path.get_hyperedge_id_set()), 3)
        self.assertTrue(path.get_hyperedge_id([2, 3], [4]))
        self.assertTrue(path.get_hyperedge_id([2], [3]))
        self.assertTrue(path.get_hyperedge_id([1], [2]))
Exemple #19
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)
Exemple #21
0
 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 makeHypergraph(model):

    S = create_stoichiometric_matrix(model, array_type='DataFrame')
    H = DirectedHypergraph()

    for i in range(len(S.columns)):
        nodes_df = S.iloc[:, i][S.iloc[:, i] != 0]

        edge_name = nodes_df.name
        head_nodes = set(nodes_df[nodes_df > 0].index)
        tail_nodes = set(nodes_df[nodes_df < 0].index)

        H.add_hyperedge(head_nodes, tail_nodes, {'reaction': edge_name})

        if model.reactions.get_by_id(edge_name).reversibility:

            H.add_hyperedge(tail_nodes, head_nodes,
                            {'reaction': edge_name + '_rev'})

    return H
 def test_returns_disconnected_nodes_on_graph_with_two_nodes(self):
     H = DirectedHypergraph()
     s, t = 's', 't'
     H.add_node(s)
     H.add_node(t)
     e1 = H.add_hyperedge({s}, {t})
     predecessor = {s: None, t: e1}
     ordering = [s, t]
     branch = ksh._branching_step(H, predecessor, ordering)[0]
     self.assertEqual(branch.get_hyperedge_id_set(), set([]))
     self.assertEqual(branch.get_node_set(), {'s', 't'})
 def test_returns_disconnected_nodes_on_graph_with_two_nodes(self):
     H = DirectedHypergraph()
     s, t = 's', 't'
     H.add_node(s)
     H.add_node(t)
     e1 = H.add_hyperedge({s}, {t})
     predecessor = {s: None, t: e1}
     ordering = [s, t]
     branch = ksh._branching_step(H, predecessor, ordering)[0]
     self.assertEqual(branch.get_hyperedge_id_set(), set([]))
     self.assertEqual(branch.get_node_set(), {'s', 't'})
    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]))
Exemple #27
0
    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]))
Exemple #28
0
def random_generate_hg(level_size, block_size_min, block_size_max):
    '''
    Generate a random hypergraph
    :param level_size: number of rewriting levels (at each level an 'and' or 'xor' block is randomly chosen for rewriting)
    :param block_size: min size of a block (number of branches)
    :param block_size: max size of a block (number of branches)
    '''
    hg = DirectedHypergraph()
    # create source and sink nodes
    source_attrs = generate_random_node_attributes()
    source_attrs['source'] = True
    sink_attrs = generate_random_node_attributes()
    sink_attrs['sink'] = True
    source = 'source'
    hg.add_node(source, source_attrs)
    sink = 'sink'
    hg.add_node(sink, sink_attrs)
    edge_attrs = {'phero' : 0.5}
    source_list = []
    sink_list = []
    source_list.append(source)
    sink_list.append(sink)
    hg.add_hyperedge(source_list, sink_list, edge_attrs)
    
    
    node_start_list = source_list
    node_end_list = sink_list
    
    # add 1 node
    node_middle = generate_random_node_list(hg, 1)
    hg.add_hyperedge(source_list, node_middle, edge_attrs)
    hg.add_hyperedge(node_middle, sink_list, edge_attrs)
    hg.remove_hyperedge(hg.get_hyperedge_id(source_list, sink_list))
    
    #print_hg_std_out_only(hg)
    
    # add one xor block
    #hg = rewrite_xor_block(hg, node_middle[0], 2)[0]
    #hg = rewrite_and_block(hg, node_middle[0], 4)[0]
    
    
    #print_hg_std_out_only(hg)
    
    # generation of test hypergraph
    current_node = node_middle[0]
    
    SIZE = level_size
    for i in range(0, SIZE, 1):
        size = randint(block_size_min, block_size_max)                                # pick size randomly
        if uniform(0,1) > 0.5:                              # make an and block
            out = rewrite_and_block(hg, current_node, size)
            hg, current_node = out[0], out[1]
            
        else:                                               # make a xor block
            out = rewrite_xor_block(hg, current_node, size)
            hg, current_node = out[0], out[1]
    
    #print_hg_std_out_only(hg)
    
    return hg
def convert_pnet_to_hypergraph_andgatewayonly(pnet):
    hg = DirectedHypergraph()
    #scan all transitions and create hyperedges
    transitions = get_transitions(pnet)
    for transition in transitions:
        #get all incoming arcs, the source of these become the tail of hyperedge
        inc_arcs = get_incoming_arcs(transition,pnet)
        tail = []
        for inc_arc in inc_arcs:
            source = str(get_arc_source(inc_arc))
            tail.append(source)
        #get all outgoing arcs, the target of these become the head of the hyperedge
        out_arcs = get_outgoing_arcs(transition,pnet)
        head = []
        for out_arc in out_arcs:
            target = str(get_arc_target(out_arc))
            head.append(target)
        name = get_transition_name(transition)
        hg.add_hyperedge(tail, head, name = name, phero = 0.5, cost = 0.4, avail = 0.6, qual = 0.2, time = 0.99)
    #print the result before exit
    print_hg_std_out_only(hg)
    return hg
Exemple #30
0
def read_hg_from_file(file_name):
    '''
    returns a hypergraph based on the info in a file. Assumption: file_name has been written using write_hg_on_file
    :param file_name:
    '''
    hg = DirectedHypergraph()
    
    in_file = open(file_name, 'r')
    lines = in_file.readlines()
    sep = '\t'
    for line in lines:
        #line.strip()
        values = line.split(sep)
        #for value in values:
        if values[0] == 'node':
            # I am processing a node
            node_id = values[1]
            node_attrs = ast.literal_eval(values[2])
            hg.add_node(node_id, node_attrs)
        if values[0] == 'edge':
            tail = None
            head = None
            edge = values[1]
            edge_attrs = ast.literal_eval(values[2])
            # I am processsing an edge
            for j in range(2, len(values), 1):
                values[j] = values[j].strip()
                tail = edge_attrs['tail']
                #print(tail)
                #tail_list = eval(tail)
                head = edge_attrs['head']
                # turn string representation of head into an actual list
                #head_list = ast.literal_eval(head)
            #print("ID, TAIL, HEAD: {2} - {0} - {1} - {3}".format(tail,head,values[1], edge_attrs))
            hg.add_hyperedge(tail, head, edge_attrs)
    print_hg_std_out_only(hg)
    in_file.close()    
    return hg
    def test_returns_only_one_hyperpath_for_k_equals_one(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('3')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'s'}, {'2'}, weight=1)
        H.add_hyperedge({'s'}, {'3'}, weight=1)
        H.add_hyperedge({'1'}, {'t'}, weight=1)
        H.add_hyperedge({'2', '3'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        self.assertEqual(len(output), 1)
    def test_returns_only_one_hyperpath_for_k_equals_one(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('3')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'s'}, {'2'}, weight=1)
        H.add_hyperedge({'s'}, {'3'}, weight=1)
        H.add_hyperedge({'1'}, {'t'}, weight=1)
        H.add_hyperedge({'2', '3'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        self.assertEqual(len(output), 1)
def test_is_BF_hypergraph():
    H = DirectedHypergraph()
    H.read("tests/data/basic_directed_hypergraph.txt")

    assert not H.is_BF_hypergraph()

    H = DirectedHypergraph()
    H.add_hyperedge(['a', 'b'], ['c'])
    assert H.is_BF_hypergraph()

    H = DirectedHypergraph()
    H.add_hyperedge(['x'], ['y', 'z'])
    assert H.is_BF_hypergraph()

    H = DirectedHypergraph()
    H.add_hyperedge(['a', 'b'], ['c'])
    H.add_hyperedge(['x'], ['y', 'z'])
    assert H.is_BF_hypergraph()
def test_is_BF_hypergraph():
    H = DirectedHypergraph()
    H.read("tests/data/basic_directed_hypergraph.txt")

    assert not H.is_BF_hypergraph()

    H = DirectedHypergraph()
    H.add_hyperedge(['a', 'b'], ['c'])
    assert H.is_BF_hypergraph()

    H = DirectedHypergraph()
    H.add_hyperedge(['x'], ['y', 'z'])
    assert H.is_BF_hypergraph()

    H = DirectedHypergraph()
    H.add_hyperedge(['a', 'b'], ['c'])
    H.add_hyperedge(['x'], ['y', 'z'])
    assert H.is_BF_hypergraph()
    def test_returns_shortest_hyperpath_for_k_equals_one(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('3')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'s'}, {'2'}, weight=1)
        H.add_hyperedge({'s'}, {'3'}, weight=1)
        H.add_hyperedge({'1'}, {'t'}, weight=1)
        H.add_hyperedge({'2', '3'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        hyperpath = output[0]
        self.assertEqual(hyperpath.get_node_set(), {'s', '1', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 2)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'1'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1'}, {'t'}))
    def test_returns_shortest_hyperpath_for_k_equals_one(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('3')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'s'}, {'2'}, weight=1)
        H.add_hyperedge({'s'}, {'3'}, weight=1)
        H.add_hyperedge({'1'}, {'t'}, weight=1)
        H.add_hyperedge({'2', '3'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        hyperpath = output[0]
        self.assertEqual(hyperpath.get_node_set(), {'s', '1', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 2)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'1'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1'}, {'t'}))
class TestComputeLowerBound(unittest.TestCase):
    def setUp(self):
        self.nielsenGraph = DirectedHypergraph()
        self.nielsenGraph.add_node('s')
        self.nielsenGraph.add_node('1')
        self.nielsenGraph.add_node('2')
        self.nielsenGraph.add_node('3')
        self.nielsenGraph.add_node('4')
        self.nielsenGraph.add_node('t')
        self.nielsenGraph.add_hyperedge({'s'}, {'1'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1', '2'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2', '3'}, {'4'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'1'}, weight=1)

    def test_returns_12_for_lower_bound_for_nielsen_H_21(self):
        '''
            Test graph is discussed in Section 3.2 example 2 of
            Nielsen et al.\
        '''
        H_2 = self.nielsenGraph.copy()
        e1 = H_2.get_hyperedge_id({'s'}, {'1'})
        e2 = H_2.get_hyperedge_id({'1'}, {'2'})
        e3 = H_2.get_hyperedge_id({'1', '2'}, {'t'})
        H_2.remove_hyperedge(H_2.get_hyperedge_id({'s'}, {'2'}))
        H_2.remove_hyperedge(H_2.get_hyperedge_id({'4'}, {'t'}))

        # weight vector
        W = {'s': 0, '1': 1, '2': 2, '3': 1, '4': 4, 't': 4}
        # predecessor function
        pred = {'s': None, '1': e1, '2': e2, 't': e3}
        # ordering
        ordering = ['s', '1', '2', 't']

        # branch of H_2 for the test
        H_2_1 = H_2.copy()
        H_2_1.remove_hyperedge(H_2_1.get_hyperedge_id({'s'}, {'1'}))

        self.assertEqual(
            ksh._compute_lower_bound(H_2_1, 0, pred, ordering, W, 't'), 12)
class TestBranchingStep(unittest.TestCase):
    def setUp(self):
        self.nielsenGraph = DirectedHypergraph()
        self.nielsenGraph.add_node('s')
        self.nielsenGraph.add_node('1')
        self.nielsenGraph.add_node('2')
        self.nielsenGraph.add_node('3')
        self.nielsenGraph.add_node('4')
        self.nielsenGraph.add_node('t')
        self.nielsenGraph.add_hyperedge({'s'}, {'1'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1', '2'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2', '3'}, {'4'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'1'}, weight=1)

    def test_returns_disconnected_nodes_on_graph_with_two_nodes(self):
        H = DirectedHypergraph()
        s, t = 's', 't'
        H.add_node(s)
        H.add_node(t)
        e1 = H.add_hyperedge({s}, {t})
        predecessor = {s: None, t: e1}
        ordering = [s, t]
        branch = ksh._branching_step(H, predecessor, ordering)[0]
        self.assertEqual(branch.get_hyperedge_id_set(), set([]))
        self.assertEqual(branch.get_node_set(), {'s', 't'})

    def test_returns_correct_branching_for_nielsen_graph(self):
        H = self.nielsenGraph
        ordering = ['s', '1', '2', 't']
        pred = {
            's': None,
            '1': H.get_hyperedge_id({'s'}, {'1'}),
            '2': H.get_hyperedge_id({'s'}, {'2'}),
            't': H.get_hyperedge_id({'2', '1'}, {'t'})
        }

        branches = ksh._branching_step(H, pred, ordering)
        self.assertEqual(len(branches), 3)
        # branch 1
        b1 = branches[0]
        self.assertEqual(b1.get_node_set(), H.get_node_set())
        hyperedges = b1.get_hyperedge_id_set()
        hyperedgesTuple = [(b1.get_hyperedge_tail(e), b1.get_hyperedge_head(e))
                           for e in hyperedges]
        self.assertEqual(len(hyperedges), 6)
        self.assertIn(({'s'}, {'2'}), hyperedgesTuple)
        self.assertIn(({'s'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'2'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'2', '3'}, {'4'}), hyperedgesTuple)
        self.assertIn(({'1', '2'}, {'t'}), hyperedgesTuple)
        self.assertIn(({'4'}, {'1'}), hyperedgesTuple)
        # branch 2
        b2 = branches[1]
        self.assertEqual(b2.get_node_set(), H.get_node_set())
        hyperedges = b2.get_hyperedge_id_set()
        hyperedgesTuple = [(b2.get_hyperedge_tail(e), b2.get_hyperedge_head(e))
                           for e in hyperedges]
        self.assertEqual(len(hyperedges), 7)
        self.assertIn(({'s'}, {'1'}), hyperedgesTuple)
        self.assertIn(({'s'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'1'}, {'2'}), hyperedgesTuple)
        self.assertIn(({'2'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'2', '3'}, {'4'}), hyperedgesTuple)
        self.assertIn(({'1', '2'}, {'t'}), hyperedgesTuple)
        self.assertIn(({'4'}, {'1'}), hyperedgesTuple)
        # branch 3
        b3 = branches[2]
        self.assertEqual(b3.get_node_set(), H.get_node_set())
        hyperedges = b3.get_hyperedge_id_set()
        hyperedgesTuple = [(b3.get_hyperedge_tail(e), b3.get_hyperedge_head(e))
                           for e in hyperedges]
        self.assertEqual(len(hyperedges), 8)
        self.assertIn(({'s'}, {'1'}), hyperedgesTuple)
        self.assertIn(({'s'}, {'2'}), hyperedgesTuple)
        self.assertIn(({'s'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'1'}, {'2'}), hyperedgesTuple)
        self.assertIn(({'2'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'2', '3'}, {'4'}), hyperedgesTuple)
        self.assertIn(({'4'}, {'t'}), hyperedgesTuple)
        self.assertIn(({'4'}, {'1'}), hyperedgesTuple)
class TestBranchingStep(unittest.TestCase):

    def setUp(self):
        self.nielsenGraph = DirectedHypergraph()
        self.nielsenGraph.add_node('s')
        self.nielsenGraph.add_node('1')
        self.nielsenGraph.add_node('2')
        self.nielsenGraph.add_node('3')
        self.nielsenGraph.add_node('4')
        self.nielsenGraph.add_node('t')
        self.nielsenGraph.add_hyperedge({'s'}, {'1'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1', '2'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2', '3'}, {'4'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'1'}, weight=1)

    def test_returns_disconnected_nodes_on_graph_with_two_nodes(self):
        H = DirectedHypergraph()
        s, t = 's', 't'
        H.add_node(s)
        H.add_node(t)
        e1 = H.add_hyperedge({s}, {t})
        predecessor = {s: None, t: e1}
        ordering = [s, t]
        branch = ksh._branching_step(H, predecessor, ordering)[0]
        self.assertEqual(branch.get_hyperedge_id_set(), set([]))
        self.assertEqual(branch.get_node_set(), {'s', 't'})

    def test_returns_correct_branching_for_nielsen_graph(self):
        H = self.nielsenGraph
        ordering = ['s', '1', '2', 't']
        pred = {'s': None, '1': H.get_hyperedge_id({'s'}, {'1'}),
                '2': H.get_hyperedge_id({'s'}, {'2'}),
                't': H.get_hyperedge_id({'2', '1'}, {'t'})}

        branches = ksh._branching_step(H, pred, ordering)
        self.assertEqual(len(branches), 3)
        # branch 1
        b1 = branches[0]
        self.assertEqual(b1.get_node_set(), H.get_node_set())
        hyperedges = b1.get_hyperedge_id_set()
        hyperedgesTuple = [(b1.get_hyperedge_tail(e),
                            b1.get_hyperedge_head(e))
                           for e in hyperedges]
        self.assertEqual(len(hyperedges), 6)
        self.assertIn(({'s'}, {'2'}), hyperedgesTuple)
        self.assertIn(({'s'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'2'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'2', '3'}, {'4'}), hyperedgesTuple)
        self.assertIn(({'1', '2'}, {'t'}), hyperedgesTuple)
        self.assertIn(({'4'}, {'1'}), hyperedgesTuple)
        # branch 2
        b2 = branches[1]
        self.assertEqual(b2.get_node_set(), H.get_node_set())
        hyperedges = b2.get_hyperedge_id_set()
        hyperedgesTuple = [(b2.get_hyperedge_tail(e),
                            b2.get_hyperedge_head(e))
                           for e in hyperedges]
        self.assertEqual(len(hyperedges), 7)
        self.assertIn(({'s'}, {'1'}), hyperedgesTuple)
        self.assertIn(({'s'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'1'}, {'2'}), hyperedgesTuple)
        self.assertIn(({'2'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'2', '3'}, {'4'}), hyperedgesTuple)
        self.assertIn(({'1', '2'}, {'t'}), hyperedgesTuple)
        self.assertIn(({'4'}, {'1'}), hyperedgesTuple)
        # branch 3
        b3 = branches[2]
        self.assertEqual(b3.get_node_set(), H.get_node_set())
        hyperedges = b3.get_hyperedge_id_set()
        hyperedgesTuple = [(b3.get_hyperedge_tail(e),
                            b3.get_hyperedge_head(e))
                           for e in hyperedges]
        self.assertEqual(len(hyperedges), 8)
        self.assertIn(({'s'}, {'1'}), hyperedgesTuple)
        self.assertIn(({'s'}, {'2'}), hyperedgesTuple)
        self.assertIn(({'s'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'1'}, {'2'}), hyperedgesTuple)
        self.assertIn(({'2'}, {'3'}), hyperedgesTuple)
        self.assertIn(({'2', '3'}, {'4'}), hyperedgesTuple)
        self.assertIn(({'4'}, {'t'}), hyperedgesTuple)
        self.assertIn(({'4'}, {'1'}), hyperedgesTuple)
Exemple #40
0
def get_hyperpath_from_predecessors(H,
                                    Pv,
                                    source_node,
                                    destination_node,
                                    node_weights=None,
                                    attr_name="weight"):
    """Gives the hyperpath (DirectedHypergraph) representing the shortest
    B-hyperpath from the source to the destination, given a predecessor
    function and source and destination nodes.

    :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 source node of the path.
    :param destination_node: the destination node of the path.
    :returns: DirectedHypergraph -- shortest B-hyperpath from source_node to
            destination_node.
    :raises: TypeError -- Algorithm only applicable to directed hypergraphs
    :raises: KeyError -- Node key in predecessor is not in H
    :raises: KeyError -- Hyperedge key in predecessor is not in H
    :raises: ValueError -- Multiple nodes without predecessor
    :raises: ValueError -- Hypertree does not have source node

    """
    if not isinstance(H, DirectedHypergraph):
        raise TypeError("Algorithm only applicable to directed hypergraphs")

    # Check that Pv is a valid predecessor function:
    # - keys must be nodes in H mapping to hyperedges in H
    # - exactly one node must map to None (i.e., only one node
    #   without predecessor)
    nodes_without_predecessor = 0
    for node, hyperedge_id in Pv.items():
        if not H.has_node(node):
            raise KeyError("Node key %s in predecessor is not in H" % node)

        if hyperedge_id is None:
            nodes_without_predecessor += 1
        elif not H.has_hyperedge_id(hyperedge_id):
            raise KeyError("Hyperedge key %s in predecessor is not in H" %
                           hyperedge_id)

    if nodes_without_predecessor > 1:
        raise ValueError("Multiple nodes without predecessor. %s received" %
                         Pv)
    elif nodes_without_predecessor == 0:
        raise ValueError("Hypertree does not have source node. %s received" %
                         Pv)

    path = DirectedHypergraph()

    # keep track of which nodes are or have been processed
    processedOrInQueue = {n: False for n in Pv}
    nodesToProcess = [destination_node]
    processedOrInQueue[destination_node] = True
    while nodesToProcess:
        node = nodesToProcess.pop(0)
        hyperedge_id = Pv[node]
        if hyperedge_id:
            for n in H.get_hyperedge_tail(hyperedge_id):
                if not processedOrInQueue[n]:
                    nodesToProcess.append(n)
                    processedOrInQueue[n] = True
            path.add_hyperedge(H.get_hyperedge_tail(hyperedge_id),
                               H.get_hyperedge_head(hyperedge_id),
                               weight=H.get_hyperedge_weight(hyperedge_id))
        elif not path.has_node(node):
            path.add_node(node)

    return path
def convert_pnet_to_hypergraph(pnet):
    """ pre-process pnet to number tau-split and tau-join transitions"""
    tau_pre_processing_pnet(pnet)
    """ Convert a Petri net (in pnml format) into a hypergraph (Halp format) """
    hg = DirectedHypergraph()
    transitions = get_transitions(pnet)
    places = get_places(pnet)
    """STEP 1: Pre-process places to find xor places (splits and joints)
    If input/output of a transitions is 2 or more places, then mark those places as "X" and put in hypergraph"""
    for place in places:
        inc_arcs = get_incoming_arcs(place,pnet)
        out_arcs = get_outgoing_arcs(place,pnet)
        isSink = False
        isSource = False
        if len(inc_arcs) > 1:
            #create node for place in hypergraph
            node_id = get_id(place)
            #check if join is end event (sink)
            if (len(out_arcs) == 0):
                isSink = True
            logger.debug("STEP 1 - Creating xor-join node -- {0}".format(node_id))
            hg.add_node(node_id, source = isSource, sink = isSink, type = 'xor-join', name = " ")
            head = []
            head.append(node_id)
            isSink = False
            isSource = False
            #create node for all source of incoming arcs
            for arc in inc_arcs:
                node_id2 = get_id(get_element(get_arc_source(arc), pnet))
                node_name = get_transition_name(get_element(get_arc_source(arc), pnet))
                logger.debug("STEP 1 - Creating transition node -- {0} -- {1}".format(node_id, node_name))
                hg.add_node(node_name, source = isSource, sink = isSink, type = 'transition', name = node_name)
                tail = []
                tail.append(node_name)
                #create hyperedge
                logger.debug("STEP 1 - Creating hyperedge from {0} to {1}".format(str(tail), str(head)))
                hg.add_hyperedge(tail, head, name = " ", phero = 0.5)
        if len(out_arcs) > 1:
            node_id = get_id(place)
            #create node for place in hypergraph (if it does not exist already)
            tail = []
            tail.append(node_id)
            if(not hg.has_node(node_id)):
                #check if source (start event)
                if (len(inc_arcs) == 0):
                    isSource = True
                logger.debug("STEP 1 - Creating xor-split node -- {0}".format(node_id))
                hg.add_node(node_id, source = isSource, sink = isSink, type = 'xor-split', name = " ")
                #create node for all targets of outgoing arcs
                isSink = False
                isSource = False
                for arc in out_arcs:
                    node_id2 = get_id(get_element(get_arc_target(arc), pnet))
                    node_name = get_transition_name(get_element(get_arc_target(arc),pnet))
                    if(not hg.has_node(node_id2)):
                        logger.debug("STEP 1 - Creating transition node -- {0} -- {1}".format(node_id, node_name))
                        hg.add_node(node_name, source = isSource, sink = isSink, type = 'transition', name = node_name)
                    head = []
                    head.append(node_name)
                    #create hyperedge
                    logger.debug("STEP 1 - Creating hyperedge from {0} to {1}".format(str(tail), str(head)))
                    hg.add_hyperedge(tail, head, name = " ", phero = 0.5)
    """ STEP2 : Process each transition """
    for transition in transitions:
        logger.debug("######## Processing transition {0}".format(get_transition_name(transition)))
        isSink = False
        isSource = False
        #check if transition is not a node in hg and add if needed
        #if (not hg.has_node(get_transition_name(transition))):
        #check if transition is start
        inc_arcs = get_incoming_arcs(transition,pnet)
        for inc_arc in inc_arcs:
            source_place = get_element(get_arc_source(inc_arc),pnet)
            place_inc = get_incoming_arcs(source_place,pnet)
            if not place_inc:
                isSource = True
                logger.debug("Transition is START: {0}".format(get_transition_name(transition)))
        #check if trsnasition is end event
        out_arcs = get_outgoing_arcs(transition,pnet)
        for out_arc in out_arcs:
            sink_place = get_element(get_arc_target(out_arc),pnet)
            place_out = get_outgoing_arcs(sink_place,pnet)
            if not place_out:
                isSink = True
                logger.debug("Transition is END: {0}".format(get_transition_name(transition)))
        #create node in hypergraph
        logger.debug("STEP 2 - Creating transition node")
        hg.add_node(get_transition_name(transition), source = isSource, sink = isSink, type = 'transition', name = get_transition_name(transition))
        #look BACKWARD 
        if not isSource:
            inc_arcs = get_incoming_arcs(transition,pnet)
            tail = []
            x_head = [get_transition_name(transition)]
            xplace_list = []
            otherp_list = []
            xplace_tail = []
            for inc_arc in inc_arcs:
                place = get_element(get_arc_source(inc_arc),pnet)
                #separate xor places from other forward places of this transition
                if(hg.has_node(get_id(place))):
                    xplace_list.append(place)
                    xplace_tail.append(get_id(place))
                else:
                    otherp_list.append(place)
                #create forward hyperedge to possibly multiple xor nodes
            he_from_xors_needed = False
            for place in xplace_tail:
                temp_tail = []
                temp_tail.append(place)
                if(not hg.has_hyperedge(temp_tail,x_head)):
                    he_from_xors_needed = True
            if(he_from_xors_needed):    
                logger.debug("STEP 2 - Creating backward hyperedge to (multiple) xor - TAIL {0} -- HEAD {1} ".format(str(xplace_tail),str(x_head)))
                hg.add_hyperedge(xplace_tail, x_head, name = " ", phero = 0.5)
                #create forward normal hyperdge
            tail = []
#             for place in otherp_list:
#                 inc_arcs_l2 = get_incoming_arcs(place)
#                 for inc_arc_l2 in inc_arcs_l2:
#                     trans2 = get_element(get_arc_source(inc_arc_l2))
#                     tail.append(get_transition_name(trans2))
#             if(tail):
#                 logger.info("STEP 2 - Creating real backward  hyperedge - TAIL {0} -- HEAD {1} ".format(str(tail),str(x_head)))
#                 hg.add_hyperedge(tail, x_head, name = " ", phero = 0.0, cost = 0.4, avail = 0.6, qual = 0.2, time = 0.99)
        #look FORWARD
        if not isSink:
            out_arcs = get_outgoing_arcs(transition,pnet)
            head = []
            x_tail = [get_transition_name(transition)]
            xplace_list = []
            otherp_list = []
            xplace_head = []
            for out_arc in out_arcs:
                place = get_element(get_arc_target(out_arc),pnet)
                #separate xor places from other forward places of this transition
                if(hg.has_node(get_id(place))):
                    xplace_list.append(place)
                    xplace_head.append(get_id(place))
                else:
                    otherp_list.append(place)
                #create forward hyperedge to possibly multiple xor nodes
            he_to_xors_needed = False
            for place in xplace_head:
                temp_head = []
                temp_head.append(place)
                if(not hg.has_hyperedge(x_tail,temp_head)):
                    he_to_xors_needed = True
            if(he_to_xors_needed):
                logger.debug("STEP 2 - Creating forward hyperedge to (multiple) xor - TAIL {0} -- HEAD {1} ".format(str(x_tail),str(xplace_head)))
                hg.add_hyperedge(x_tail, xplace_head, name = " ", phero = 0.5)
                #create forward normal hyperdge
            head = []
            for place in otherp_list:
                out_arcs_l2 = get_outgoing_arcs(place,pnet)
                for out_arc_l2 in out_arcs_l2:
                    trans2 = get_element(get_arc_target(out_arc_l2),pnet)
                    head.append(get_transition_name(trans2))
            if(head):
                logger.debug("STEP 2 - Creating real forward  hyperedge - TAIL {0} -- HEAD {1} ".format(str(x_tail),str(head)))
                hg.add_hyperedge(x_tail, head, name = " ", phero = 0.5, cost = 0.4, avail = 0.6, qual = 0.2, time = 0.99)
    """ POST PROCESSING of tau-split/join generated by inductive miner """
    hg = tau_post_processing(hg)
    """ reduction of tau split/join """
    #hg = tau_reduction(hg)
    return hg
Exemple #42
0
def convert_pnet_to_hypergraph(pnet):
    """ pre-process pnet to number tau-split and tau-join transitions"""
    tau_pre_processing_pnet(pnet)
    """ Convert a Petri net (in pnml format) into a hypergraph (Halp format) """
    hg = DirectedHypergraph()
    transitions = get_transitions(pnet)
    places = get_places(pnet)
    """STEP 1: Pre-process places to find xor places (splits and joints)
    If input/output of a transitions is 2 or more places, then mark those places as "X" and put in hypergraph"""
    for place in places:
        inc_arcs = get_incoming_arcs(place, pnet)
        out_arcs = get_outgoing_arcs(place, pnet)
        isSink = False
        isSource = False
        if len(inc_arcs) > 1:
            #create node for place in hypergraph
            node_id = get_id(place)
            #check if join is end event (sink)
            if (len(out_arcs) == 0):
                isSink = True
            logger.debug(
                "STEP 1 - Creating xor-join node -- {0}".format(node_id))
            hg.add_node(node_id,
                        source=isSource,
                        sink=isSink,
                        type='xor-join',
                        name=" ")
            head = []
            head.append(node_id)
            isSink = False
            isSource = False
            #create node for all source of incoming arcs
            for arc in inc_arcs:
                node_id2 = get_id(get_element(get_arc_source(arc), pnet))
                node_name = get_transition_name(
                    get_element(get_arc_source(arc), pnet))
                logger.debug(
                    "STEP 1 - Creating transition node -- {0} -- {1}".format(
                        node_id, node_name))
                hg.add_node(node_name,
                            source=isSource,
                            sink=isSink,
                            type='transition',
                            name=node_name)
                tail = []
                tail.append(node_name)
                #create hyperedge
                logger.debug(
                    "STEP 1 - Creating hyperedge from {0} to {1}".format(
                        str(tail), str(head)))
                hg.add_hyperedge(tail, head, name=" ", phero=0.5)
        if len(out_arcs) > 1:
            node_id = get_id(place)
            #create node for place in hypergraph (if it does not exist already)
            tail = []
            tail.append(node_id)
            if (not hg.has_node(node_id)):
                #check if source (start event)
                if (len(inc_arcs) == 0):
                    isSource = True
                logger.debug(
                    "STEP 1 - Creating xor-split node -- {0}".format(node_id))
                hg.add_node(node_id,
                            source=isSource,
                            sink=isSink,
                            type='xor-split',
                            name=" ")
                #create node for all targets of outgoing arcs
                isSink = False
                isSource = False
                for arc in out_arcs:
                    node_id2 = get_id(get_element(get_arc_target(arc), pnet))
                    node_name = get_transition_name(
                        get_element(get_arc_target(arc), pnet))
                    if (not hg.has_node(node_id2)):
                        logger.debug(
                            "STEP 1 - Creating transition node -- {0} -- {1}".
                            format(node_id, node_name))
                        hg.add_node(node_name,
                                    source=isSource,
                                    sink=isSink,
                                    type='transition',
                                    name=node_name)
                    head = []
                    head.append(node_name)
                    #create hyperedge
                    logger.debug(
                        "STEP 1 - Creating hyperedge from {0} to {1}".format(
                            str(tail), str(head)))
                    hg.add_hyperedge(tail, head, name=" ", phero=0.5)
    """ STEP2 : Process each transition """
    for transition in transitions:
        logger.debug("######## Processing transition {0}".format(
            get_transition_name(transition)))
        isSink = False
        isSource = False
        #check if transition is not a node in hg and add if needed
        #if (not hg.has_node(get_transition_name(transition))):
        #check if transition is start
        inc_arcs = get_incoming_arcs(transition, pnet)
        for inc_arc in inc_arcs:
            source_place = get_element(get_arc_source(inc_arc), pnet)
            place_inc = get_incoming_arcs(source_place, pnet)
            if not place_inc:
                isSource = True
                logger.debug("Transition is START: {0}".format(
                    get_transition_name(transition)))
        #check if trsnasition is end event
        out_arcs = get_outgoing_arcs(transition, pnet)
        for out_arc in out_arcs:
            sink_place = get_element(get_arc_target(out_arc), pnet)
            place_out = get_outgoing_arcs(sink_place, pnet)
            if not place_out:
                isSink = True
                logger.debug("Transition is END: {0}".format(
                    get_transition_name(transition)))
        #create node in hypergraph
        logger.debug("STEP 2 - Creating transition node")
        hg.add_node(get_transition_name(transition),
                    source=isSource,
                    sink=isSink,
                    type='transition',
                    name=get_transition_name(transition))
        #look BACKWARD
        if not isSource:
            inc_arcs = get_incoming_arcs(transition, pnet)
            tail = []
            x_head = [get_transition_name(transition)]
            xplace_list = []
            otherp_list = []
            xplace_tail = []
            for inc_arc in inc_arcs:
                place = get_element(get_arc_source(inc_arc), pnet)
                #separate xor places from other forward places of this transition
                if (hg.has_node(get_id(place))):
                    xplace_list.append(place)
                    xplace_tail.append(get_id(place))
                else:
                    otherp_list.append(place)
                #create forward hyperedge to possibly multiple xor nodes
            he_from_xors_needed = False
            for place in xplace_tail:
                temp_tail = []
                temp_tail.append(place)
                if (not hg.has_hyperedge(temp_tail, x_head)):
                    he_from_xors_needed = True
            if (he_from_xors_needed):
                logger.debug(
                    "STEP 2 - Creating backward hyperedge to (multiple) xor - TAIL {0} -- HEAD {1} "
                    .format(str(xplace_tail), str(x_head)))
                hg.add_hyperedge(xplace_tail, x_head, name=" ", phero=0.5)
                #create forward normal hyperdge
            tail = []


#             for place in otherp_list:
#                 inc_arcs_l2 = get_incoming_arcs(place)
#                 for inc_arc_l2 in inc_arcs_l2:
#                     trans2 = get_element(get_arc_source(inc_arc_l2))
#                     tail.append(get_transition_name(trans2))
#             if(tail):
#                 logger.info("STEP 2 - Creating real backward  hyperedge - TAIL {0} -- HEAD {1} ".format(str(tail),str(x_head)))
#                 hg.add_hyperedge(tail, x_head, name = " ", phero = 0.0, cost = 0.4, avail = 0.6, qual = 0.2, time = 0.99)
#look FORWARD
        if not isSink:
            out_arcs = get_outgoing_arcs(transition, pnet)
            head = []
            x_tail = [get_transition_name(transition)]
            xplace_list = []
            otherp_list = []
            xplace_head = []
            for out_arc in out_arcs:
                place = get_element(get_arc_target(out_arc), pnet)
                #separate xor places from other forward places of this transition
                if (hg.has_node(get_id(place))):
                    xplace_list.append(place)
                    xplace_head.append(get_id(place))
                else:
                    otherp_list.append(place)
                #create forward hyperedge to possibly multiple xor nodes
            he_to_xors_needed = False
            for place in xplace_head:
                temp_head = []
                temp_head.append(place)
                if (not hg.has_hyperedge(x_tail, temp_head)):
                    he_to_xors_needed = True
            if (he_to_xors_needed):
                logger.debug(
                    "STEP 2 - Creating forward hyperedge to (multiple) xor - TAIL {0} -- HEAD {1} "
                    .format(str(x_tail), str(xplace_head)))
                hg.add_hyperedge(x_tail, xplace_head, name=" ", phero=0.5)
                #create forward normal hyperdge
            head = []
            for place in otherp_list:
                out_arcs_l2 = get_outgoing_arcs(place, pnet)
                for out_arc_l2 in out_arcs_l2:
                    trans2 = get_element(get_arc_target(out_arc_l2), pnet)
                    head.append(get_transition_name(trans2))
            if (head):
                logger.debug(
                    "STEP 2 - Creating real forward  hyperedge - TAIL {0} -- HEAD {1} "
                    .format(str(x_tail), str(head)))
                hg.add_hyperedge(x_tail,
                                 head,
                                 name=" ",
                                 phero=0.5,
                                 cost=0.4,
                                 avail=0.6,
                                 qual=0.2,
                                 time=0.99)
    """ POST PROCESSING of tau-split/join generated by inductive miner """
    hg = tau_post_processing(hg)
    """ reduction of tau split/join """
    #hg = tau_reduction(hg)
    return hg
class TestComputeLowerBound(unittest.TestCase):

    def setUp(self):
        self.nielsenGraph = DirectedHypergraph()
        self.nielsenGraph.add_node('s')
        self.nielsenGraph.add_node('1')
        self.nielsenGraph.add_node('2')
        self.nielsenGraph.add_node('3')
        self.nielsenGraph.add_node('4')
        self.nielsenGraph.add_node('t')
        self.nielsenGraph.add_hyperedge({'s'}, {'1'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1', '2'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2', '3'}, {'4'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'1'}, weight=1)

    def test_returns_12_for_lower_bound_for_nielsen_H_21(self):
        '''
            Test graph is discussed in Section 3.2 example 2 of
            Nielsen et al.\
        '''
        H_2 = self.nielsenGraph.copy()
        e1 = H_2.get_hyperedge_id({'s'}, {'1'})
        e2 = H_2.get_hyperedge_id({'1'}, {'2'})
        e3 = H_2.get_hyperedge_id({'1', '2'}, {'t'})
        H_2.remove_hyperedge(H_2.get_hyperedge_id({'s'}, {'2'}))
        H_2.remove_hyperedge(H_2.get_hyperedge_id({'4'}, {'t'}))

        # weight vector
        W = {'s': 0, '1': 1, '2': 2, '3': 1, '4': 4, 't': 4}
        # predecessor function
        pred = {'s': None, '1': e1, '2': e2, 't': e3}
        # ordering
        ordering = ['s', '1', '2', 't']

        # branch of H_2 for the test
        H_2_1 = H_2.copy()
        H_2_1.remove_hyperedge(
            H_2_1.get_hyperedge_id({'s'}, {'1'}))

        self.assertEqual(ksh._compute_lower_bound(
            H_2_1, 0, pred, ordering, W, 't'), 12)
class TestKShortestHyperpaths(unittest.TestCase):
    def setUp(self):
        self.nielsenGraph = DirectedHypergraph()
        self.nielsenGraph.add_node('s')
        self.nielsenGraph.add_node('1')
        self.nielsenGraph.add_node('2')
        self.nielsenGraph.add_node('3')
        self.nielsenGraph.add_node('4')
        self.nielsenGraph.add_node('t')
        self.nielsenGraph.add_hyperedge({'s'}, {'1'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1', '2'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2', '3'}, {'4'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'1'}, weight=1)

    # valid input tests
    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_hypegraph(self):
        H = "DirectedHypergraph"
        source, destination = 1, 2
        self.assertRaises(TypeError, ksh.k_shortest_hyperpaths, H, source,
                          destination, 1)

    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_destination_not_in_graph(self):
        H = DirectedHypergraph()
        source, destination = 1, 2
        H.add_nodes([source, destination])
        self.assertRaises(ValueError, ksh.k_shortest_hyperpaths, H, source, 3,
                          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_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)

    # various cases
    def test_returns_only_one_hyperpath_for_k_equals_one(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('3')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'s'}, {'2'}, weight=1)
        H.add_hyperedge({'s'}, {'3'}, weight=1)
        H.add_hyperedge({'1'}, {'t'}, weight=1)
        H.add_hyperedge({'2', '3'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        self.assertEqual(len(output), 1)

    def test_returns_shortest_hyperpath_for_k_equals_one(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('3')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'s'}, {'2'}, weight=1)
        H.add_hyperedge({'s'}, {'3'}, weight=1)
        H.add_hyperedge({'1'}, {'t'}, weight=1)
        H.add_hyperedge({'2', '3'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        hyperpath = output[0]
        self.assertEqual(hyperpath.get_node_set(), {'s', '1', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 2)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'1'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1'}, {'t'}))

    def test_returns_empty_list_if_no_s_t_path(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'1', '2'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        self.assertEqual(output, [])

    def test_returns_3_shortest_hypergraphs_for_nielsen_example_with_k_equal_3(
            self):
        threeShortest = ksh.k_shortest_hyperpaths(self.nielsenGraph, 's', 't',
                                                  3)
        self.assertEqual(len(threeShortest), 3)
        # shortest path
        hyperpath = threeShortest[0]
        self.assertEqual(hyperpath.get_node_set(), {'s', '1', '2', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 3)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'1'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'2'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1', '2'}, {'t'}))
        # second shortest path
        hyperpath = threeShortest[1]
        self.assertEqual(hyperpath.get_node_set(), {'s', '1', '2', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 3)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'1'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1'}, {'2'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1', '2'}, {'t'}))
        # third shortest path
        hyperpath = threeShortest[2]
        self.assertEqual(hyperpath.get_node_set(), {'s', '2', '3', '4', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 4)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'2'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'3'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'2', '3'}, {'4'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'4'}, {'t'}))
class TestKShortestHyperpaths(unittest.TestCase):

    def setUp(self):
        self.nielsenGraph = DirectedHypergraph()
        self.nielsenGraph.add_node('s')
        self.nielsenGraph.add_node('1')
        self.nielsenGraph.add_node('2')
        self.nielsenGraph.add_node('3')
        self.nielsenGraph.add_node('4')
        self.nielsenGraph.add_node('t')
        self.nielsenGraph.add_hyperedge({'s'}, {'1'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'s'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1'}, {'2'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2'}, {'3'}, weight=1)
        self.nielsenGraph.add_hyperedge({'1', '2'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'t'}, weight=1)
        self.nielsenGraph.add_hyperedge({'2', '3'}, {'4'}, weight=1)
        self.nielsenGraph.add_hyperedge({'4'}, {'1'}, weight=1)

    # valid input tests
    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_hypegraph(self):
        H = "DirectedHypergraph"
        source, destination = 1, 2
        self.assertRaises(TypeError,
                          ksh.k_shortest_hyperpaths, H, source, destination, 1)

    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_destination_not_in_graph(self):
        H = DirectedHypergraph()
        source, destination = 1, 2
        H.add_nodes([source, destination])
        self.assertRaises(ValueError,
                          ksh.k_shortest_hyperpaths, H, source, 3, 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_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)

    # various cases
    def test_returns_only_one_hyperpath_for_k_equals_one(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('3')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'s'}, {'2'}, weight=1)
        H.add_hyperedge({'s'}, {'3'}, weight=1)
        H.add_hyperedge({'1'}, {'t'}, weight=1)
        H.add_hyperedge({'2', '3'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        self.assertEqual(len(output), 1)

    def test_returns_shortest_hyperpath_for_k_equals_one(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('3')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'s'}, {'2'}, weight=1)
        H.add_hyperedge({'s'}, {'3'}, weight=1)
        H.add_hyperedge({'1'}, {'t'}, weight=1)
        H.add_hyperedge({'2', '3'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        hyperpath = output[0]
        self.assertEqual(hyperpath.get_node_set(), {'s', '1', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 2)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'1'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1'}, {'t'}))

    def test_returns_empty_list_if_no_s_t_path(self):
        H = DirectedHypergraph()
        H.add_node('s')
        H.add_node('1')
        H.add_node('2')
        H.add_node('t')
        H.add_hyperedge({'s'}, {'1'}, weight=1)
        H.add_hyperedge({'1', '2'}, {'t'}, weight=1)

        output = ksh.k_shortest_hyperpaths(H, 's', 't', 1)
        self.assertEqual(output, [])

    def test_returns_3_shortest_hypergraphs_for_nielsen_example_with_k_equal_3(
            self):
        threeShortest = ksh.k_shortest_hyperpaths(
            self.nielsenGraph, 's', 't', 3)
        self.assertEquals(len(threeShortest), 3)
        # shortest path
        hyperpath = threeShortest[0]
        self.assertEqual(hyperpath.get_node_set(), {'s', '1', '2', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 3)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'1'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'2'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1', '2'}, {'t'}))
        # second shortest path
        hyperpath = threeShortest[1]
        self.assertEqual(hyperpath.get_node_set(), {'s', '1', '2', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 3)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'1'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1'}, {'2'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'1', '2'}, {'t'}))
        # third shortest path
        hyperpath = threeShortest[2]
        self.assertEqual(hyperpath.get_node_set(), {'s', '2', '3', '4', 't'})
        self.assertEqual(len(hyperpath.get_hyperedge_id_set()), 4)
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'2'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'s'}, {'3'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'2', '3'}, {'4'}))
        self.assertTrue(hyperpath.get_hyperedge_id({'4'}, {'t'}))
Exemple #46
0
def make_hypergraph(file_prefix,
                    delim=';',
                    sep='\t',
                    keep_singleton_nodes=False):
    '''
    Creates the directed hypergraph object from the hypernodes and hyperedges files.
    Returns the hypergraph object.
    '''
    #NOTE: This is directly copied from https://github.com/annaritz/pathway-connectivity
    hypernodes = {}
    with open(file_prefix + '-hypernodes.txt') as fin:
        for line in fin:
            if line[0] == '#':
                continue
            row = line.strip().split(sep)
            if len(row) == 1:
                hypernodes[row[0]] = ['OtherComplexes-FIX']
            else:
                hypernodes[row[0]] = row[1].split(delim)
    print('%d hypernodes from hypernodes file' % (len(hypernodes)))
    identifier2id = {}
    id2identifier = {}
    H = DirectedHypergraph()
    if keep_singleton_nodes:
        for n in hypernodes:
            H.add_node(n)

    skipped1 = 0
    skipped2 = 0
    tailsizes = []
    headsizes = []
    selfloops = []
    noinselfloops = 0
    indegree = []
    outdegree = []
    numtargets = 0
    with open(file_prefix + '-hyperedges.txt') as fin:
        for line in fin:
            if line[0] == '#':
                continue
            row = line.strip().split(sep)
            tail = set()
            head = set()

            ## Tail includes tail and regulators.
            ## Head includes head.
            if row[0] != 'None':
                tail.update(row[0].split(delim))
            if row[1] != 'None':
                head.update(row[1].split(delim))
            if row[2] != 'None':
                tail.update(row[2].split(delim))
            #NOTE: This line was commented out to exclude negative regulators in the tail
            #if row[3] != 'None':
            #tail.update(row[3].split(delim))
            hedge_id = row[4]

            ## THIS IS A HACK FOR NOW ( should be incorporated in the make-hypergraph.py code)
            ## IGnore any reactions that have a Reactome Identifier (e.g. has "HSA") instead of
            ## a PAthway Commons identifier.
            if any(['HSA' in s for s in tail] + ['HSA' in s for s in head]):
                skipped1 += 1
            elif len(tail) == 0 or len(head) == 0:
                skipped2 += 1
            else:
                hid = H.add_hyperedge(tail, head, identifier=hedge_id)
                tailsizes.append(len(tail))
                headsizes.append(len(head))
                intersection = tail.intersection(head)
                if len(intersection) > 0:
                    selfloops.append([v for v in intersection])

                identifier2id[hedge_id] = hid
                id2identifier[hid] = hedge_id

    print('%d reactions skipped because of Reactome identifier' % (skipped1))
    print('%d reactions skipped because of an empty tail or head' % (skipped2))
    ## annotate nodes
    num_hypernodes = 0
    for node in H.get_node_set():
        if node in hypernodes and hypernodes[node] != [node]:
            H.add_node(node,
                       hypernode_members=hypernodes[node],
                       is_hypernode=True)
            num_hypernodes += 1
        else:
            H.add_node(node, is_hypernode=False, hypernode_members=[])

        H.add_node(node)

    return H, identifier2id, id2identifier
Exemple #47
0
def initialize(H, source, target, node_dict={}):
    '''
    Finds the set of reachable and backwards-recoverable edges, sets up the tail reached counters, the inedge lists,  and the heap pointer for each edge.
    Initializes the taillength for each edge, and the heap, and the reachable edge counter
    '''
    edgedict = {}

    #find reachable and backwards-recoverable edge list
    reachableedges = findreachableandbackrecoverable(H, source, target)

    #trim H
    H2 = DirectedHypergraph()
    if len(node_dict) == 0:
        for v in H.node_iterator():
            H2.add_node(v, H.get_node_attributes(v))
    for edge in reachableedges:
        H2.add_hyperedge(H.get_hyperedge_tail(edge),
                         H.get_hyperedge_head(edge),
                         weight=H.get_hyperedge_weight(edge))
    H2.add_node('SUPERSOURCE', {'label': 'SUPERSOURCE'})
    for edge in H2.get_forward_star('SUPERSOURCE'):
        forwardstarlist = []
        for v in H2.get_hyperedge_head(edge):
            if len(H2.get_forward_star(v)) > 0:
                forwardstarlist.append(v)
        H2.remove_hyperedge(edge)
        if len(forwardstarlist) > 0:
            H2.add_hyperedge(['SUPERSOURCE'], forwardstarlist, weight=0)
        else:
            H2.add_hyperedge(['SUPERSOURCE'], [], weight=0)

    H = H2
    for v in H.get_node_set():
        #need to remap the edges because just calling remove_node(v) removes also all the hyperedges v is in
        if len(H.get_forward_star(v)) == 0 and v != 'SUPERTARGET':
            #find edges that need to be replaced
            backedges = H.get_backward_star(v)
            for e in backedges:
                tail = H.get_hyperedge_tail(e)
                head = H.get_hyperedge_head(e)
                head.remove(v)
                w = H.get_hyperedge_weight(e)
                H.remove_hyperedge(e)
                H.add_hyperedge(tail, head, weight=w)
            H.remove_node(v)
    reachableedges = []
    H2.add_node('SUPERSOURCE', {'label': 'SUPERSOURCE'})
    for edge in H.hyperedge_id_iterator():
        reachableedges.append(edge)

    #initialize edgedict
    for e in H.hyperedge_id_iterator():
        edgedict[e] = {
            'isremoved': False,
            'bestinedges': [],
            'candidateinedges': [],
            'tailcount': len(H.get_hyperedge_tail(e))
        }

    #initialize taildistancelist
    taildistancelist = {}
    for e in reachableedges:
        taildistancelist[e] = 'inf'

    #initialize reachableedgecounter
    reachableedgecounter = len(reachableedges)

    #initialize heap
    heap = []
    entry_finder = {
    }  # mapping of tasks to entries, this and the line below are strictly for the heap
    counter = itertools.count()  # unique sequence count
    for e in H.get_forward_star(source):
        if e in reachableedges:
            add_node(heap, e, weight(H, [e]), counter, entry_finder)

    #initialize reachedtable
    reachedtable = {}
    for e in H.hyperedge_id_iterator():
        reachedtable[e] = []

    return reachableedges, edgedict, taildistancelist, heap, reachableedgecounter, reachedtable, entry_finder, counter, H
Exemple #48
0
def get_hyperpath_from_predecessors(H, Pv, source_node, destination_node,
                                    node_weights=None, attr_name="weight"):
    """Gives the hyperpath (DirectedHypergraph) representing the shortest
    B-hyperpath from the source to the destination, given a predecessor
    function and source and destination nodes.

    :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 source node of the path.
    :param destination_node: the destination node of the path.
    :returns: DirectedHypergraph -- shortest B-hyperpath from source_node to
            destination_node.
    :raises: TypeError -- Algorithm only applicable to directed hypergraphs
    :raises: KeyError -- Node key in predecessor is not in H
    :raises: KeyError -- Hyperedge key in predecessor is not in H
    :raises: ValueError -- Multiple nodes without predecessor
    :raises: ValueError -- Hypertree does not have source node

    """
    if not isinstance(H, DirectedHypergraph):
        raise TypeError("Algorithm only applicable to directed hypergraphs")

    # Check that Pv is a valid predecessor function:
    # - keys must be nodes in H mapping to hyperedges in H
    # - exactly one node must map to None (i.e., only one node
    #   without predecessor)
    nodes_without_predecessor = 0
    for node, hyperedge_id in Pv.items():
        if not H.has_node(node):
            raise KeyError(
                "Node key %s in predecessor is not in H" % node)

        if hyperedge_id is None:
            nodes_without_predecessor += 1
        elif not H.has_hyperedge_id(hyperedge_id):
            raise KeyError(
                "Hyperedge key %s in predecessor is not in H" % hyperedge_id)

    if nodes_without_predecessor > 1:
        raise ValueError(
            "Multiple nodes without predecessor. %s received" % Pv)
    elif nodes_without_predecessor == 0:
        raise ValueError(
            "Hypertree does not have source node. %s received" % Pv)

    path = DirectedHypergraph()

    # keep track of which nodes are or have been processed
    processedOrInQueue = {n: False for n in Pv}
    nodesToProcess = [destination_node]
    processedOrInQueue[destination_node] = True
    while nodesToProcess:
        node = nodesToProcess.pop(0)
        hyperedge_id = Pv[node]
        if hyperedge_id:
            for n in H.get_hyperedge_tail(hyperedge_id):
                if not processedOrInQueue[n]:
                    nodesToProcess.append(n)
                    processedOrInQueue[n] = True
            path.add_hyperedge(H.get_hyperedge_tail(hyperedge_id),
                               H.get_hyperedge_head(hyperedge_id),
                               weight=H.get_hyperedge_weight(
                               hyperedge_id))
        elif not path.has_node(node):
            path.add_node(node)

    return path