code: 
  
  
  
  
  
  
  import math
  
  
  
  
  
  class     __a						:
  
  
  
  
  
  
  
   def __init__(	self      :     List[str]							,     SCREAMING_SNAKE_CASE      :     int							,     SCREAMING_SNAKE_CASE      :     int							,     SCREAMING_SNAKE_CASE      :     int							,     SCREAMING_SNAKE_CASE      :     int		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        UpperCamelCase__    :     int        =						x
        UpperCamelCase__    :     int        =						y
        UpperCamelCase__    :     int        =						step_size
        UpperCamelCase__    :     List[Any]        =						function_to_optimize
  
  
  
  
  
  
  
   def       __lowercase      (	self      :     int		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        return self.function(self.x							,     self.y		)
  
  
  
  
  
  
  
   def       __lowercase      (	self      :     Dict		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        UpperCamelCase__    :     Dict        =						self.step_size
        return [
            SearchProblem(SCREAMING_SNAKE_CASE							,     SCREAMING_SNAKE_CASE							,     SCREAMING_SNAKE_CASE							,     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      :     List[str]		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        return hash(str(self		)		)
  
  
  
  
  
  
  
   def __eq__(	self      :     Tuple							,     SCREAMING_SNAKE_CASE      :     Any		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        if isinstance(SCREAMING_SNAKE_CASE							,     SCREAMING_SNAKE_CASE		):
             return hash(str(self		)		) == hash(str(SCREAMING_SNAKE_CASE		)		)
        return False
  
  
  
  
  
  
  
   def __str__(	self      :     Optional[int]		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        return F'x: {self.x} y: {self.y}'
  
  
  
  
  
  
  
  def 	SCREAMING_SNAKE_CASE							(      __lowerCAmelCase      ,					__lowerCAmelCase = True      ,					__lowerCAmelCase = math.inf      ,					__lowerCAmelCase = -math.inf      ,					__lowerCAmelCase = math.inf      ,					__lowerCAmelCase = -math.inf      ,					__lowerCAmelCase = False      ,					__lowerCAmelCase = 1_0000      ,					)				->			SearchProblem:
       UpperCamelCase__    :     List[Any]        =						search_prob
       UpperCamelCase__    :     List[Any]        =						[]  # list to store the current score at each iteration
       UpperCamelCase__    :     Optional[int]        =						0
       UpperCamelCase__    :     Union[str, Any]        =						False
       UpperCamelCase__    :     Optional[Any]        =						set()
       while not solution_found and iterations < max_iter:
            visited.add(__lowerCAmelCase    )
            iterations += 1
            UpperCamelCase__    :     Dict        =						current_state.score()
            scores.append(__lowerCAmelCase    )
            UpperCamelCase__    :     Optional[Any]        =						current_state.get_neighbors()
            UpperCamelCase__    :     str        =						-math.inf
            UpperCamelCase__    :     Any        =						math.inf
            UpperCamelCase__    :     Optional[Any]        =						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
                 UpperCamelCase__    :     Tuple        =						neighbor.score() - current_score
                 if find_max:  # finding max
                      # going to direction with greatest ascent
                      if change > max_change and change > 0:
                           UpperCamelCase__    :     Union[str, Any]        =						change
                           UpperCamelCase__    :     int        =						neighbor
                 else:  # finding min
                      # to direction with greatest descent
                      if change < min_change and change < 0:
                           UpperCamelCase__    :     List[Any]        =						change
                           UpperCamelCase__    :     Any        =						neighbor
            if next_state is not None:
                 # we found at least one neighbor which improved the current state
                 UpperCamelCase__    :     Tuple        =						next_state
            else:
                 # since we have no neighbor that improves the solution we stop the search
                 UpperCamelCase__    :     Tuple        =						True
  
       if visualization:
            from matplotlib import pyplot as plt
  
            plt.plot(range(__lowerCAmelCase    )      ,					__lowerCAmelCase    )
            plt.xlabel("Iterations"    )
            plt.ylabel("Function values"    )
            plt.show()
  
       return current_state
  
  
  if __name__ == "__main__":
   import doctest
  
   doctest.testmod()
  
  
  
  
  
  
  
   def 	SCREAMING_SNAKE_CASE							(      __lowerCAmelCase      ,					__lowerCAmelCase    )				->			Optional[Any]:
        return (x**2) + (y**2)
  
   # starting the problem with initial coordinates (3, 4)
   lowerCamelCase			:							List[str]       =SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_fa)
   lowerCamelCase			:							List[str]       =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			:							List[str]       =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 	SCREAMING_SNAKE_CASE							(      __lowerCAmelCase      ,					__lowerCAmelCase    )				->			Any:
        return (3 * x**2) - (6 * y)
  
   lowerCamelCase			:							Union[str, Any]       =SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_fa)
   lowerCamelCase			:							List[str]       =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: 
  
  
  
  
  
  
  from __future__ import annotations
  
  from collections.abc import Iterator
  from typing import Any
  
  
  
  
  
  class     __a						:
  
  
  
  
  
  
  
   def __init__(	self      :     str							,     SCREAMING_SNAKE_CASE      :     Any		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        UpperCamelCase__    :     Any        =						data
        UpperCamelCase__    :     Node | None        =						None
  
  
  
  
  
  
  
   def __str__(	self      :     Union[str, Any]		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        return F'{self.data}'
  
  
  
  
  
  
  
  class     __a						:
  
  
  
  
  
  
  
   def __init__(	self      :     Optional[int]		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        UpperCamelCase__    :     Node | None        =						None
        UpperCamelCase__    :     Node | None        =						None
  
  
  
  
  
  
  
   def __iter__(	self      :     str		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        UpperCamelCase__    :     int        =						self.front
        while node:
             yield node.data
             UpperCamelCase__    :     Any        =						node.next
  
  
  
  
  
  
  
   def __len__(	self      :     Tuple		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        return len(tuple(iter(self		)		)		)
  
  
  
  
  
  
  
   def __str__(	self      :     Union[str, Any]		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        return " <- ".join(str(SCREAMING_SNAKE_CASE		) for item in self		)
  
  
  
  
  
  
  
   def       __lowercase      (	self      :     List[str]		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        return len(self		) == 0
  
  
  
  
  
  
  
   def       __lowercase      (	self      :     Union[str, Any]							,     SCREAMING_SNAKE_CASE      :     Any		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        UpperCamelCase__    :     int        =						Node(SCREAMING_SNAKE_CASE		)
        if self.is_empty():
             UpperCamelCase__    :     int        =						node
        else:
             assert isinstance(self.rear							,     SCREAMING_SNAKE_CASE		)
             UpperCamelCase__    :     Dict        =						node
             UpperCamelCase__    :     str        =						node
  
  
  
  
  
  
  
   def       __lowercase      (	self      :     Dict		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        if self.is_empty():
             raise IndexError("dequeue from empty queue"		)
        assert isinstance(self.front							,     SCREAMING_SNAKE_CASE		)
        UpperCamelCase__    :     Optional[int]        =						self.front
        UpperCamelCase__    :     List[str]        =						self.front.next
        if self.front is None:
             UpperCamelCase__    :     List[Any]        =						None
        return node.data
  
  
  
  
  
  
  
   def       __lowercase      (	self      :     str		):
  
  
        '''simple docstring'''
  
  
  
  
  
  
        UpperCamelCase__    :     Optional[int]        =						None
  
  
  if __name__ == "__main__":
   from doctest import testmod
  
   testmod()