Exemplo n.º 1
0
def test_get_hypertree_from_predecessors():
    H = DirectedHypergraph()
    H.read("tests/data/basic_directed_hypergraph.txt")

    # Test with a weighting
    Pv, W, valid_ordering = \
        directed_paths.shortest_b_tree(
            H, 's', directed_paths.sum_function, True)

    sub_H = directed_paths.get_hypertree_from_predecessors(H, Pv, 's', W)

    sub_H._check_consistency()

    assert sub_H.get_node_set() == set(['s', 'x', 'y', 'z', 't', 'u'])

    assert sub_H.get_node_attribute('s', 'weight') == 0
    assert sub_H.get_node_attribute('x', 'weight') == 1
    assert sub_H.get_node_attribute('y', 'weight') == 2
    assert sub_H.get_node_attribute('z', 'weight') == 2
    assert sub_H.get_node_attribute('u', 'weight') == 8
    assert sub_H.get_node_attribute('t', 'weight') == 8

    assert Pv['s'] == None
    assert Pv['x'] == "e1"
    assert Pv['y'] == "e2"
    assert Pv['z'] == "e3"
    assert (Pv['u'], Pv['t']) == ("e4", "e4")
    assert (Pv['a'], Pv['b']) == (None, None)

    assert len(sub_H.get_hyperedge_id_set()) == 4
    assert sub_H.has_hyperedge(['s'], ['x'])
    assert sub_H.has_hyperedge(['s'], ['x', 'y'])
    assert sub_H.has_hyperedge(['s'], ['z'])
    assert sub_H.has_hyperedge(['x', 'y', 'z'], ['u', 't'])

    # Test without a weighting
    Pv, W = directed_paths.shortest_f_tree(H, 't', directed_paths.sum_function)

    sub_H = directed_paths.get_hypertree_from_predecessors(H, Pv, 't')

    sub_H._check_consistency()

    assert sub_H.get_node_set() == set(['t', 's', 'x'])

    assert len(sub_H.get_hyperedge_id_set()) == 2
    assert sub_H.has_hyperedge(['x'], ['s'])
    assert sub_H.has_hyperedge(['s'], ['t'])

	# Try an invalid hypergraph
    try:
        directed_paths.shortest_b_tree('s', 't')
        assert False
    except TypeError:
        pass
    except BaseException as e:
        assert False, e
Exemplo n.º 2
0
def test_get_hypertree_from_predecessors():
    H = DirectedHypergraph()
    H.read("tests/data/basic_directed_hypergraph.txt")

    # Test with a weighting
    Pv, W, valid_ordering = \
        directed_paths.shortest_b_tree(
            H, 's', directed_paths.sum_function, True)

    sub_H = directed_paths.get_hypertree_from_predecessors(H, Pv, 's', W)

    sub_H._check_consistency()

    assert sub_H.get_node_set() == set(['s', 'x', 'y', 'z', 't', 'u'])

    assert sub_H.get_node_attribute('s', 'weight') == 0
    assert sub_H.get_node_attribute('x', 'weight') == 1
    assert sub_H.get_node_attribute('y', 'weight') == 2
    assert sub_H.get_node_attribute('z', 'weight') == 2
    assert sub_H.get_node_attribute('u', 'weight') == 8
    assert sub_H.get_node_attribute('t', 'weight') == 8

    assert Pv['s'] == None
    assert Pv['x'] == "e1"
    assert Pv['y'] == "e2"
    assert Pv['z'] == "e3"
    assert (Pv['u'], Pv['t']) == ("e4", "e4")
    assert (Pv['a'], Pv['b']) == (None, None)

    assert len(sub_H.get_hyperedge_id_set()) == 4
    assert sub_H.has_hyperedge(['s'], ['x'])
    assert sub_H.has_hyperedge(['s'], ['x', 'y'])
    assert sub_H.has_hyperedge(['s'], ['z'])
    assert sub_H.has_hyperedge(['x', 'y', 'z'], ['u', 't'])

    # Test without a weighting
    Pv, W = directed_paths.shortest_f_tree(H, 't', directed_paths.sum_function)

    sub_H = directed_paths.get_hypertree_from_predecessors(H, Pv, 't')

    sub_H._check_consistency()

    assert sub_H.get_node_set() == set(['t', 's', 'x'])

    assert len(sub_H.get_hyperedge_id_set()) == 2
    assert sub_H.has_hyperedge(['x'], ['s'])
    assert sub_H.has_hyperedge(['s'], ['t'])

    # Try an invalid hypergraph
    try:
        directed_paths.shortest_b_tree('s', 't')
        assert False
    except TypeError:
        pass
    except BaseException as e:
        assert False, e
