Commit 298095c8 authored by Vít Novotný's avatar Vít Novotný
Browse files

best_search now uses stable sorting

parent ffedfdf9
......@@ -2,7 +2,7 @@
# encoding=utf-8 (pep 0263)
from linked_lists import LinkedList, Cons, Nil
from best_search import best_search
from best_search import BestSearch
biggest = 99
start = LinkedList([(2, 2), (3, 1), (2, 3), (2, 1), (3, 3), (1, 2), (3, 2), (1, 3), (1, 1)])
......@@ -68,11 +68,11 @@ if __name__ == "__main__":
print("Pocatecni stav: %s" % start)
print("\nNalezene reseni (heuristika h1):")
solution, searched, cost = next(best_search(start, biggest, is_goal, move_anyYC, 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))
writelist(solution.reverse())
print("\nNalezene reseni (heuristika h2):")
solution, searched, cost = next(best_search(start, biggest, is_goal, move_anyYC, 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))
writelist(solution.reverse())
8-posunovacka, algoritmus A*
Pocatecni stav: [(2, 2), (3, 1), (2, 3), (2, 1), (3, 3), (1, 2), (3, 2), (1, 3), (1, 1)]
Nalezene reseni (heuristika h1):
Prohledano 170244 stavu, vysledne reseni ma cenu 26.
1: [(2, 2), (3, 1), (2, 3), (2, 1), (3, 3), (1, 2), (3, 2), (1, 3), (1, 1)]
2: [(1, 2), (3, 1), (2, 3), (2, 1), (3, 3), (2, 2), (3, 2), (1, 3), (1, 1)]
3: [(1, 3), (3, 1), (2, 3), (2, 1), (3, 3), (2, 2), (3, 2), (1, 2), (1, 1)]
4: [(2, 3), (3, 1), (1, 3), (2, 1), (3, 3), (2, 2), (3, 2), (1, 2), (1, 1)]
5: [(2, 2), (3, 1), (1, 3), (2, 1), (3, 3), (2, 3), (3, 2), (1, 2), (1, 1)]
6: [(3, 2), (3, 1), (1, 3), (2, 1), (3, 3), (2, 3), (2, 2), (1, 2), (1, 1)]
7: [(3, 1), (3, 2), (1, 3), (2, 1), (3, 3), (2, 3), (2, 2), (1, 2), (1, 1)]
8: [(2, 1), (3, 2), (1, 3), (3, 1), (3, 3), (2, 3), (2, 2), (1, 2), (1, 1)]
9: [(1, 1), (3, 2), (1, 3), (3, 1), (3, 3), (2, 3), (2, 2), (1, 2), (2, 1)]
10: [(1, 2), (3, 2), (1, 3), (3, 1), (3, 3), (2, 3), (2, 2), (1, 1), (2, 1)]
11: [(2, 2), (3, 2), (1, 3), (3, 1), (3, 3), (2, 3), (1, 2), (1, 1), (2, 1)]
12: [(3, 2), (2, 2), (1, 3), (3, 1), (3, 3), (2, 3), (1, 2), (1, 1), (2, 1)]
13: [(3, 1), (2, 2), (1, 3), (3, 2), (3, 3), (2, 3), (1, 2), (1, 1), (2, 1)]
14: [(2, 1), (2, 2), (1, 3), (3, 2), (3, 3), (2, 3), (1, 2), (1, 1), (3, 1)]
15: [(1, 1), (2, 2), (1, 3), (3, 2), (3, 3), (2, 3), (1, 2), (2, 1), (3, 1)]
16: [(1, 2), (2, 2), (1, 3), (3, 2), (3, 3), (2, 3), (1, 1), (2, 1), (3, 1)]
17: [(2, 2), (1, 2), (1, 3), (3, 2), (3, 3), (2, 3), (1, 1), (2, 1), (3, 1)]
18: [(3, 2), (1, 2), (1, 3), (2, 2), (3, 3), (2, 3), (1, 1), (2, 1), (3, 1)]
19: [(3, 3), (1, 2), (1, 3), (2, 2), (3, 2), (2, 3), (1, 1), (2, 1), (3, 1)]
20: [(2, 3), (1, 2), (1, 3), (2, 2), (3, 2), (3, 3), (1, 1), (2, 1), (3, 1)]
21: [(1, 3), (1, 2), (2, 3), (2, 2), (3, 2), (3, 3), (1, 1), (2, 1), (3, 1)]
22: [(1, 2), (1, 3), (2, 3), (2, 2), (3, 2), (3, 3), (1, 1), (2, 1), (3, 1)]
23: [(2, 2), (1, 3), (2, 3), (1, 2), (3, 2), (3, 3), (1, 1), (2, 1), (3, 1)]
24: [(3, 2), (1, 3), (2, 3), (1, 2), (2, 2), (3, 3), (1, 1), (2, 1), (3, 1)]
25: [(3, 3), (1, 3), (2, 3), (1, 2), (2, 2), (3, 2), (1, 1), (2, 1), (3, 1)]
26: [(2, 3), (1, 3), (3, 3), (1, 2), (2, 2), (3, 2), (1, 1), (2, 1), (3, 1)]
27: [(1, 3), (2, 3), (3, 3), (1, 2), (2, 2), (3, 2), (1, 1), (2, 1), (3, 1)]
Nalezene reseni (heuristika h2):
Prohledano 7087 stavu, vysledne reseni ma cenu 26.
1: [(2, 2), (3, 1), (2, 3), (2, 1), (3, 3), (1, 2), (3, 2), (1, 3), (1, 1)]
2: [(1, 2), (3, 1), (2, 3), (2, 1), (3, 3), (2, 2), (3, 2), (1, 3), (1, 1)]
3: [(1, 3), (3, 1), (2, 3), (2, 1), (3, 3), (2, 2), (3, 2), (1, 2), (1, 1)]
4: [(2, 3), (3, 1), (1, 3), (2, 1), (3, 3), (2, 2), (3, 2), (1, 2), (1, 1)]
5: [(2, 2), (3, 1), (1, 3), (2, 1), (3, 3), (2, 3), (3, 2), (1, 2), (1, 1)]
6: [(2, 1), (3, 1), (1, 3), (2, 2), (3, 3), (2, 3), (3, 2), (1, 2), (1, 1)]
7: [(1, 1), (3, 1), (1, 3), (2, 2), (3, 3), (2, 3), (3, 2), (1, 2), (2, 1)]
8: [(1, 2), (3, 1), (1, 3), (2, 2), (3, 3), (2, 3), (3, 2), (1, 1), (2, 1)]
9: [(2, 2), (3, 1), (1, 3), (1, 2), (3, 3), (2, 3), (3, 2), (1, 1), (2, 1)]
10: [(3, 2), (3, 1), (1, 3), (1, 2), (3, 3), (2, 3), (2, 2), (1, 1), (2, 1)]
11: [(3, 3), (3, 1), (1, 3), (1, 2), (3, 2), (2, 3), (2, 2), (1, 1), (2, 1)]
12: [(2, 3), (3, 1), (1, 3), (1, 2), (3, 2), (3, 3), (2, 2), (1, 1), (2, 1)]
13: [(1, 3), (3, 1), (2, 3), (1, 2), (3, 2), (3, 3), (2, 2), (1, 1), (2, 1)]
14: [(1, 2), (3, 1), (2, 3), (1, 3), (3, 2), (3, 3), (2, 2), (1, 1), (2, 1)]
15: [(2, 2), (3, 1), (2, 3), (1, 3), (3, 2), (3, 3), (1, 2), (1, 1), (2, 1)]
16: [(3, 2), (3, 1), (2, 3), (1, 3), (2, 2), (3, 3), (1, 2), (1, 1), (2, 1)]
17: [(3, 1), (3, 2), (2, 3), (1, 3), (2, 2), (3, 3), (1, 2), (1, 1), (2, 1)]
18: [(2, 1), (3, 2), (2, 3), (1, 3), (2, 2), (3, 3), (1, 2), (1, 1), (3, 1)]
19: [(2, 2), (3, 2), (2, 3), (1, 3), (2, 1), (3, 3), (1, 2), (1, 1), (3, 1)]
20: [(3, 2), (2, 2), (2, 3), (1, 3), (2, 1), (3, 3), (1, 2), (1, 1), (3, 1)]
21: [(3, 3), (2, 2), (2, 3), (1, 3), (2, 1), (3, 2), (1, 2), (1, 1), (3, 1)]
22: [(2, 3), (2, 2), (3, 3), (1, 3), (2, 1), (3, 2), (1, 2), (1, 1), (3, 1)]
23: [(2, 2), (2, 3), (3, 3), (1, 3), (2, 1), (3, 2), (1, 2), (1, 1), (3, 1)]
24: [(2, 1), (2, 3), (3, 3), (1, 3), (2, 2), (3, 2), (1, 2), (1, 1), (3, 1)]
25: [(1, 1), (2, 3), (3, 3), (1, 3), (2, 2), (3, 2), (1, 2), (2, 1), (3, 1)]
26: [(1, 2), (2, 3), (3, 3), (1, 3), (2, 2), (3, 2), (1, 1), (2, 1), (3, 1)]
27: [(1, 3), (2, 3), (3, 3), (1, 2), (2, 2), (3, 2), (1, 1), (2, 1), (3, 1)]
......@@ -2,7 +2,7 @@
# encoding=utf-8 (pep 0263)
from linked_lists import LinkedList, Cons, Nil
from best_search import best_search
from best_search import BestSearch
biggest = 99
start = (LinkedList([("t1", 4), ("t2", 2), ("t3", 2), ("t4", 20),
......@@ -110,6 +110,6 @@ if __name__ == "__main__":
print("Pocatecni stav: %s" % (start,))
print("\nNalezene reseni:")
solution, searched, cost_ = next(best_search(start, biggest, is_goal, move_anyYC, h))
solution, searched, cost_ = next(BestSearch(biggest, is_goal, move_anyYC, h).search(start))
print("Prohledano %d stavu, vysledne reseni ma cenu %d." % (searched, cost_))
writelist(solution.reverse())
Rozvrh prace procesoru, algoritmus A*
Pocatecni stav: ([('t1', 4), ('t2', 2), ('t3', 2), ('t4', 20), ('t5', 20), ('t6', 11), ('t7', 11)], [('idle', 0), ('idle', 0), ('idle', 0)], 0)
Nalezene reseni:
Prohledano 130 stavu, vysledne reseni ma cenu 24.
1: ([('t1', 4), ('t2', 2), ('t3', 2), ('t4', 20), ('t5', 20), ('t6', 11), ('t7', 11)], [('idle', 0), ('idle', 0), ('idle', 0)], 0)
2: ([('t2', 2), ('t3', 2), ('t4', 20), ('t5', 20), ('t6', 11), ('t7', 11)], [('idle', 0), ('idle', 0), ('t1', 4)], 4)
3: ([('t3', 2), ('t4', 20), ('t5', 20), ('t6', 11), ('t7', 11)], [('idle', 0), ('t2', 2), ('t1', 4)], 4)
4: ([('t4', 20), ('t5', 20), ('t6', 11), ('t7', 11)], [('t3', 2), ('t2', 2), ('t1', 4)], 4)
5: ([('t4', 20), ('t5', 20), ('t7', 11)], [('t2', 2), ('t1', 4), ('t6', 13)], 13)
6: ([('t4', 20), ('t5', 20), ('t7', 11)], [('idle', 4), ('t1', 4), ('t6', 13)], 13)
7: ([('t4', 20), ('t7', 11)], [('t1', 4), ('t6', 13), ('t5', 24)], 24)
8: ([('t7', 11)], [('t6', 13), ('t4', 24), ('t5', 24)], 24)
9: ([], [('t7', 24), ('t4', 24), ('t5', 24)], 24)
......@@ -2,7 +2,7 @@
IGNORED_PYLINT_TESTS=invalid-name missing-docstring \
redefined-variable-type too-few-public-methods duplicate-code \
too-many-locals too-many-branches
too-many-locals too-many-branches too-many-arguments
IGNORED_PYLINT2_TESTS=superfluous-parens
IGNORED_PYLINT3_TESTS=
......
......@@ -3,25 +3,97 @@
""" Implementace algoritmu A* pomoci prioritni fronty """
import heapq
from linked_lists import Cons, Nil
def best_search(start, bound, is_goal, move_anyYC, h):
searched = 0
heap = [(0, 0, start, Nil)]
while True:
try:
f, g, node, path = heapq.heappop(heap)
except IndexError: # fronta je prazdna
break
searched = searched + 1
path1 = Cons(node, path)
if is_goal(node):
yield (path1, searched, g)
if f <= bound:
for m, c in move_anyYC(node):
if not member(m, path):
heapq.heappush(heap, (g+c+h(m), g+c, m, path1))
class BestSearch(object):
def __init__(self, bound, is_goal, move_anyYC, h):
self.total = 0
self.bound = bound
self.is_goal = is_goal
self.move_anyYC = move_anyYC
self.h = h
def search(self, start):
self.total = 0
for _, solved, sol in self.expand(Nil, (start, 0, 0), self.bound):
if solved == "yes":
yield sol
def expand(self, path, tree, bound):
if len(tree) == 3: # a leaf
node, f_, g = tree
if self.is_goal(node):
yield (None, "yes", (Cons(node, path), self.total, f_))
if f_ <= bound:
succ = Nil
for m, c in self.move_anyYC(node):
if not member(m, path):
self.total = self.total + 1
succ = Cons((m, c), succ)
if succ == Nil:
yield (None, "never", None)
else:
trees = self.succlist(g, succ)
f1 = self.bestf(trees)
for tree1, solved, sol in self.expand(path, (node, f1, g, trees), bound):
yield (tree1, solved, sol)
elif f_ > bound:
yield (tree, "no", None)
else: # a tree
node, f_, g, trees = tree
if trees == Nil:
yield (None, "never", None)
else:
if f_ <= bound:
bound1 = min(bound, self.bestf(trees.tail))
for t1, solved1, sol1 in self.expand(Cons(node, path), trees.head, bound1):
for tree1, solved, sol in self.continue_(path, (node, f_, g,
Cons(t1, trees.tail)),
bound, solved1, sol1):
yield (tree1, solved, sol)
elif f_ > bound:
yield (tree, "no", None)
def continue_(self, path, tree, bound, subtr_solved, sol):
node, _, g, trees = tree
if subtr_solved == "yes":
yield (None, "yes", sol)
elif subtr_solved == "no":
nts = self.insert(trees.head, trees.tail)
f1 = self.bestf(nts)
for tree1, solved, sol in self.expand(path, (node, f1, g, nts), bound):
yield (tree1, solved, sol)
elif subtr_solved == "never":
f1 = self.bestf(trees.tail)
for tree1, solved, sol in self.expand(path, (node, f1, g, trees.tail), bound):
yield (tree1, solved, sol)
def succlist(self, g0, succ):
if succ == Nil:
return Nil
n, c = succ.head
g = g0 + c
f_ = g + self.h(n)
ts1 = self.succlist(g0, succ.tail)
ts = self.insert((n, f_, g), ts1)
return ts
def bestf(self, trees):
if trees == Nil:
return self.bound
return f(trees.head)
def insert(self, t, ts):
if f(t) <= self.bestf(ts):
return Cons(t, ts)
return Cons(ts.head, self.insert(t, ts.tail))
def f(tree):
if len(tree) == 3: # a leaf
_, f_, _ = tree
else: # a tree
_, f_, _, _ = tree
return f_
def member(x, xs):
if xs == Nil:
......
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