Compare commits
No commits in common. "2d498eb23162177eb833879081e7b075caea4a51" and "7f5313608ec0b988da0e37a4c9c7b387e65c8f13" have entirely different histories.
2d498eb231
...
7f5313608e
247
cidades.py
247
cidades.py
|
@ -1,130 +1,119 @@
|
||||||
#
|
#
|
||||||
# Module: cidades
|
# Module: cidades
|
||||||
#
|
#
|
||||||
# Implements a SearchDomain for find paths between cities
|
# Implements a SearchDomain for find paths between cities
|
||||||
# using the tree_search module
|
# using the tree_search module
|
||||||
#
|
#
|
||||||
# (c) Luis Seabra Lopes
|
# (c) Luis Seabra Lopes
|
||||||
# Introducao a Inteligencia Artificial, 2012-2020
|
# Introducao a Inteligencia Artificial, 2012-2020
|
||||||
# Inteligência Artificial, 2014-2023
|
# Inteligência Artificial, 2014-2023
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
from tree_search import *
|
from tree_search import *
|
||||||
|
|
||||||
class Cidades(SearchDomain):
|
class Cidades(SearchDomain):
|
||||||
def __init__(self,connections, coordinates):
|
def __init__(self,connections, coordinates):
|
||||||
self.connections = connections
|
self.connections = connections
|
||||||
self.coordinates = coordinates
|
self.coordinates = coordinates
|
||||||
|
def actions(self,city):
|
||||||
def actions(self,city):
|
actlist = []
|
||||||
actlist = []
|
for (C1,C2,D) in self.connections:
|
||||||
for (C1,C2,D) in self.connections:
|
if (C1==city):
|
||||||
if (C1==city):
|
actlist += [(C1,C2)]
|
||||||
actlist += [(C1,C2)]
|
elif (C2==city):
|
||||||
elif (C2==city):
|
actlist += [(C2,C1)]
|
||||||
actlist += [(C2,C1)]
|
return actlist
|
||||||
return actlist
|
def result(self,city,action):
|
||||||
|
(C1,C2) = action
|
||||||
def result(self,city,action):
|
if C1==city:
|
||||||
(C1,C2) = action
|
return C2
|
||||||
if C1==city:
|
def cost(self, city, action):
|
||||||
return C2
|
pass
|
||||||
|
def heuristic(self, city, goal_city):
|
||||||
def cost(self, city, action):
|
pass
|
||||||
(C1,C2) = action
|
def satisfies(self, city, goal_city):
|
||||||
for (X,Y,D) in self.connections:
|
return goal_city==city
|
||||||
if X==C1 and Y==C2:
|
|
||||||
return D
|
|
||||||
if X==C2 and Y==C1:
|
cidades_portugal = Cidades(
|
||||||
return D
|
# Ligacoes por estrada
|
||||||
|
[
|
||||||
def heuristic(self, city, goal_city):
|
('Coimbra', 'Leiria', 73),
|
||||||
coords_city = cidades_portugal.coordinates[city]
|
('Aveiro', 'Agueda', 35),
|
||||||
coords_goal_city = cidades_portugal.coordinates[goal_city]
|
('Porto', 'Agueda', 79),
|
||||||
|
('Agueda', 'Coimbra', 45),
|
||||||
return ((coords_city[0] - coords_goal_city[0])**2 + (coords_city[1] - coords_goal_city[1])**2)**0.5
|
('Viseu', 'Agueda', 78),
|
||||||
|
('Aveiro', 'Porto', 78),
|
||||||
def satisfies(self, city, goal_city):
|
('Aveiro', 'Coimbra', 65),
|
||||||
return goal_city==city
|
('Figueira', 'Aveiro', 77),
|
||||||
|
('Braga', 'Porto', 57),
|
||||||
|
('Viseu', 'Guarda', 75),
|
||||||
cidades_portugal = Cidades(
|
('Viseu', 'Coimbra', 91),
|
||||||
# Ligacoes por estrada
|
('Figueira', 'Coimbra', 52),
|
||||||
[
|
('Leiria', 'Castelo Branco', 169),
|
||||||
('Coimbra', 'Leiria', 73),
|
('Figueira', 'Leiria', 62),
|
||||||
('Aveiro', 'Agueda', 35),
|
('Leiria', 'Santarem', 78),
|
||||||
('Porto', 'Agueda', 79),
|
('Santarem', 'Lisboa', 82),
|
||||||
('Agueda', 'Coimbra', 45),
|
('Santarem', 'Castelo Branco', 160),
|
||||||
('Viseu', 'Agueda', 78),
|
('Castelo Branco', 'Viseu', 174),
|
||||||
('Aveiro', 'Porto', 78),
|
('Santarem', 'Evora', 122),
|
||||||
('Aveiro', 'Coimbra', 65),
|
('Lisboa', 'Evora', 132),
|
||||||
('Figueira', 'Aveiro', 77),
|
('Evora', 'Beja', 105),
|
||||||
('Braga', 'Porto', 57),
|
('Lisboa', 'Beja', 178),
|
||||||
('Viseu', 'Guarda', 75),
|
('Faro', 'Beja', 147),
|
||||||
('Viseu', 'Coimbra', 91),
|
# extra
|
||||||
('Figueira', 'Coimbra', 52),
|
('Braga', 'Guimaraes', 25),
|
||||||
('Leiria', 'Castelo Branco', 169),
|
('Porto', 'Guimaraes', 44),
|
||||||
('Figueira', 'Leiria', 62),
|
('Guarda', 'Covilha', 46),
|
||||||
('Leiria', 'Santarem', 78),
|
('Viseu', 'Covilha', 57),
|
||||||
('Santarem', 'Lisboa', 82),
|
('Castelo Branco', 'Covilha', 62),
|
||||||
('Santarem', 'Castelo Branco', 160),
|
('Guarda', 'Castelo Branco', 96),
|
||||||
('Castelo Branco', 'Viseu', 174),
|
('Lamego','Guimaraes', 88),
|
||||||
('Santarem', 'Evora', 122),
|
('Lamego','Viseu', 47),
|
||||||
('Lisboa', 'Evora', 132),
|
('Lamego','Guarda', 64),
|
||||||
('Evora', 'Beja', 105),
|
('Portalegre','Castelo Branco', 64),
|
||||||
('Lisboa', 'Beja', 178),
|
('Portalegre','Santarem', 157),
|
||||||
('Faro', 'Beja', 147),
|
('Portalegre','Evora', 194) ],
|
||||||
# extra
|
|
||||||
('Braga', 'Guimaraes', 25),
|
# City coordinates
|
||||||
('Porto', 'Guimaraes', 44),
|
{ 'Aveiro': (41,215),
|
||||||
('Guarda', 'Covilha', 46),
|
'Figueira': ( 24, 161),
|
||||||
('Viseu', 'Covilha', 57),
|
'Coimbra': ( 60, 167),
|
||||||
('Castelo Branco', 'Covilha', 62),
|
'Agueda': ( 58, 208),
|
||||||
('Guarda', 'Castelo Branco', 96),
|
'Viseu': ( 104, 217),
|
||||||
('Lamego','Guimaraes', 88),
|
'Braga': ( 61, 317),
|
||||||
('Lamego','Viseu', 47),
|
'Porto': ( 45, 272),
|
||||||
('Lamego','Guarda', 64),
|
'Lisboa': ( 0, 0),
|
||||||
('Portalegre','Castelo Branco', 64),
|
'Santarem': ( 38, 59),
|
||||||
('Portalegre','Santarem', 157),
|
'Leiria': ( 28, 115),
|
||||||
('Portalegre','Evora', 194) ],
|
'Castelo Branco': ( 140, 124),
|
||||||
|
'Guarda': ( 159, 204),
|
||||||
# City coordinates
|
'Evora': (120, -10),
|
||||||
{ 'Aveiro': (41,215),
|
'Beja': (125, -110),
|
||||||
'Figueira': ( 24, 161),
|
'Faro': (120, -250),
|
||||||
'Coimbra': ( 60, 167),
|
#extra
|
||||||
'Agueda': ( 58, 208),
|
'Guimaraes': ( 71, 300),
|
||||||
'Viseu': ( 104, 217),
|
'Covilha': ( 130, 175),
|
||||||
'Braga': ( 61, 317),
|
'Lamego' : (125,250),
|
||||||
'Porto': ( 45, 272),
|
'Portalegre': (130,170) }
|
||||||
'Lisboa': ( 0, 0),
|
)
|
||||||
'Santarem': ( 38, 59),
|
|
||||||
'Leiria': ( 28, 115),
|
|
||||||
'Castelo Branco': ( 140, 124),
|
|
||||||
'Guarda': ( 159, 204),
|
|
||||||
'Evora': (120, -10),
|
p = SearchProblem(cidades_portugal,'Braga','Faro')
|
||||||
'Beja': (125, -110),
|
t = SearchTree(p,'breadth')
|
||||||
'Faro': (120, -250),
|
|
||||||
#extra
|
print(t.search())
|
||||||
'Guimaraes': ( 71, 300),
|
|
||||||
'Covilha': ( 130, 175),
|
|
||||||
'Lamego' : (125,250),
|
# Atalho para obter caminho de c1 para c2 usando strategy:
|
||||||
'Portalegre': (130,170) }
|
def search_path(c1,c2,strategy):
|
||||||
)
|
my_prob = SearchProblem(cidades_portugal,c1,c2)
|
||||||
|
my_tree = SearchTree(my_prob)
|
||||||
|
my_tree.strategy = strategy
|
||||||
|
return my_tree.search()
|
||||||
|
|
||||||
p = SearchProblem(cidades_portugal,'Braga','Faro')
|
|
||||||
t = SearchTree(p,'breadth')
|
|
||||||
|
|
||||||
print(t.search())
|
|
||||||
|
|
||||||
|
|
||||||
# Atalho para obter caminho de c1 para c2 usando strategy:
|
|
||||||
def search_path(c1,c2,strategy):
|
|
||||||
my_prob = SearchProblem(cidades_portugal,c1,c2)
|
|
||||||
my_tree = SearchTree(my_prob)
|
|
||||||
my_tree.strategy = strategy
|
|
||||||
return my_tree.search()
|
|
||||||
|
|
||||||
|
|
|
@ -62,16 +62,12 @@ class SearchProblem:
|
||||||
|
|
||||||
# Nos de uma arvore de pesquisa
|
# Nos de uma arvore de pesquisa
|
||||||
class SearchNode:
|
class SearchNode:
|
||||||
def __init__(self,state,parent, depth, cost=0, heuristic=0):
|
def __init__(self,state,parent, depth):
|
||||||
self.state = state
|
self.state = state
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.depth = depth
|
self.depth = depth
|
||||||
self.cost = cost
|
|
||||||
self.heuristic = heuristic
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "no(" + str(self.state) + "," + str(self.parent) + ")"
|
return "no(" + str(self.state) + "," + str(self.parent) + ")"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
|
@ -87,8 +83,6 @@ class SearchTree:
|
||||||
self.solution = None
|
self.solution = None
|
||||||
self.terminals = 0
|
self.terminals = 0
|
||||||
self.non_terminals = 0
|
self.non_terminals = 0
|
||||||
self.highest_cost_nodes = [root]
|
|
||||||
self.average_depth = 0
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def length(self):
|
def length(self):
|
||||||
|
@ -98,10 +92,6 @@ class SearchTree:
|
||||||
def avg_branching(self):
|
def avg_branching(self):
|
||||||
return ((self.terminals + self.non_terminals) - 1) / self.non_terminals if self.non_terminals > 0 else None
|
return ((self.terminals + self.non_terminals) - 1) / self.non_terminals if self.non_terminals > 0 else None
|
||||||
|
|
||||||
@property
|
|
||||||
def cost(self):
|
|
||||||
return self.solution.cost if self.solution else None
|
|
||||||
|
|
||||||
# obter o caminho (sequencia de estados) da raiz ate um no
|
# obter o caminho (sequencia de estados) da raiz ate um no
|
||||||
def get_path(self,node):
|
def get_path(self,node):
|
||||||
if node.parent == None:
|
if node.parent == None:
|
||||||
|
@ -115,10 +105,8 @@ class SearchTree:
|
||||||
while self.open_nodes != []:
|
while self.open_nodes != []:
|
||||||
self.terminals = len(self.open_nodes)
|
self.terminals = len(self.open_nodes)
|
||||||
node = self.open_nodes.pop(0)
|
node = self.open_nodes.pop(0)
|
||||||
|
|
||||||
if self.problem.goal_test(node.state):
|
if self.problem.goal_test(node.state):
|
||||||
self.solution = node
|
self.solution = node
|
||||||
self.average_depth = self.average_depth / (self.terminals + self.non_terminals)
|
|
||||||
return self.get_path(node)
|
return self.get_path(node)
|
||||||
|
|
||||||
self.non_terminals += 1
|
self.non_terminals += 1
|
||||||
|
@ -126,22 +114,13 @@ class SearchTree:
|
||||||
for a in self.problem.domain.actions(node.state):
|
for a in self.problem.domain.actions(node.state):
|
||||||
newstate = self.problem.domain.result(node.state,a)
|
newstate = self.problem.domain.result(node.state,a)
|
||||||
if newstate not in self.get_path(node):
|
if newstate not in self.get_path(node):
|
||||||
newnode = SearchNode(
|
newnode = SearchNode(newstate,node,node.depth+1)
|
||||||
newstate,
|
if limit != None and self.strategy == 'depth':
|
||||||
node,
|
if newnode.depth <= limit:
|
||||||
node.depth+1,
|
lnewnodes.append(newnode)
|
||||||
node.cost+self.problem.domain.cost(node.state,a),
|
else:
|
||||||
self.problem.domain.heuristic(newstate,self.problem.goal)
|
|
||||||
)
|
|
||||||
if not (limit != None and self.strategy == 'depth' and newnode.depth > limit):
|
|
||||||
lnewnodes.append(newnode)
|
lnewnodes.append(newnode)
|
||||||
if newnode.cost > self.highest_cost_nodes[0].cost:
|
|
||||||
self.highest_cost_nodes = [newnode]
|
|
||||||
elif newnode.cost == self.highest_cost_nodes[0].cost:
|
|
||||||
self.highest_cost_nodes.append(newnode)
|
|
||||||
self.average_depth += newnode.depth
|
|
||||||
self.add_to_open(lnewnodes)
|
self.add_to_open(lnewnodes)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# juntar novos nos a lista de nos abertos de acordo com a estrategia
|
# juntar novos nos a lista de nos abertos de acordo com a estrategia
|
||||||
|
@ -151,9 +130,5 @@ class SearchTree:
|
||||||
elif self.strategy == 'depth':
|
elif self.strategy == 'depth':
|
||||||
self.open_nodes[:0] = lnewnodes
|
self.open_nodes[:0] = lnewnodes
|
||||||
elif self.strategy == 'uniform':
|
elif self.strategy == 'uniform':
|
||||||
self.open_nodes = sorted(self.open_nodes + lnewnodes, key=lambda node: node.cost)
|
pass
|
||||||
elif self.strategy == 'greedy':
|
|
||||||
self.open_nodes = sorted(self.open_nodes + lnewnodes, key=lambda node: node.heuristic)
|
|
||||||
elif self.strategy == 'a*':
|
|
||||||
self.open_nodes = sorted(self.open_nodes + lnewnodes, key=lambda node: node.cost + node.heuristic)
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue