class_docstr: Grid search tuner divides search space into evenly spaced grid, and performs brute-force traverse.
  
  Recommended when the search space is small, or if you want to find strictly optimal hyperparameters.
  
  **Implementation**
  
  The original grid search approach performs an exhaustive search through a space consists of ``choice`` and ``randint``.
  
  NNI's implementation extends grid search to support all search spaces types.
  
  When the search space contains continuous parameters like ``normal`` and ``loguniform``,
  grid search tuner works in following steps:
  
  1. Divide the search space into a grid.
  2. Perform an exhaustive searth through the grid.
  3. Subdivide the grid into a finer-grained new grid.
  4. Goto step 2, until experiment end.
  
  As a deterministic algorithm, grid search has no argument.
  
  Examples
  --------
  
  .. code-block::
  
      config.tuner.name = 'GridSearch'
code: def _suggest(self):
      # returns next parameter set, or None if the space is already fully explored
      while True:
          if self.grid is None:  # search space fully explored
              return None
  
          self._next_vector()
  
          if self.vector is None:  # epoch end, update grid and retry
              self._next_grid()
              continue
  
          old = all(
              (self.vector[i] < self.epoch_bar[i])
              for i in range(len(self.space))
          )
          if old:  # already explored in past epochs
              continue
  
          # this vector is valid, stop
          _logger.debug(f"vector: {self.vector}")
          return self._current_parameters()
  
imports: import logging
  import math
  import numpy
  from scipy.special import erfinv
  import nni
  from nni.common.hpo_utils import ParameterSpec, deformat_parameters, format_search_space
  from nni.tuner import Tuner
label_desc: Use image node_id 6 for calling the GridSearchTuner obj's underlying member method code with example usage: obj._suggest() and returns: self, None