Está en la página 1de 4

Tarea #9

Integrantes:
Camila Aguilar
Alex Escobar
Jhoselin Fernandez
Materia: Sistemas inteligentes
Docente: Paola Carranza

Tenemos el código transcrito y comentado, ya que lo revisamos parte por parte para poder entenderlos, y comentamos
para que sirven ciertas partes del código, que es importante, y demás.

#En esta parte del codigo se importa las librerias que se utilizaran.
%matplotlib inline
import matplotlib.pyplot as plt
import random
import heapq
import math
import sys
from collections import defaultdict, deque, Counter
from itertools import combinations

#En esta parte se define el tamaño del problema que se va a abordar mediante las clas
es
#esta parte abarca al constructor
class Problem(object) :
def _init_ (self,initial=None, goal=None, sizes=(3,5)): #en el argumento se halla
n los parámetros de entrada que no tienen ningún valor
self.initial =initial
self.goal= goal
self.sizes= sizes
#esta parte define las acciones que necesitan un estado previo
#entonces se tiene definidas las funciones para el nodo
def actions(self, state): raise NotImplementedError #el raise ayuda a que no h
aya errores
def result(self, state, action): raise NotImplementedError
def is_goal(self, state): return state ==self .goal # en re resultado se encue
ntra el estado y la acción que permite llegar al resultado
def _str_(self): #esta parte permite llenar un string
return '{}({!r},{!r})'.format(
type(self)._name_, self.initiat, self.goal) #nombre, donde te encuentras, y e
l objetivo

#aquí definimos el nodo con el cual se irá trabajando


class Node:
def _init_(self, state, parent=None, action=None, path_cost=0): #se inicializa el n
odo
self._dict_.update(state=state, parent=parent, action=action, path_cost=path_cost
)
#las funciones de abajo permiten saber longitud y en general el uso de recursos al
momento de trabajar con el nodo
def _repr_(self): return '<{}>'.format(self.state)
def _len_(self): return 0 if self.parent is None else (1 + len(self.parent)) #perm
ite saber longitud y en general el uso de recursos al momento de trabajar con el nodo
def _lt_ (self, other): return self.path_cost < other.path_cost
#se definieron las funciones
failure = Node('failure', path_cost=math.inf) # permite detectar fallas si el algorit
mo no ha encontrado salida
cutoff = Node('cutoff', path_cost=math.inf)

#con esta función se define que el nodo trabajado anteriormente debe expandirse media
nte el estado anterior del nodo

def expand (problem, node): #toma como parametro el problema y el nodo que hemos cons
truido antes
s = node.state
for action in problem .actions(s):
sl =problem .result(s, action)
cost =node.path_cost + problem .action_cost(s, action, sl)
yield Node(sl, node, action, cost)
#y comienza a generar los nodos hijos

#mediante esta funcion se determina la ruta de las acciones que se llevaran acabo par
a solucionar el problema
def path_actions(node):
if node.parent is None:
return []
return path_actions(node.parent) + [node.action]
#si no hay ningun nodo a ejecutar operar o expandir, este retorna vacío
#de lo contrario nos retorna la ruta de las acciones que se han tomado y va acompañad
o con las acciones.

FIFOQueue = deque
LIFOQueue = list

#mantiene actualizada nuestra lista ya sea abierta o cerrada y va a depender si se tr


ata de una cola o un stack
#controla las entradas y salidas de la cola
class PriorityQueue:

def _init_(self, items=(), key=lambda x: x):


self.key = key
self.items = [] # pares (score, item)
for item in items:
self.add(item)
def add(self, item):
pair= (self. key( item), item)
heapq. heappush(self. items, pair)
def pop(self):
return heapq.heappop(self. items) [1]
def top(self): return self.items [0] [1]
#se debe entender en que momento esta ejecutando el problema
#van ingresando items para poder ir trabajando y también los mismos items van salie
ndo, de los que salen se va sacando la estructura de las filas o las columnas

#esta función permite hacer la busqueda por niveles llamando al problema definido
# va a trabajar a partir del análisis de nodos a partir delnodo inicial
#va preguntando si es metal, si no, pues continua analizando
#lo que hace es que toma un nodo frontera lo analiza y genera los hijos, actualizando
el estado de los hijos a los nuevos nodos frotera
def breadth_first_bfs(problem):
return best_first_search(problem, f=len)

def breadth_first_search(problem):
node = Node(problem. initial)
if problem.is_goal(initial):
return node
frontier=FIFOQueue([node])
reached={problem.initial}
while frontier:
node=frontier.pop()
for child in expand(problem, node):
s = child.state #corresponde a los hijos que se van generando en la frontera
#pregunta si los nodos hijos son meta y si no,pues continua, y si si pues retor
na al hio
if problem. is_goal(s):
return child
if s not in reached:
reached.add(s)
frontier.appendleft(child)
return failure

#el algoritmo corresponde a uno por amplitud, y no por profundidad, ya que maneja m
ejor los recursos

#en esta clase ya se trabaja con el problema


class PourProblem(Problem) : #se llama al problema
# en la función acciones va recorriendo los niveles y la longitud de las jarras y gen
era las acciones permitidas de acuerdo a la necesidad
def actions(self, state):
jarra= range( len(state))
return ([('llenar', i) for i in jarra if state[i] < self.sizes [i]] +
[('vaciar', i) for i in jarra if state[i]] +
[('intercambiar', i, j) for i in jarra if state[i] for j in jarra if i!=j
])
#esta funcion genera el resultado y lo almacena en una lista
def result(self, state, action) :
result = list(state)
act, i, *_= action
#aquí las condicionales actual y de acuerdo a estas se realiza una aciion que esta co
ncatenada a una ruta de acción
if act =='llenar': # llenar i a su maxima capacidad
result [i]
elif act == 'vaciar': # Vacia todo el contenido i
result [i]
elif act == 'intercambiar': # intercambiar de Za jarra
j = action[2]

amount = min(state[i],self.sizes[j] - state[j])# aqui se trabaja la lógica del


llenado y vaciado de las jarras, de la suma y resta del cotenido
result[i] -= amount
result [j]+= amount
return tuple( result)

def is_goal(self, state):


return self.goal in state

#estas lineas permiten determinar la ruta solución mediante la descripción y condicio


nes del problema y que acciones y rutas se tomo para llegar a esta
problem= PourProblem((0,0), goal=4, sizes=(3,5))
problem.actions((0,3))

Conclusión

Como grupo estudiamos el Código y como funciona este, si bien la lógica de como resolver esto mediante diagramas es
más sencillo y lo estamos desarrollando de buena forma en clase, esto presenta dificultad al momento de
implementarlos a un código, ya que utiliza muchas clases y funcione, y esto puede deberse a que si bien en nuestra
carrera llevamos programación, no se profundiza tanto como en carreras especializada. Por otro lado, si analizamos con
calma el código es entendible en su mayoría, teniendo bien marcado los punto de extrema importancia como la
generación del problema sus condiciones, la generación de nodos y las expansiones, es así que podemos concluir que si
bien el implementar código parece difícil, si tenemos bien sólidas las bases lógicas, solucionar cualquier problema es
posible.

También podría gustarte