code: def a_star_algorithm(self, start_node: Node, stop_node: Node):
      # TODO store the graph as an attribute
      # open_list is a list of nodes which have been visited, but who's neighbors
      # haven't all been inspected, starts off with the start node
      # closed_list is a list of nodes which have been visited
      # and who's neighbors have been inspected
      open_list = set([start_node])
      closed_list = set([])
  
      # g contains current distances from start_node to all other nodes
      # the default value (if it's not found in the map) is +infinity
      g = {}
  
      g[start_node] = 0
  
      # parents contains an adjacency map of all nodes
      parents = {}
      parents[start_node] = start_node
  
      while len(open_list) > 0:
          print(f"The open list is {open_list}")
          n = None
  
          # find a node with the lowest value of f() - evaluation function
          for v in open_list:
              # TODO if v == decoder, run the decoder
              print(f"The for loop node v is {v}")
              if n is None or g[v] + self.h(v) < g[n] + self.h(n):
                  n = v
                  print(f"The value of n is {n}")
  
          if n is None:
              print("Path does not exist!")
              return None
  
          # if the current node is the stop_node
          # then we begin reconstructin the path from it to the start_node
          # NOTE Uncomment this for an exit condition
          # TODO Make it exit if decrypter returns True
          # TODO We need to append the decryption methods to each node
          # So when we reconstruct the path we can reconstruct the decryptions
          # used
          if n == stop_node:
              print("n is the stop node, we are stopping!")
              reconst_path = []
  
              while parents[n] != n:
                  reconst_path.append(n)
                  n = parents[n]
  
              reconst_path.append(start_node)
  
              reconst_path.reverse()
  
              print("Path found: {}".format(reconst_path))
              return reconst_path
  
          print(n)
          for m, weight in self.get_neighbors(n):
              print(f"And the iteration is ({m}, {weight})")
              # if the current node isn't in both open_list and closed_list
              # add it to open_list and note n as it's parent
              if m not in open_list and m not in closed_list:
                  open_list.add(m)
                  parents[m] = n
                  g[m] = g[n] + weight
  
              # otherwise, check if it's quicker to first visit n, then m
              # and if it is, update parent data and g data
              # and if the node was in the closed_list, move it to open_list
              else:
                  if g[m] > g[n] + weight:
                      g[m] = g[n] + weight
                      parents[m] = n
  
                      if m in closed_list:
                          closed_list.remove(m)
                          open_list.add(m)
  
          # remove n from the open_list, and add it to closed_list
          # because all of his neighbors were inspected
          # open_list.remove(node)
          # closed_list.add(node)
  
          open_list.remove(n)
          closed_list.add(n)
          print("\n")
  
      print("Path does not exist!")
      return None
  
file_path: Ciphey/ciphey/basemods/Searchers/astar.py
imports: import cipheycore
label_desc: Use image node_id 4 for calling the Graph obj's underlying member method code with example usage: obj.a_star_algorithm(start_node, stop_node) and returns: None, None, reconst_path