Commit ad4cea4a authored by Vít Starý Novotný's avatar Vít Starý Novotný
Browse files

added example 5.3_15.py

parent 6f10c2ef
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ def best_search(start):
            yield (f, path1)
        if f <= biggest:
            for m, c in move_anyYC(node):
                if not member(m, path):
                if not member(m, path1):
                    heapq.heappush(heap, (g+c+h(m), g+c, m, path1))

def member(x, xs):
@@ -46,7 +46,7 @@ def h(x):

# demonstracni vypis
if __name__ == "__main__":
    print("Best-First Search (algoritmus A*)")
    print("Best-First Search (algoritmus A*) - implementace pomoci prioritni fronty")
    print("Veskere jednoduche cesty mezi mesty Arad a Bukurest serazene vzestupne podle ceny:")
    for solution in best_search('Arad'):
        print(solution)
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ graph = dict(
goals = dict(d=True, g=True, h=True)

def is_goal(node):
    # zavisi na resenem problemu
    return node in goals

def solve(node):
+121 −0
Original line number Diff line number Diff line
#!/usr/bin/env python
# encoding=utf-8 (pep 0263)

import heapq
from linked_lists import LinkedList, Cons, Nil

# horni zavora pro cenu nejlepsi cesty
biggest = 9999

# Algoritmus funguje analogicky k algoritmu ze souboru
# 4.1_9-priority-queue.py, ale namisto jednotlivych uzlu udrzujeme ve
# fronte skupiny uzlu, ze kterych je nutne se dostat do koncovych uzlu
# pro splneni vsech jiz navstivenych AND uzlu. Na zaver jsou cesty
# jednotlivych uzlu zrekonstruovany do stromu.
def andor(start):
    heap = [(0, 0, LinkedList([(0, 0, 0, start, Nil)]), Nil)]
    while True:
        try:
            f, g, nodes, solved = heapq.heappop(heap)
        except IndexError: # fronta je prazdna
            raise ValueError("Reseni neexistuje.")
        if nodes == Nil: # seznam uzlu k vyreseni je prazdny
            return reconstruct_search_tree(solved)
        _, g1, c, node, path = nodes.head
        if is_goal(node):
            solved = Cons((node, Cons(node, path)), solved)
            heapq.heappush(heap, (f-h(node)-c, g-c, nodes.tail, solved))
        elif f <= biggest:
            succ = get_successors(node)
            if succ is None: # narazili jsme na necilovy uzel
                continue
            op, successors = succ
            path1 = Cons(node, path)
            if op == "and":
                nodes1 = nodes.tail
                for m, c in successors:
                    if not member(m, path1):
                        nodes1 = insert((g1+c+h(m), g1+c, c, m, path1), nodes1)
                        f = g + c + h(m)
                        g = g + c
                heapq.heappush(heap, (f, g, nodes1, solved))
            if op == "or":
                for m, c in successors:
                    if not member(m, path1):
                        nodes1 = insert((g1+c+h(m), g1+c, c, m, path1), nodes.tail)
                        heapq.heappush(heap, (g+c+h(m), g+c, nodes1, solved))

def reconstruct_search_tree(leaves):
    tree = dict()
    for node, path in leaves:
        tree[node] = "goal"
        while path != Nil and path.tail != Nil:
            node = path.head
            parent = path.tail.head
            if parent not in tree:
                op, _ = get_successors(parent)
                tree[parent] = (op + "_result", LinkedList([node]))
            else:
                op, nodes = tree[parent]
                if not member(node, nodes):
                    tree[parent] = (op, Cons(node, nodes))
                break
            path = path.tail
    return tree

def insert(node, nodes):
    if nodes == Nil:
        return LinkedList([node])
    f = node[0]
    f1 = nodes.head[0]
    if f <= f1:
        return Cons(node, nodes)
    return Cons(nodes.head, insert(node, nodes.tail))

def member(x, xs):
    if xs == Nil:
        return False
    if x == xs.head:
        return True
    return member(x, xs.tail)

def h(_):
    # zavisi na resenem problemu
    return 0

graph = dict(
    a=("or", LinkedList([("b", 1), ("c", 3)])),
    b=("and", LinkedList([("d", 1), ("e", 1)])),
    c=("and", LinkedList([("f", 2), ("g", 1)])),
    e=("or", LinkedList([("h", 6)])),
    f=("or", LinkedList([("h", 2), ("i", 3)])))

goals = dict(d=True, g=True, h=True)

def is_goal(node):
    # zavisi na resenem problemu
    return node in goals

# tato funkce nahrazuje prologovska fakta tvaru node ---> Op:Subtrees
# a pro zadany node navraci prislusne Op:Subtrees
def get_successors(node):
    # zavisi na resenem problemu
    if node in graph:
        return graph[node]
    return None

# demonstracni vypis
if __name__ == "__main__":
    print('Prohledavani AND/OR grafu - implementace pomoci prioritni fronty')
    print('\n  Graf:')
    print('    a ---> or:[b/1,c/3].')
    print('    b ---> and:[d/1,e/1].')
    print('    c ---> and:[f/2,g/1].')
    print('    e ---> or:[h/6].')
    print('    f ---> or:[h/2,i/3].')
    print('    h(X,0).')
    print('    goal(d).')
    print('    goal(g).')
    print('    goal(h).')
    print('\nVysledky dotazu andor("a"):')
    print(andor("a"))
+15 −0
Original line number Diff line number Diff line
Prohledavani AND/OR grafu - implementace pomoci prioritni fronty

  Graf:
    a ---> or:[b/1,c/3].
    b ---> and:[d/1,e/1].
    c ---> and:[f/2,g/1].
    e ---> or:[h/6].
    f ---> or:[h/2,i/3].
    h(X,0).
    goal(d).
    goal(g).
    goal(h).

Vysledky dotazu andor("a"):
{'a': ('or_result', ['c']), 'h': 'goal', 'c': ('and_result', ['g', 'f']), 'g': 'goal', 'f': ('or_result', ['h'])}
+175 −11
Original line number Diff line number Diff line
#!/usr/bin/env python
# encoding=utf-8 (pep 0263)

from linked_lists import LinkedList, Cons, Nil

# horni zavora pro cenu nejlepsi cesty
biggest = 9999

# format uzlu: ("leaf", n, f, c)
#              ("tree", n, f, c, subtrees)
#              ("solved_leaf", n, f)
#              ("solved_tree", n, f, subtrees)

# format seznamu potomku:
#              ("and", trees)
#              ("or", trees)
#              ("and_result", trees)
#              ("or_result", tree)

def andor(node):
    sol, solved = expand(("leaf", node, 0, 0), biggest):
    sol, solved = expand(("leaf", node, 0, 0), biggest)
    if solved == "yes":
        return sol
    else
    else:
        raise ValueError("Reseni neexistuje.")

def expand(tree, bound):
    if f(tree) > bound:
        return (tree, "no")
    if tree[0] == "leaf":
        _, node, f, c = tree
        if f(tree) <= bound:
    tree_type = tree[0]
    if tree_type == "leaf":
        _, node, f_, c = tree
        if is_goal(node):
                return (("solvedleaf", node, f), "yes")
            # ...
            return (("solved_leaf", node, f_), "yes")
        tree1 = expandnode(node, c)
        if tree1 is None: # neexistuji naslednici
            return (None, "never")
        return expand(tree1, bound)
    elif tree_type == "tree":
        _, node, f_, c, subtrees = tree
        newsubs, solved1 = expandlist(subtrees, bound-c)
        return continue_(solved1, node, c, newsubs, bound)

def expandlist(trees, bound):
    tree, othertrees, bound1 = select_tree(trees, bound)
    newtree, solved = expand(tree, bound1)
    return combine(othertrees, newtree, solved)

def continue_(subtr_solved, node, c, subtrees, bound):
    if subtr_solved == "never":
        return (None, "never")
    h_ = bestf(subtrees)
    f_ = c + h_
    if subtr_solved == "yes":
        return (("solved_tree", node, f_, subtrees), "yes")
    if subtr_solved == "no":
        return expand(("tree", node, f_, c, subtrees), bound)

def combine(subtrees, tree, solved):
    op, trees = subtrees
    if op == "or":
        if solved == "yes":
            return (("or_result", tree), "yes")
        if solved == "no":
            newtrees = insert(tree, trees)
            return (("or", newtrees), "no")
        if solved == "never":
            if trees == Nil:
                return (None, "never")
            return (("or", trees), "no")
    if op == "and":
        if solved == "yes" and are_all_solved(trees):
            return (("and_result", Cons(tree, trees)), "yes")
        if solved == "never":
            return (None, "never")
        newtrees = insert(tree, trees)
        return (("and", newtrees), "no")

def expandnode(node, c):
    succ = get_successors(node)
    if succ is None:
        return None
    op, successors = succ
    subtrees = evaluate(successors)
    h_ = bestf((op, subtrees))
    f_ = c + h_
    return ("tree", node, f_, c, (op, subtrees))

def evaluate(nodes):
    if nodes == Nil:
        return Nil
    node, c = nodes.head
    h_ = h(node)
    f_ = c + h_
    trees1 = evaluate(nodes.tail)
    trees = insert(("leaf", node, f_, c), trees1)
    return trees

def are_all_solved(trees):
    if trees == Nil:
        return True
    return is_solved(trees.head) and are_all_solved(trees.tail)

def is_solved(tree):
    tree_type = tree[0]
    return tree_type == "solved_tree" or tree_type == "solved_leaf"

def is_goal(x):
def f(tree):
    return tree[2]

def insert(t, trees):
    if trees == Nil:
        return Cons(t, Nil)
    t1 = trees.head
    ts = trees.tail
    if is_solved(t1):
        return Cons(t, trees)
    if is_solved(t):
        return Cons(t1, insert(t, ts))
    if f(t) <= f(t1):
        return Cons(t, trees)
    return Cons(t1, insert(t, ts))

def bestf(subtrees):
    op = subtrees[0]
    if op == "or":
        trees = subtrees[1]
        assert trees != Nil
        return f(trees.head)
    if op == "and" or op == "and_result":
        trees = subtrees[1]
        if trees == Nil:
            return 0
        return f(trees.head) + bestf(("and", trees.tail))
    if op == "or_result":
        tree = subtrees[1]
        return f(tree)

def select_tree(subtrees, bound):
    op, trees = subtrees
    if trees.tail == Nil:
        return (trees.head, (op, Nil), bound)
    f_ = bestf((op, trees.tail))
    assert op == "or" or op == "and"
    if op == "or":
        bound1 = min(bound, f_)
    if op == "and":
        bound1 = bound - f_
    return (trees.head, (op, trees.tail), bound1)

def h(_):
    # zavisi na resenem problemu
    return False
    return 0

graph = dict(
    a=("or", LinkedList([("b", 1), ("c", 3)])),
    b=("and", LinkedList([("d", 1), ("e", 1)])),
    c=("and", LinkedList([("f", 2), ("g", 1)])),
    e=("or", LinkedList([("h", 6)])),
    f=("or", LinkedList([("h", 2), ("i", 3)])))

goals = dict(d=True, g=True, h=True)

def is_goal(node):
    # zavisi na resenem problemu
    return node in goals

# tato funkce nahrazuje prologovska fakta tvaru node ---> Op:Subtrees
# a pro zadany node navraci prislusne Op:Subtrees
def get_successors(node):
    # zavisi na resenem problemu
    if node in graph:
        return graph[node]
    return None

# demonstracni vypis
if __name__ == "__main__":
    print('Prohledavani AND/OR grafu')
    print('\n  Graf:')
    print('    a ---> or:[b/1,c/3].')
    print('    b ---> and:[d/1,e/1].')
    print('    c ---> and:[f/2,g/1].')
    print('    e ---> or:[h/6].')
    print('    f ---> or:[h/2,i/3].')
    print('    h(X,0).')
    print('    goal(d).')
    print('    goal(g).')
    print('    goal(h).')
    print('\nVysledky dotazu andor("a"):')
    print(andor("a"))
Loading