Exemplo n.º 3
0
def test_shortest_sum_b_tree():
    H = DirectedHypergraph()
    H.read("tests/data/basic_directed_hypergraph.txt")

    Pv, W, valid_ordering = \
        directed_paths.shortest_b_tree(
            H, 's', directed_paths.sum_function, True)

    assert valid_ordering.count('s') == 1
    assert valid_ordering.index('s') < valid_ordering.index('x')
    assert valid_ordering.index('s') < valid_ordering.index('y')
    assert valid_ordering.index('s') < valid_ordering.index('z')
    assert valid_ordering.index('s') < valid_ordering.index('t')
    assert valid_ordering.index('s') < valid_ordering.index('u')
    assert valid_ordering.count('x') == 1
    assert valid_ordering.index('x') < valid_ordering.index('t')
    assert valid_ordering.index('x') < valid_ordering.index('u')
    assert valid_ordering.count('y') == 1
    assert valid_ordering.index('y') < valid_ordering.index('t')
    assert valid_ordering.index('y') < valid_ordering.index('u')
    assert valid_ordering.count('z') == 1
    assert valid_ordering.index('z') < valid_ordering.index('t')
    assert valid_ordering.index('z') < valid_ordering.index('u')
    assert valid_ordering.count('t') == 1
    assert valid_ordering.count('u') == 1
    assert valid_ordering.count('a') == 0
    assert valid_ordering.count('b') == 0

    assert Pv['s'] is None
    assert Pv['x'] == 'e1'
    assert Pv['y'] == 'e2'
    assert Pv['z'] == 'e3'
    assert Pv['t'] == 'e4'
    assert Pv['u'] == 'e4'
    assert (Pv['a'], Pv['b']) == (None, None)

    assert W['s'] == 0
    assert W['x'] == 1
    assert W['y'] == 2
    assert W['z'] == 2
    assert W['u'] == 8
    assert W['t'] == 8
    assert W['a'] == float('inf')
    assert W['b'] == float('inf')

    # Try an invalid hypergraph
    try:
        directed_paths.shortest_b_tree('s', 't')
        assert False
    except TypeError:
        pass
    except BaseException as e:
        assert False, e
Exemplo n.º 4
0
def test_shortest_sum_b_tree():
    H = DirectedHypergraph()
    H.read("tests/data/basic_directed_hypergraph.txt")

    Pv, W, valid_ordering = \
        directed_paths.shortest_b_tree(
            H, 's', directed_paths.sum_function, True)

    assert valid_ordering.count('s') == 1
    assert valid_ordering.index('s') < valid_ordering.index('x')
    assert valid_ordering.index('s') < valid_ordering.index('y')
    assert valid_ordering.index('s') < valid_ordering.index('z')
    assert valid_ordering.index('s') < valid_ordering.index('t')
    assert valid_ordering.index('s') < valid_ordering.index('u')
    assert valid_ordering.count('x') == 1
    assert valid_ordering.index('x') < valid_ordering.index('t')
    assert valid_ordering.index('x') < valid_ordering.index('u')
    assert valid_ordering.count('y') == 1
    assert valid_ordering.index('y') < valid_ordering.index('t')
    assert valid_ordering.index('y') < valid_ordering.index('u')
    assert valid_ordering.count('z') == 1
    assert valid_ordering.index('z') < valid_ordering.index('t')
    assert valid_ordering.index('z') < valid_ordering.index('u')
    assert valid_ordering.count('t') == 1
    assert valid_ordering.count('u') == 1
    assert valid_ordering.count('a') == 0
    assert valid_ordering.count('b') == 0

    assert Pv['s'] is None
    assert Pv['x'] == 'e1'
    assert Pv['y'] == 'e2'
    assert Pv['z'] == 'e3'
    assert Pv['t'] == 'e4'
    assert Pv['u'] == 'e4'
    assert (Pv['a'], Pv['b']) == (None, None)

    assert W['s'] == 0
    assert W['x'] == 1
    assert W['y'] == 2
    assert W['z'] == 2
    assert W['u'] == 8
    assert W['t'] == 8
    assert W['a'] == float('inf')
    assert W['b'] == float('inf')

    # Try an invalid hypergraph
    try:
        directed_paths.shortest_b_tree('s', 't')
        assert False
    except TypeError:
        pass
    except BaseException as e:
        assert False, e
Exemplo n.º 5
0
def test_shortest_gap_b_tree():
    H = DirectedHypergraph()
    H.read("tests/data/basic_directed_hypergraph.txt")

    Pv, W = \
        directed_paths.shortest_b_tree(H, 's', directed_paths.gap_function)

    assert Pv['s'] is None
    assert Pv['x'] == 'e1'
    assert Pv['y'] == 'e2'
    assert Pv['z'] == 'e3'
    assert Pv['t'] == 'e4'
    assert Pv['u'] == 'e4'
    assert (Pv['a'], Pv['b']) == (None, None)

    assert W['s'] == 0
    assert W['x'] == 1
    assert W['y'] == 2
    assert W['z'] == 2
    assert W['u'] == 4
    assert W['t'] == 4
    assert W['a'] == float('inf')
    assert W['b'] == float('inf')
