docs: def hill_climbing_random_restarts(problem, restarts_limit, iterations_limit=0, viewer=None):
      '''
      Hill climbing with random restarts.
  
      restarts_limit specifies the number of times hill_climbing will be runned.
      If iterations_limit is specified, each hill_climbing will end after that
      number of iterations. Else, it will continue until it can't find a
      better node than the current one.
      Requires: SearchProblem.actions, SearchProblem.result, SearchProblem.value,
      and SearchProblem.generate_random_state.
      '''
      restarts = 0
      best = None
  
      while restarts < restarts_limit:
          new = _local_search(problem,
                              _first_expander,
                              iterations_limit=iterations_limit,
                              fringe_size=1,
                              random_initial_states=True,
                              stop_when_no_better=True,
                              viewer=viewer)
  
          if not best or best.value < new.value:
              best = new
  
          restarts += 1
  
      if viewer:
          viewer.event('no_more_runs', best, 'returned after %i runs' % restarts_limit)
  
      return best