code: 
  
  
  
  import math
  
  class      UpperCAmelCase_						:
  
  						'''simple docstring'''
  
  
  
  
  						def __init__(					self   ,							_A   ,							_A   ,							_A   ,							_A	):
  
  
  
  
  
  
  
  													'''simple docstring'''
  
  													__SCREAMING_SNAKE_CASE								=      x
  													__SCREAMING_SNAKE_CASE								=      y
  													__SCREAMING_SNAKE_CASE								=      step_size
  													__SCREAMING_SNAKE_CASE								=      function_to_optimize
  
  
  
  
  
  
  						def  _A			(					self	):
  
  
  
  
  
  
  
  													'''simple docstring'''
  
  													return self.function(self.x   ,							self.y	)
  
  
  
  
  
  
  						def  _A			(					self	):
  
  
  
  
  
  
  
  													'''simple docstring'''
  
  													__SCREAMING_SNAKE_CASE								=      self.step_size
  													return [
  													    SearchProblem(_A   ,							_A   ,							_A   ,							self.function	)
  													    for x, y in (
  													        (self.x - step_size, self.y - step_size),
  													        (self.x - step_size, self.y),
  													        (self.x - step_size, self.y + step_size),
  													        (self.x, self.y - step_size),
  													        (self.x, self.y + step_size),
  													        (self.x + step_size, self.y - step_size),
  													        (self.x + step_size, self.y),
  													        (self.x + step_size, self.y + step_size),
  													    )
  													]
  
  
  
  
  
  
  						def __hash__(					self	):
  
  
  
  
  
  
  
  													'''simple docstring'''
  
  													return hash(str(self	)	)
  
  
  
  
  
  
  						def __eq__(					self   ,							_A	):
  
  
  
  
  
  
  
  													'''simple docstring'''
  
  													if isinstance(_A   ,							_A	):
  																				return hash(str(self	)	) == hash(str(_A	)	)
  													return False
  
  
  
  
  
  
  						def __str__(					self	):
  
  
  
  
  
  
  
  													'''simple docstring'''
  
  													return f"""x: {self.x} y: {self.y}"""
  
  
  
  
  
  
  
  def 			__lowercase     (				a__							,     a__ = True							,     a__ = math.inf							,     a__ = -math.inf							,     a__ = math.inf							,     a__ = -math.inf							,     a__ = False							,     a__ = 1_00_00							,     )       ->				SearchProblem:
  							__SCREAMING_SNAKE_CASE								=      search_prob
  							__SCREAMING_SNAKE_CASE								=      []  # list to store the current score at each iteration
  							__SCREAMING_SNAKE_CASE								=      0
  							__SCREAMING_SNAKE_CASE								=      False
  							__SCREAMING_SNAKE_CASE								=      set()
  							while not solution_found and iterations < max_iter:
  														visited.add(a__     )
  														iterations += 1
  														__SCREAMING_SNAKE_CASE								=      current_state.score()
  														scores.append(a__     )
  														__SCREAMING_SNAKE_CASE								=      current_state.get_neighbors()
  														__SCREAMING_SNAKE_CASE								=      -math.inf
  														__SCREAMING_SNAKE_CASE								=      math.inf
  														__SCREAMING_SNAKE_CASE								=      None  # to hold the next best neighbor
  														for neighbor in neighbors:
  																					if neighbor in visited:
  																												continue  # do not want to visit the same state again
  																					if (
  																					    neighbor.x > max_x
  																					    or neighbor.x < min_x
  																					    or neighbor.y > max_y
  																					    or neighbor.y < min_y
  																					):
  																												continue  # neighbor outside our bounds
  																					__SCREAMING_SNAKE_CASE								=      neighbor.score() - current_score
  																					if find_max:  # finding max
  																												# going to direction with greatest ascent
  																												if change > max_change and change > 0:
  																																			__SCREAMING_SNAKE_CASE								=      change
  																																			__SCREAMING_SNAKE_CASE								=      neighbor
  																					else:  # finding min
  																												# to direction with greatest descent
  																												if change < min_change and change < 0:
  																																			__SCREAMING_SNAKE_CASE								=      change
  																																			__SCREAMING_SNAKE_CASE								=      neighbor
  														if next_state is not None:
  																					# we found at least one neighbor which improved the current state
  																					__SCREAMING_SNAKE_CASE								=      next_state
  														else:
  																					# since we have no neighbor that improves the solution we stop the search
  																					__SCREAMING_SNAKE_CASE								=      True
  
  							if visualization:
  														from matplotlib import pyplot as plt
  
  														plt.plot(range(a__     )							,     a__     )
  														plt.xlabel('Iterations'     )
  														plt.ylabel('Function values'     )
  														plt.show()
  
  							return current_state
  
  
  if __name__ == "__main__":
  			import doctest
  
  			doctest.testmod()
  
  
  
  
  
  
  			def 			__lowercase     (				a__							,     a__     )       ->				str:
  										return (x**2) + (y**2)
  
  			# starting the problem with initial coordinates (3, 4)
  			lowerCAmelCase__	:  Union[str, Any] 		=SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_fa)
  			lowerCAmelCase__	:  Dict 		=hill_climbing(prob, find_max=False)
  			print(
  			    '''The minimum score for f(x, y) = x^2 + y^2 found via hill climbing: '''
  			    F'''{local_min.score()}'''
  			)
  
  			# starting the problem with initial coordinates (12, 47)
  			lowerCAmelCase__	:  Tuple 		=SearchProblem(x=12, y=47, step_size=1, function_to_optimize=test_fa)
  			lowerCAmelCase__	:  Optional[int] 		=hill_climbing(
  			    prob, find_max=False, max_x=100, min_x=5, max_y=50, min_y=-5, visualization=True
  			)
  			print(
  			    '''The minimum score for f(x, y) = x^2 + y^2 with the domain 100 > x > 5 '''
  			    F'''and 50 > y > - 5 found via hill climbing: {local_min.score()}'''
  			)
  
  
  
  
  
  
  			def 			__lowercase     (				a__							,     a__     )       ->				int:
  										return (3 * x**2) - (6 * y)
  
  			lowerCAmelCase__	:  Any 		=SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_fa)
  			lowerCAmelCase__	:  Dict 		=hill_climbing(prob, find_max=True)
  
  			print(
  			    '''The maximum score for f(x, y) = x^2 + y^2 found via hill climbing: '''
  			    F'''{local_min.score()}'''
  			)
  
  
  
  
  
  
  
style_context: 
  
  
  
  def 			__lowercase     (				a__     )       ->				int:
  							return int(a__     ) if x - int(a__     ) <= 0 else int(a__     ) + 1
  
  
  if __name__ == "__main__":
  			import doctest
  
  			doctest.testmod()
  
  
  
  
  
  
  