code: def find_energy_minimum(self, energy, x, maxSteps=40000):
          r
          E = energy
          y = np.zeros(self.output_size) 
  
          min_so_far = E(x, y)
  
          for _ in range(maxSteps):
              neighbours       = self.get_neighbours(y)
              energies         = np.array([ E(x,z) for z in neighbours ])
              steepest_descent = np.argmin(energies)
  
              if energies[steepest_descent] < min_so_far:
                  y          = neighbours[steepest_descent]
                  min_so_far =   energies[steepest_descent]
              else:
                  break
  
          return y
docs: r"""
          Naive hill descend algorithm:
          Starts at $y=0$ and iteratively chooses the direction of steepest descent from 
          a neighbourhood of the current position. If not indicated otherwise the neighbourhood
          consists of elements at Hamming distance less than or equal to $1$.