Commit 001f2184 authored by Vít Novotný's avatar Vít Novotný
Browse files

added example 5.3_15-cesta_mezi_mesty

parent 5b91ea35
......@@ -62,17 +62,24 @@ def writelist_(xs, i):
print("%d: %s" % (i, xs.head))
writelist_(xs.tail, i+1)
def length(xs):
if xs == Nil:
return 0
return 1 + length(xs.tail)
# demonstracni vypis
if __name__ == "__main__":
print("8-posunovacka, algoritmus A*\n")
print("Pocatecni stav: %s" % start)
print("\nNalezene reseni (heuristika h1):")
solution, searched, cost = next(BestSearch(biggest, is_goal, move_anyYC, h1).search(start))
print("Prohledano %d stavu, vysledne reseni ma cenu %d." % (searched, cost))
astar = BestSearch(biggest, is_goal, move_anyYC, h1)
solution = next(astar.search(start))
print("Prohledano %d stavu, vysledne reseni ma cenu %d." % (astar.total, length(solution)-1))
writelist(solution.reverse())
print("\nNalezene reseni (heuristika h2):")
solution, searched, cost = next(BestSearch(biggest, is_goal, move_anyYC, h2).search(start))
print("Prohledano %d stavu, vysledne reseni ma cenu %d." % (searched, cost))
astar = BestSearch(biggest, is_goal, move_anyYC, h2)
solution = next(astar.search(start))
print("Prohledano %d stavu, vysledne reseni ma cenu %d." % (astar.total, length(solution)-1))
writelist(solution.reverse())
......@@ -110,6 +110,7 @@ if __name__ == "__main__":
print("Pocatecni stav: %s" % (start,))
print("\nNalezene reseni:")
solution, searched, cost_ = next(BestSearch(biggest, is_goal, move_anyYC, h).search(start))
print("Prohledano %d stavu, vysledne reseni ma cenu %d." % (searched, cost_))
astar = BestSearch(biggest, is_goal, move_anyYC, h)
solution = next(astar.search(start))
print("Prohledano %d stavu, vysledne reseni ma cenu %d." % (astar.total, solution.head[2]))
writelist(solution.reverse())
% pklad Cesta mezi msty pomoc AND/OR A*
move(a,b,2). move(a,c,3). move(b,e,3).
move(b,d,2). move(c,e,1). move(c,l,2).
move(e,k,4). move(e,l,2). move(k,u,2).
move(k,x,3). move(u,v,5). move(x,y,3).
move(y,z,3). move(v,z,3). move(l,u,1).
move(d,k,1). move(u,y,2).
stateS(a). stateS(b). stateS(c). stateS(d). stateS(e).
stateT(u). stateT(v). stateT(x). stateT(y). stateT(z).
border(l). border(k).
key(M1-M2,M3) :- stateS(M1), stateT(M2), border(M3).
city(X) :- (stateS(X);stateT(X);border(X)).
% slide 20 - konstrukce grafu
?- op(700, xfx, --->),
op(560,xfx,via). % operatory X-Z a X-Z via Y
% a-z ---> or:[a-z via k/0,a-z via l/0].
% a-v ---> or:[a-v via k/0,a-v via l/0].
% ...
X-Z ---> or:Problemlist :- city(X),city(Z), bagof((X-Z via Y)/0, key(X-Z,Y), Problemlist),!.
% a-l ---> or:[c-l/3,b-l/2].
% b-l ---> or:[e-l/3,d-l/2].
% ...
X-Z ---> or:Problemlist :- city(X),city(Z), bagof((Y-Z)/D, move(X,Y,D), Problemlist).
% a-z via l ---> and:[a-l/0,l-z/0].
% a-v via l ---> and:[a-l/0,l-v/0].
% ...
X-Z via Y ---> and:[(X-Y)/0,(Y-Z)/0]:- city(X),city(Z),key(X-Z,Y).
%goal(a-a). goal(b-b). ...
goal(X-X).
% heuristika h - podle hrany nebo ze stejneho statu=1, z ruzneho=2
h(X-X,0).
h(X-Z,C):-move(X,Z,C),!.
h(X-Z,C):-move(Z,X,C),!.
h(X-Z,2):-stateS(X),stateT(Z),!.
h(X-Z,2):-stateT(X),stateS(Z),!.
h(X-Z via _,2):-stateS(X),stateT(Z),!.
h(X-Z via _,2):-stateT(X),stateS(Z),!.
h(_-_,1).
biggest(99).
run:-
['5.3_15.pl'], nl,
write('Cesta mezi mesty, algoritmus AND/OR A*'), nl, nl,
Start=a-z,
write('Zadani: '), write(Start), nl,
andor(Start,SolutionTree),
write('Nalezene reseni:'),nl,
write(SolutionTree).
% s heuristikou h1 vyzaduje hodne pameti (pro d=26)
%:- set_prolog_stack(local, limit(256 000 000)). % vyzaduje 64-bit system
:- run.
% vim: set ft=prolog:
#!/usr/bin/env python
# encoding=utf-8 (pep 0263)
from linked_lists import LinkedList, Cons, Nil
from and_or_best_search import BestSearch
biggest = 99
start = ("direct", "a", "z")
stateS = dict(a=True, b=True, c=True, d=True, e=True)
stateU = dict(u=True, v=True, x=True, y=True, z=True)
borders = dict(l=True, k=True)
distances = dict(
a=[("b", 2), ("c", 3)],
b=[("d", 2)],
c=[("e", 1), ("l", 2)],
d=[("k", 1)],
e=[("k", 3), ("l", 2)],
k=[("u", 2), ("x", 3)],
l=[("u", 1)],
u=[("v", 5), ("y", 2)],
x=[("y", 3)],
y=[("z", 3)],
v=[("z", 3)])
def get_successors(node):
if node[0] == "direct":
_, x, z = node
succ = Nil
if x in stateS and z in stateU:
for y in borders:
succ = Cons((("via", x, z, y), 0), succ)
if x in distances:
for y, d in distances[x]:
succ = Cons((("direct", y, z), d), succ)
if succ == Nil:
return None
return ("or", succ)
if node[0] == "via":
_, x, z, y = node
return ("and", LinkedList([(("direct", x, y), 0), (("direct", y, z), 0)]))
def is_goal(node):
return node[0] == "direct" and node[1] == node[2]
def h(node):
if is_goal(node):
return 0
if node[0] == "direct":
_, x, z = node
if x in distances:
for y, d in distances[x]:
if y == z:
return d
if x in stateS and z in stateU or z in stateS and x in stateU:
return 2
return 1
if node[0] == "via":
_, x, z, _ = node
if x in stateS and z in stateU or z in stateS and x in stateU:
return 2
# demonstracni vypis
if __name__ == "__main__":
print("Cesta mezi mesty, algoritmus AND/OR A*\n")
print("Zadani: %s" % (start,))
print("\nNalezene reseni:")
obj = BestSearch(biggest, is_goal, get_successors, h)
solution = obj.search(start)
print("Prohledano %d stavu, vysledne reseni ma cenu %d." % (obj.total, solution[2]))
print(solution)
Cesta mezi mesty, algoritmus AND/OR A*
Zadani: ('direct', 'a', 'z')
Nalezene reseni:
Prohledano 69 stavu, vysledne reseni ma cenu 11.
('solved_tree', ('direct', 'a', 'z'), 11, ('or_result', ('solved_tree', ('direct', 'c', 'z'), 11, ('or_result', ('solved_tree', ('via', 'c', 'z', 'l'), 8, ('and_result', [('solved_tree', ('direct', 'l', 'z'), 6, ('or_result', ('solved_tree', ('direct', 'u', 'z'), 6, ('or_result', ('solved_tree', ('direct', 'y', 'z'), 5, ('or_result', ('solved_leaf', ('direct', 'z', 'z'), 3))))))), ('solved_tree', ('direct', 'c', 'l'), 2, ('or_result', ('solved_leaf', ('direct', 'l', 'l'), 2)))]))))))
#!/usr/bin/env python
# encoding=utf-8 (pep 0263)
""" Implementace algoritmu AND/OR A* """
from linked_lists import Cons, Nil
class BestSearch(object):
def __init__(self, bound, is_goal, get_successors, h):
self.total = 0
self.bound = bound
self.is_goal = is_goal
self.get_successors = get_successors
self.h = h
def search(self, start):
self.total = 0
sol, solved = self.expand(("leaf", start, 0, 0), self.bound)
if solved == "yes":
return sol
else:
raise ValueError("Reseni neexistuje.")
def expand(self, tree, bound):
if f(tree) > bound:
return (tree, "no")
tree_type = tree[0]
if tree_type == "leaf":
self.total = self.total + 1
_, node, f_, c = tree
if self.is_goal(node):
return (("solved_leaf", node, f_), "yes")
tree1 = self.expandnode(node, c)
if tree1 is None: # neexistuji naslednici
return (None, "never")
return self.expand(tree1, bound)
elif tree_type == "tree":
_, node, f_, c, subtrees = tree
newsubs, solved1 = self.expandlist(subtrees, bound-c)
return self.continue_(solved1, node, c, newsubs, bound)
def expandlist(self, trees, bound):
tree, othertrees, bound1 = select_tree(trees, bound)
newtree, solved = self.expand(tree, bound1)
return combine(othertrees, newtree, solved)
def continue_(self, 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 self.expand(("tree", node, f_, c, subtrees), bound)
def expandnode(self, node, c):
succ = self.get_successors(node)
if succ is None:
return None
op, successors = succ
subtrees = self.evaluate(successors)
h_ = bestf((op, subtrees))
f_ = c + h_
return ("tree", node, f_, c, (op, subtrees))
def evaluate(self, nodes):
if nodes == Nil:
return Nil
node, c = nodes.head
h_ = self.h(node)
f_ = c + h_
trees1 = self.evaluate(nodes.tail)
trees = insert(("leaf", node, f_, c), trees1)
return trees
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 f(tree):
return tree[2]
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 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)
......@@ -23,7 +23,7 @@ class BestSearch(object):
if len(tree) == 3: # a leaf
node, f_, g = tree
if self.is_goal(node):
yield (None, "yes", (Cons(node, path), self.total, f_))
yield (None, "yes", Cons(node, path))
if f_ <= bound:
succ = Nil
for m, c in self.move_anyYC(node):
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment