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

added example 4.1_9

parent 8d6e62be
% pklad na reen posunovaky pomoc A*
start([2/2, 3/1, 2/3, 2/1, 3/3, 1/2, 3/2, 1/3, 1/1]).
goal([1/3, 2/3, 3/3, 1/2, 2/2, 3/2, 1/1, 2/1, 3/1]).
% move pomoc pohyb mezery (cena vdy 1)
move([XB/YB | Numbers], [XL/YB | NewNumbers], 1) :-
XB>1, % pohyb mezery doleva
XL is XB - 1, replace(XL/YB, XB/YB, Numbers, NewNumbers).
move([XB/YB | Numbers], [XR/YB | NewNumbers], 1) :-
XB<3, % pohyb mezery doprava
XR is XB + 1, replace(XR/YB, XB/YB, Numbers, NewNumbers).
move([XB/YB | Numbers], [XB/YD | NewNumbers], 1) :-
YB>1, % pohyb mezery dolu
YD is YB - 1, replace(XB/YD, XB/YB, Numbers, NewNumbers).
move([XB/YB | Numbers], [XB/YU | NewNumbers], 1) :-
YB<3, % pohyb mezery nahoru
YU is YB + 1, replace(XB/YU, XB/YB, Numbers, NewNumbers).
% replace
replace(A,B,[A|T],[B|T]):-!.
replace(A,B,[H|T1],[H|T2]) :- replace(A,B,T1,T2).
% heuristika h1
h(State,H):-
cnt_1(State,Ok_1),
cnt_2(State,Ok_2),
cnt_3(State,Ok_3),
cnt_4(State,Ok_4),
cnt_5(State,Ok_5),
cnt_6(State,Ok_6),
cnt_7(State,Ok_7),
cnt_8(State,Ok_8),
H is Ok_1+Ok_2+Ok_3+Ok_4+Ok_5+Ok_6+Ok_7+Ok_8.
%write('H['),write(State),write(']='),write(H),nl.
%goal([1/3, 2/3, 3/3, 1/2, 2/2, 3/2, 1/1, 2/1, 3/1]).
cnt_1([_,2/3|_],0):-!. cnt_1(_,1).
cnt_2([_,_,3/3|_],0):-!. cnt_2(_,1).
cnt_3([_,_,_,1/2|_],0):-!. cnt_3(_,1).
cnt_4([_,_,_,_,2/2|_],0):-!. cnt_4(_,1).
cnt_5([_,_,_,_,_,3/2|_],0):-!. cnt_5(_,1).
cnt_6([_,_,_,_,_,_,1/1|_],0):-!. cnt_6(_,1).
cnt_7([_,_,_,_,_,_,_,2/1|_],0):-!. cnt_7(_,1).
cnt_8([_,_,_,_,_,_,_,_,3/1],0):-!. cnt_8(_,1).
%
biggest(99).
writelist(L):-writelist(L,1).
writelist([E|L],I):-write(I),write(': '),write(E),nl,I1 is I+1,writelist(L,I1).
writelist([],_).
run:-
['4.1_9.pl'], nl,
write('8-posunovacka, algoritmus A*, heuristika h1'), nl, nl,
start(Start),
write('Pocatecni stav: '), write(Start), nl,
bestsearch(Start, Solution),
write('Nalezene reseni:'),nl,
reverse(Solution,RSolution),
writelist(RSolution).
% 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)
import heapq
from linked_lists import Cons, Nil
from romanian_cities import graph
# horni zavora pro cenu nejlepsi cesty
biggest = 9999
def bestsearch(start):
heap = [(0, 0, start, Nil)]
while True:
try:
f, g, node, path = heapq.heappop(heap)
except IndexError: # fronta je prazdna
break
path1 = Cons(node, path)
if is_goal(node):
yield (f, path1)
if f <= biggest:
for m, c in move_anyYC(node):
if not member(m, path):
heapq.heappush(heap, (g+c+h(m), g+c, m, path1))
def member(x, xs):
if xs == Nil:
return False
if x == xs.head:
return True
return member(x, xs.tail)
def is_goal(x):
# zavisi na resenem problemu
return x == "Bukurest"
def move_anyYC(x):
# zavisi na resenem problemu
if x in graph:
for y, c in graph[x][0]:
yield (y, c)
def h(x):
# zavisi na resenem problemu
return graph[x][1]
# demonstracni vypis
if __name__ == "__main__":
print("Best-First Search (algoritmus A*)")
print("Veskere jednoduche cesty mezi mesty Arad a Bukurest serazene vzestupne podle ceny:")
for solution in bestsearch('Arad'):
print(solution)
Best-First Search (algoritmus A*)
Veskere jednoduche cesty mezi mesty Arad a Bukurest serazene vzestupne podle ceny:
(418, ['Bukurest', 'Pitesti', 'Rimnicu_Vilcea', 'Sibiu', 'Arad'])
(450, ['Bukurest', 'Fagaras', 'Sibiu', 'Arad'])
(575, ['Bukurest', 'Pitesti', 'Rimnicu_Vilcea', 'Sibiu', 'Oradea', 'Zerind', 'Arad'])
(605, ['Bukurest', 'Pitesti', 'Craiova', 'Rimnicu_Vilcea', 'Sibiu', 'Arad'])
(607, ['Bukurest', 'Fagaras', 'Sibiu', 'Oradea', 'Zerind', 'Arad'])
(733, ['Bukurest', 'Pitesti', 'Craiova', 'Dobreta', 'Mehadia', 'Lugoj', 'Timisoara', 'Arad'])
(762, ['Bukurest', 'Pitesti', 'Craiova', 'Rimnicu_Vilcea', 'Sibiu', 'Oradea', 'Zerind', 'Arad'])
(838, ['Bukurest', 'Pitesti', 'Rimnicu_Vilcea', 'Craiova', 'Dobreta', 'Mehadia', 'Lugoj', 'Timisoara', 'Arad'])
(1030, ['Bukurest', 'Fagaras', 'Sibiu', 'Rimnicu_Vilcea', 'Craiova', 'Dobreta', 'Mehadia', 'Lugoj', 'Timisoara', 'Arad'])
(1109, ['Bukurest', 'Fagaras', 'Sibiu', 'Rimnicu_Vilcea', 'Pitesti', 'Craiova', 'Dobreta', 'Mehadia', 'Lugoj', 'Timisoara', 'Arad'])
% nacteni:
/* ['4.1_9.pl']. */
bestsearch(Start,Solution) :- biggest(Big), expand([], l(Start,0/0),Big,_,yes,Solution).
expand(P,l(N,_),_,_,yes,[N|P]) :- goal(N).
expand(P,l(N,F/G),Bound,Tree1,Solved,Sol) :- F=<Bound,
(bagof(M/C,(move(N,M,C),\+ member(M,P)),Succ),!,succlist(G,Succ,Ts),
bestf(Ts,F1), expand(P,t(N,F1/G,Ts),Bound,Tree1,Solved,Sol);Solved=never).
expand(P,t(N,F/G,[T|Ts]),Bound,Tree1,Solved,Sol) :- F=<Bound, bestf(Ts,BF),
min(Bound,BF,Bound1),expand([N|P],T,Bound1,T1,Solved1,Sol),
continue(P,t(N,F/G,[T1|Ts]),Bound,Tree1,Solved1,Solved,Sol).
expand(_,t(_,_,[]),_,_,never,_) :- !.
expand(_,Tree,Bound,Tree,no,_) :- f(Tree,F), F>Bound.
continue(_,_,_,_,yes,yes,_Sol).
continue(P,t(N,_F/G,[T1|Ts]),Bound,Tree1,Solved1,Solved,Sol) :-
(Solved1=no,insert(T1,Ts,NTs);Solved1=never,NTs=Ts),
bestf(NTs,F1),expand(P,t(N,F1/G,NTs),Bound,Tree1,Solved,Sol).
succlist(_,[],[]).
succlist(G0,[N/C|NCs],Ts) :- G is G0+C,h(N,H),F is G+H,
succlist(G0,NCs,Ts1), insert(l(N,F/G),Ts1,Ts).
insert(T,Ts,[T|Ts]) :- f(T,F),bestf(Ts,F1),F=<F1,!.
insert(T,[T1|Ts],[T1|Ts1]) :- insert(T,Ts,Ts1).
f(l(_,F/_),F).
f(t(_,F/_,_),F).
bestf([T|_], F) :- f(T,F).
bestf([], Big) :- biggest(Big).
min(X,Y,X) :- X=<Y,!.
min(_X,Y,Y).
#!/usr/bin/env python
# encoding=utf-8 (pep 0263)
from linked_lists import Cons, Nil
from romanian_cities import graph
# horni zavora pro cenu nejlepsi cesty
biggest = 9999
def bestsearch(start):
for _, solved, sol in expand(Nil, (start, 0, 0), biggest):
if solved == "yes":
yield sol
def expand(path, tree, bound):
if len(tree) == 3: # a leaf
node, f_, g = tree
if is_goal(node):
yield (None, "yes", (f_, Cons(node, path)))
if f_ <= bound:
succ = Nil
for m, c in move_anyYC(node):
if not member(m, path):
succ = Cons((m, c), succ)
if succ == Nil:
yield (None, "never", None)
else:
trees = succlist(g, succ)
f1 = bestf(trees)
for tree1, solved, sol in 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, bestf(trees.tail))
for t1, solved1, sol1 in expand(Cons(node, path), trees.head, bound1):
for tree1, solved, sol in 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_(path, tree, bound, subtr_solved, sol):
node, _, g, trees = tree
if subtr_solved == "yes":
yield (None, "yes", sol)
elif subtr_solved == "no":
nts = insert(trees.head, trees.tail)
f1 = bestf(nts)
for tree1, solved, sol in expand(path, (node, f1, g, nts), bound):
yield (tree1, solved, sol)
elif subtr_solved == "never":
f1 = bestf(trees.tail)
for tree1, solved, sol in expand(path, (node, f1, g, trees.tail), bound):
yield (tree1, solved, sol)
def succlist(g0, succ):
if succ == Nil:
return Nil
n, c = succ.head
g = g0 + c
f_ = g + h(n)
ts1 = succlist(g0, succ.tail)
ts = insert((n, f_, g), ts1)
return ts
def f(tree):
if len(tree) == 3: # a leaf
_, f_, _ = tree
else: # a tree
_, f_, _, _ = tree
return f_
def bestf(trees):
if trees == Nil:
return biggest
return f(trees.head)
def insert(t, ts):
if f(t) <= bestf(ts):
return Cons(t, ts)
return Cons(ts.head, insert(t, ts.tail))
def member(x, xs):
if xs == Nil:
return False
if x == xs.head:
return True
return member(x, xs.tail)
def is_goal(x):
# zavisi na resenem problemu
return x == "Bukurest"
def move_anyYC(x):
# zavisi na resenem problemu
if x in graph:
for y, c in graph[x][0]:
yield (y, c)
def h(x):
# zavisi na resenem problemu
return graph[x][1]
# demonstracni vypis
if __name__ == "__main__":
print("Best-First Search (algoritmus A*)")
print("Veskere jednoduche cesty mezi mesty Arad a Bukurest serazene vzestupne podle ceny:")
for solution in bestsearch('Arad'):
print(solution)
Best-First Search (algoritmus A*)
Veskere jednoduche cesty mezi mesty Arad a Bukurest serazene vzestupne podle ceny:
(418, ['Bukurest', 'Pitesti', 'Rimnicu_Vilcea', 'Sibiu', 'Arad'])
(450, ['Bukurest', 'Fagaras', 'Sibiu', 'Arad'])
(575, ['Bukurest', 'Pitesti', 'Rimnicu_Vilcea', 'Sibiu', 'Oradea', 'Zerind', 'Arad'])
(605, ['Bukurest', 'Pitesti', 'Craiova', 'Rimnicu_Vilcea', 'Sibiu', 'Arad'])
(607, ['Bukurest', 'Fagaras', 'Sibiu', 'Oradea', 'Zerind', 'Arad'])
(733, ['Bukurest', 'Pitesti', 'Craiova', 'Dobreta', 'Mehadia', 'Lugoj', 'Timisoara', 'Arad'])
(762, ['Bukurest', 'Pitesti', 'Craiova', 'Rimnicu_Vilcea', 'Sibiu', 'Oradea', 'Zerind', 'Arad'])
(838, ['Bukurest', 'Pitesti', 'Rimnicu_Vilcea', 'Craiova', 'Dobreta', 'Mehadia', 'Lugoj', 'Timisoara', 'Arad'])
(1030, ['Bukurest', 'Fagaras', 'Sibiu', 'Rimnicu_Vilcea', 'Craiova', 'Dobreta', 'Mehadia', 'Lugoj', 'Timisoara', 'Arad'])
(1109, ['Bukurest', 'Fagaras', 'Sibiu', 'Rimnicu_Vilcea', 'Pitesti', 'Craiova', 'Dobreta', 'Mehadia', 'Lugoj', 'Timisoara', 'Arad'])
.PHONY: tests output pylint2 pylint3
IGNORED_PYLINT_TESTS=invalid-name missing-docstring \
redefined-variable-type too-few-public-methods duplicate-code
redefined-variable-type too-few-public-methods duplicate-code \
too-many-locals too-many-branches
IGNORED_PYLINT2_TESTS=superfluous-parens
IGNORED_PYLINT3_TESTS=
......
#!/usr/bin/env python
# encoding=utf-8 (pep 0263)
""" Graf rumunskych mest vcetne predpocitanych vzdalenosti
mezi mesty a predpocitanou vzdusnou vzdalenosti do Bukuresti """
graph = dict(
Arad=([
("Sibiu", 140),
("Timisoara", 118),
("Zerind", 75),
], 366),
Bukurest=([
("Fagaras", 211),
("Giurgiu", 90),
("Pitesti", 101),
("Urziceni", 85),
], 0),
Craiova=([
("Dobreta", 120),
("Pitesti", 138),
("Rimnicu_Vilcea", 146),
], 160),
Dobreta=([
("Craiova", 120),
("Mehadia", 75),
], 242),
Fagaras=([
("Bukurest", 211),
("Sibiu", 99),
], 178),
Eforie=([
("Hirsova", 86),
], 161),
Giurgiu=([
("Bukurest", 90),
], 77),
Hirsova=([
("Eforie", 86),
("Urziceni", 98),
], 151),
Iasi=([
("Neamt", 87),
("Vaslui", 92),
], 226),
Lugoj=([
("Mehadia", 70),
("Timisoara", 111),
], 244),
Mehadia=([
("Dobreta", 75),
("Lugoj", 70),
], 241),
Neamt=([
("Iasi", 87),
], 234),
Oradea=([
("Sibiu", 151),
("Zerind", 71),
], 380),
Pitesti=([
("Bukurest", 101),
("Craiova", 138),
("Rimnicu_Vilcea", 87),
], 98),
Rimnicu_Vilcea=([
("Craiova", 146),
("Pitesti", 97),
("Sibiu", 80),
], 193),
Sibiu=([
("Arad", 140),
("Fagaras", 99),
("Oradea", 151),
("Rimnicu_Vilcea", 80),
], 253),
Timisoara=([
("Arad", 118),
("Lugoj", 111),
], 320),
Urziceni=([
("Bukurest", 85),
("Hirsova", 98),
("Vaslui", 142),
], 80),
Vaslui=([
("Iasi", 92),
("Urziceni", 142),
], 199),
Zerind=([
("Arad", 75),
("Oradea", 71),
], 374))
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