class_docstr: Implementation of the Geometric Decision-based Attack (GeoDA), a black-box attack requiring class predictions.
  Based on reference implementation: https://github.com/thisisalirah/GeoDA
  
  | Paper link: https://arxiv.org/abs/2003.06468
class_docstr_tok: ["Implementation","of","the","Geometric","Decision-based","Attack","(","GeoDA",")",",","a","black-box","attack","requiring","class","predictions",".","Based","on","reference","implementation",":","https",":","\/\/github.com\/thisisalirah\/GeoDA","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/2003.06468"]
docstr: Move towards decision boundary.
  
  :param x: Current example to be moved towards the decision boundary.
  :param y: The true label.
  :param grad: Gradient towards decision boundary.
  :return: Example moved towards decision boundary.
docstr_tok: ["Move","towards","decision","boundary",".",":","param","x",":","Current","example","to","be","moved","towards","the","decision","boundary",".",":","param","y",":","The","true","label",".",":","param","grad",":","Gradient","towards","decision","boundary",".",":","return",":","Example","moved","towards","decision","boundary","."]
code: def _go_to_boundary(
      self, x: np.ndarray, y: np.ndarray, grad: np.ndarray
  ) -> np.ndarray:
      """
      Move towards decision boundary.
  
      :param x: Current example to be moved towards the decision boundary.
      :param y: The true label.
      :param grad: Gradient towards decision boundary.
      :return: Example moved towards decision boundary.
      """
      epsilon = 5
      nb_calls = 0
      x_perturbed = x
  
      if self.norm in [np.inf, "inf"]:
          grads = np.sign(grad) / np.linalg.norm(grad.flatten(), ord=2)
      else:
          grads = grad  # self.norm in [1, 2]
  
      while not self._is_adversarial(x_perturbed, y):
          nb_calls += 1
          if nb_calls > 100:
              logger.info(
                  "Moving towards decision boundary failed because of too many iterations."
              )
              break
  
          x_perturbed = x + (nb_calls * epsilon * grads[0])
          x_perturbed = np.clip(
              x_perturbed, a_min=self.clip_min, a_max=self.clip_max
          )
  
      self.nb_calls += nb_calls
  
      return x_perturbed
  
imports: import os
  import math
  import logging
  from typing import List, Optional, Tuple, Union, TYPE_CHECKING
  import numpy
  from tqdm.auto import trange
  from art.attacks.attack import EvasionAttack
  from art.config import ART_NUMPY_DTYPE
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification.classifier import ClassifierMixin
  from art.utils import check_and_transform_label_format, get_labels_np_array
label_desc: Use image node_id 9 for calling the GeoDA obj's underlying member method code with example usage: obj._go_to_boundary(x, y, grad) and returns: x_perturbed