Exemplo n.º 6
0
def test_shortest_gap_b_tree():
    H = DirectedHypergraph()
    H.read("tests/data/basic_directed_hypergraph.txt")

    Pv, W = \
        directed_paths.shortest_b_tree(H, 's', directed_paths.gap_function)

    assert Pv['s'] is None
    assert Pv['x'] == 'e1'
    assert Pv['y'] == 'e2'
    assert Pv['z'] == 'e3'
    assert Pv['t'] == 'e4'
    assert Pv['u'] == 'e4'
    assert (Pv['a'], Pv['b']) == (None, None)

    assert W['s'] == 0
    assert W['x'] == 1
    assert W['y'] == 2
    assert W['z'] == 2
    assert W['u'] == 4
    assert W['t'] == 4
    assert W['a'] == float('inf')
    assert W['b'] == float('inf')
Exemplo n.º 7
0
def k_shortest_hyperpaths(H, source_node, destination_node, k, F=sum_function):
    """Computes the k shortest hyperpaths from a source node to every other
    node in the hypergraph.
    This algorithm is only applicable to directed B-hypergraphs.
    The algorithm is described in the paper:
    Lars Relund Nielsen, Kim Allan Andersen, Daniele Pretolani,
    Finding the K shortest hyperpaths, Computers & Operations Research,
    Volume 32, Issue 6, June 2005, Pages 1477-1497, ISSN 0305-0548,
    http://dx.doi.org/10.1016/j.cor.2003.11.014.
    (http://www.sciencedirect.com/science/article/pii/S0305054803003459)

    :param H: the hypergraph for which the function will compute the shortest
              hyperpaths.
    :param source_node: the source node in H for the path computation.
    :param destination_node: the destination node in H for the path
                        computation.
    :param k: a positive integer indicating how many paths to compute.
    :param F: [optional] function used for the shortest path computation.
              See algorithms.directed_paths module for expected format of
              function.
    :returns: a list containing at most k hyperpaths (DirectedHypergraph) from
              source to destination in ascending order of path length.
    :raises: TypeError -- Input hypergraph must be a B-hypergraph
    :raises: TypeError -- Algorithm only applicable to directed hypergraphs
    :raises: ValueError -- source_node must be a node in H
    :raises: ValueError -- destination_node must be a node in H
    :raises: TypeError -- k must be an integer
    :raises: ValueError -- k must be a positive integer

    """
    try:
        if not H.is_B_hypergraph():
            raise TypeError("Input graph must be a B-hypergraph")
    except AttributeError:
        raise TypeError("Algorithm only applicable to directed hypergraphs")

    if not H.has_node(source_node):
        raise ValueError("source_node must be a node in H. \
                         %s received" % source_node)

    if not H.has_node(destination_node):
        raise ValueError("destination_node must be a node in H. \
                         %s received" % destination_node)

    if type(k) != int:
        raise TypeError("k must be an integer. %s received" % k)

    if k <= 0:
        raise ValueError("k must be a positive integer. %s received" % k)

    # Container for the k-shortest hyperpaths
    paths = []

    # Container for the candidate paths. Every item is a 4-tuple:
    # 1) subgraph H'
    # 2) lower bound on shortest hyperpath weight
    # 3) predecessor function of shortest hypertree rootes at s on H'
    # 4) valid ordering of the nodes in H'
    candidates = []

    shortest_hypertree, W, ordering = \
        shortest_b_tree(H, source_node, F=F, valid_ordering=True)
    # Check if there is source-destination hyperpath
    # if there isn't the for loop below
    # will break immediately and the function returns an empty list
    if W[destination_node] != float('inf'):
        candidates.append((H, W, shortest_hypertree, ordering))

    i = 1
    while i <= k and candidates:
        ind = candidates.index(
            min(candidates, key=lambda x: x[1][destination_node]))
        kShortest = candidates[ind]
        if kShortest[2]:
            candidates.pop(ind)
            path = \
                get_hyperpath_from_predecessors(kShortest[0], kShortest[2],
                                                source_node, destination_node)
            pathPredecessor = \
                {node: edge for node, edge in kShortest[2].items()
                 if node in path.get_node_set()}
            pathOrdering = \
                [node for node in kShortest[3] if node in pathPredecessor]
            paths.append(path)

            # check if we are done
            if len(paths) == k:
                break

            branches = _branching_step(kShortest[0], pathPredecessor,
                                       pathOrdering)
            for j, branch in enumerate(branches):
                lb = _compute_lower_bound(branch, j, kShortest[2],
                                          pathOrdering, kShortest[1],
                                          destination_node, F)
                if lb < float('inf'):
                    candidates.append((branch,
                                      {destination_node: lb},
                                      None, None))
            i += 1
        else:
            # Compute shortest hypertree for kShortest[0] and exact bound
            # reinsert into candidates
            H_sub = kShortest[0]
            tree_sub, W_sub, ordering_sub = \
                shortest_b_tree(H_sub, source_node, valid_ordering=True)
            candidates[ind] = (H_sub, W_sub, tree_sub, ordering_sub)

    return paths