def heap_sort(arr): ''' This consists of 2 steps: 1. build a min heap, which is O(nlogn) 2. extract all n elements of the heap, which is O(nlogn) Overall, this takes O(nlogn) ''' heap = BinaryHeap(arr) result = [] while not heap.is_empty(): result.append(heap.extract_min()) return result
class Astar: def __init__(self, initial_state, heuristic, weight=1): self.expansions = 0 self.generated = 0 self.initial_state = initial_state self.weight = weight self.heuristic = heuristic def search(self): self.start_time = time.process_time() self.open = BinaryHeap() self.expansions = 0 initial_node = Node(self.initial_state) initial_node.g = 0 initial_node.h = self.heuristic(self.initial_state) initial_node.key = 10000 * self.weight * initial_node.h # asignamos el valor f self.open.insert(initial_node) # para cada estado alguna vez generado, generated almacena # el Node que le corresponde self.generated = {} self.generated[self.initial_state] = initial_node while not self.open.is_empty(): n = self.open.extract() # extrae n de la open if n.state.is_goal(): self.end_time = time.process_time() return n succ = n.state.successors() self.expansions += 1 for child_state, action, cost in succ: child_node = self.generated.get(child_state) is_new = child_node is None # es la primera vez que veo a child_state path_cost = n.g + cost # costo del camino encontrado hasta child_state if is_new or path_cost < child_node.g: # si vemos el estado child_state por primera vez o lo vemos por # un mejor camino, entonces lo agregamos a open if is_new: # creamos el nodo de child_state child_node = Node(child_state, n) child_node.h = self.heuristic(child_state) self.generated[child_state] = child_node child_node.action = action child_node.parent = n child_node.g = path_cost child_node.key = 10000 * ( child_node.g + self.weight * child_node.h ) - child_node.g # actualizamos el f de child_node self.open.insert( child_node ) # inserta child_node a la open si no esta en la open self.end_time = time.process_time( ) # en caso contrario, modifica la posicion de child_node en open return None
class PriorityQueue(object): def __init__(self): self._heap = BinaryHeap() def peek(self): return self._heap.peek_min() def is_empty(self): return self._heap.is_empty() def enqueue(self, value): self._heap.insert(value) def dequeue(self): self._heap.extract_min() def __iter__(self): yield from iter(self._heap) def __len__(self): return len(self._heap)
class TestBinaryHeap(unittest.TestCase): def setUp(self): size = 8 self.random_list = random.sample(range(0, size), size) print "random list generated: " + str(self.random_list) self.heap = BinaryHeap(size) for key in self.random_list: if not self.heap.is_full(): self.heap.insert(key) def tearDown(self): pass def test_delete_min(self): order_list = sorted(self.random_list) index = 0 while not self.heap.is_empty(): min_value = self.heap.delete_min() print min_value self.assertEqual(min_value, order_list[index]) index += 1
class Astar: def __init__(self, initial_state, heuristic, weight=1): self.expansions = 0 self.generated = 0 self.initial_state = initial_state self.heuristic = heuristic self.weight = weight def estimate_suboptimality(self, result): costo = result.g mini = 1000000000 for n in self.open: f = n.h + n.g if f < mini: mini = f return costo / mini print(self.open) return 0 # este método debe ser implementado en la parte 1 def fvalue(self, g, h): return ( g + self.weight * h, h ) #Esto nos permite seleccionar primero los que tienen menor h si g+h spn iguales def search(self): self.start_time = time.process_time() self.open = BinaryHeap() self.expansions = 0 initial_node = Node(self.initial_state) initial_node.g = 0 initial_node.h = self.heuristic(self.initial_state) initial_node.key = self.fvalue(0, initial_node.h) # asignamos el valor f self.open.insert(initial_node) # para cada estado alguna vez generado, generated almacena # el Node que le corresponde self.generated = {} self.generated[self.initial_state] = initial_node while not self.open.is_empty(): n = self.open.extract() # extrae n de la open if n.state.is_goal(): self.end_time = time.process_time() return n succ = n.state.successors() self.expansions += 1 for child_state, action, cost in succ: child_node = self.generated.get(child_state) is_new = child_node is None # es la primera vez que veo a child_state path_cost = n.g + cost # costo del camino encontrado hasta child_state if is_new or path_cost < child_node.g: # si vemos el estado child_state por primera vez o lo vemos por # un mejor camino, entonces lo agregamos a open if is_new: # creamos el nodo de child_state child_node = Node(child_state, n) child_node.h = self.heuristic(child_state) self.generated[child_state] = child_node child_node.action = action child_node.parent = n child_node.g = path_cost child_node.key = self.fvalue( child_node.g, child_node.h) # actualizamos el valor f de child_node self.open.insert( child_node ) # inserta child_node a la open si no esta en la open self.end_time = time.process_time( ) # en caso contrario, modifica la posicion de child_node en open return None
class Ara: def __init__(self, initial_state, heuristic, weight, max_expansions): self.expansions = 0 self.generated = 0 self.initial_state = initial_state self.heuristic = heuristic self.weight = weight self.open = None self.cost = None self.max_expansions = max_expansions self.last_solution = None def estimate_suboptimality(self): cost = self.cost denominator = min(self.open, key=lambda x: x.g + x.h) denominator_num = denominator.h + denominator.g return cost / denominator_num def fvalue(self, g, h): return g + self.weight * h def adjust_weight(self): denominator = min(self.open, key=lambda x: x.g + x.h) denominator_num = denominator.h + denominator.g self.weight = self.last_solution.g / denominator_num def recalculate_open(self): for i in self.open: i.key = self.fvalue(i.g, i.h) self.open.reorder() def search(self): self.start_time = time.process_time() self.open = BinaryHeap() self.expansions = 0 initial_node = Node(self.initial_state) initial_node.g = 0 initial_node.h = self.heuristic(self.initial_state) initial_node.key = self.fvalue(0, initial_node.h) # asignamos el valor f self.open.insert(initial_node) self.generated = {} self.generated[self.initial_state] = initial_node while self.expansions <= self.max_expansions: while not self.open.is_empty(): if self.expansions >= self.max_expansions: return self.last_solution n = self.open.extract() if not self.open.is_empty() and self.open.top().key == n.key: tied_node = self.open.top() if tied_node.g < n.g: tied_node = self.open.extract() self.open.insert(n) n = tied_node if n.state.is_goal(): self.end_time = time.process_time() self.cost = n.g self.last_solution = n self.adjust_weight() self.recalculate_open() #print('aaa') yield n if not (self.last_solution is not None and n.g + n.h >= self.last_solution.g): succ = n.state.successors() self.expansions += 1 if self.expansions >= self.max_expansions: return self.last_solution for child_state, action, cost in succ: child_node = self.generated.get(child_state) is_new = child_node is None path_cost = n.g + cost if is_new or path_cost < child_node.g: if is_new: child_node = Node(child_state, n) child_node.h = self.heuristic(child_state) self.generated[child_state] = child_node child_node.action = action child_node.parent = n child_node.g = path_cost child_node.key = self.fvalue( child_node.g, child_node.h) self.open.insert(child_node) self.end_time = time.process_time() if self.open.is_empty(): #print("empty open") return self.last_solution #return None return self.last_solution