Ejemplo n.º 1
0
def test_priority_queue():
    """
    Ensure the priority set is sorting elements correctly.
    """
    random_elements = [i for i in range(10)]
    shuffle(random_elements)

    pq = PriorityQueue()
    for e in random_elements:
        pq.push(e)

    random_elements.sort()

    assert [e for e in pq] == random_elements
    assert pq.peek() == random_elements[0]

    output = []
    while len(pq) > 0:
        output.append(pq.pop())
    assert output == random_elements

    for e in random_elements:
        pq.push(e)
    assert len(pq) == 10

    pq.update_cost_limit(5)
    assert len(pq) == 6

    output = []
    while len(pq) > 0:
        output.append(pq.pop())
    assert output == random_elements[:6]

    pq = PriorityQueue(node_value=lambda x: x, max_length=3)
    pq.push(6)
    pq.push(0)
    pq.push(2)
    pq.push(6)
    pq.push(7)

    assert len(pq) == 3
    assert list(pq) == [0, 2, 6]

    pq.update_cost_limit(5)

    assert len(pq) == 2
    assert pq.peek() == 0
    assert pq.peek_value() == 0
    assert pq.pop() == 0
    assert pq.peek() == 2
    assert pq.peek_value() == 2
    assert pq.pop() == 2
    assert len(pq) == 0
Ejemplo n.º 2
0
def local_beam_search(problem, beam_width=1, max_sideways=0,
                      graph_search=True, cost_limit=float('-inf')):
    """
    A variant of :func:`py_search.informed_search.beam_search` that can be
    applied to local search problems.  When the beam width of 1 this approach
    yields behavior similar to :func:`hill_climbing`.

    :param problem: The problem to solve.
    :type problem: :class:`py_search.base.Problem`
    :param beam_width: The size of the search beam.
    :type beam_width: int
    :param max_sideways: Specifies the max number of contiguous sideways moves. 
    :type max_sideways: int
    :param graph_search: Whether to use graph search (no duplicates) or tree
        search (duplicates)
    :type graph_search: Boolean
    """
    b = None
    bv = float('inf')
    sideways_moves = 0

    fringe = PriorityQueue(node_value=problem.node_value)
    fringe.push(problem.initial)

    while len(fringe) < beam_width:
        fringe.push(problem.random_node())
    
    if graph_search:
        closed = set()
        closed.add(problem.initial)

    while len(fringe) > 0 and sideways_moves <= max_sideways:
        pv = fringe.peek_value()

        if pv > bv:
            yield b

        if pv == bv:
            sideways_moves += 1
        else:
            sideways_moves = 0

        parents = []
        while len(fringe) > 0 and len(parents) < beam_width:
            parent = fringe.pop()
            parents.append(parent)
        fringe.clear()

        b = parents[0]
        bv = pv

        for node in parents:
            for s in problem.successors(node):
                added = True
                if not graph_search:
                    fringe.push(s)
                elif s not in closed:
                    fringe.push(s)
                    closed.add(s)
                else:
                    added = False

                if added and fringe.peek_value() <= cost_limit:
                    yield fringe.peek()


    yield b