class_docstr: Implementation of the boundary attack from Brendel et al. (2018). This is a powerful black-box attack that
  only requires final class prediction.
  
  | Paper link: https://arxiv.org/abs/1712.04248
class_docstr_tok: ["Implementation","of","the","boundary","attack","from","Brendel","et","al",".","(","2018",")",".","This","is","a","powerful","black-box","attack","that","only","requires","final","class","prediction",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1712.04248"]
docstr: Main function for the boundary attack.
  
  :param initial_sample: An initial adversarial example.
  :param original_sample: The original input.
  :param y_p: The predicted label of the original input.
  :param target: The target label.
  :param initial_delta: Initial step size for the orthogonal step.
  :param initial_epsilon: Initial step size for the step towards the target.
  :param clip_min: Minimum value of an example.
  :param clip_max: Maximum value of an example.
  :return: an adversarial example.
docstr_tok: ["Main","function","for","the","boundary","attack",".",":","param","initial_sample",":","An","initial","adversarial","example",".",":","param","original_sample",":","The","original","input",".",":","param","y_p",":","The","predicted","label","of","the","original","input",".",":","param","target",":","The","target","label",".",":","param","initial_delta",":","Initial","step","size","for","the","orthogonal","step",".",":","param","initial_epsilon",":","Initial","step","size","for","the","step","towards","the","target",".",":","param","clip_min",":","Minimum","value","of","an","example",".",":","param","clip_max",":","Maximum","value","of","an","example",".",":","return",":","an","adversarial","example","."]
code: def _attack(
      self,
      initial_sample: np.ndarray,
      original_sample: np.ndarray,
      y_p: int,
      target: int,
      initial_delta: float,
      initial_epsilon: float,
      clip_min: float,
      clip_max: float,
  ) -> np.ndarray:
      """
      Main function for the boundary attack.
  
      :param initial_sample: An initial adversarial example.
      :param original_sample: The original input.
      :param y_p: The predicted label of the original input.
      :param target: The target label.
      :param initial_delta: Initial step size for the orthogonal step.
      :param initial_epsilon: Initial step size for the step towards the target.
      :param clip_min: Minimum value of an example.
      :param clip_max: Maximum value of an example.
      :return: an adversarial example.
      """
      # Get initialization for some variables
      x_adv = initial_sample
      self.curr_delta = initial_delta
      self.curr_epsilon = initial_epsilon
  
      self.curr_adv = x_adv
  
      # Main loop to wander around the boundary
      for _ in trange(
          self.max_iter,
          desc="Boundary attack - iterations",
          disable=not self.verbose,
      ):
          # Trust region method to adjust delta
          for _ in range(self.num_trial):
              potential_advs_list: List[np.ndarray] = []
              for _ in range(self.sample_size):
                  potential_adv = x_adv + self._orthogonal_perturb(
                      self.curr_delta, x_adv, original_sample
                  )
                  potential_adv = np.clip(
                      potential_adv, clip_min, clip_max
                  )
                  potential_advs_list.append(potential_adv)
  
              preds = np.argmax(
                  self.estimator.predict(
                      np.array(potential_advs_list),
                      batch_size=self.batch_size,
                  ),
                  axis=1,
              )
  
              if self.targeted:
                  satisfied = preds == target
              else:
                  satisfied = preds != y_p
  
              delta_ratio = np.mean(satisfied)
  
              if delta_ratio < 0.2:
                  self.curr_delta *= self.step_adapt
              elif delta_ratio > 0.5:
                  self.curr_delta /= self.step_adapt
  
              if delta_ratio > 0:
                  x_advs = np.array(potential_advs_list)[
                      np.where(satisfied)[0]
                  ]
                  break
          else:  # pragma: no cover
              logger.warning(
                  "Adversarial example found but not optimal."
              )
              return x_adv
  
          # Trust region method to adjust epsilon
          for _ in range(self.num_trial):
              perturb = (
                  np.repeat(
                      np.array([original_sample]), len(x_advs), axis=0
                  )
                  - x_advs
              )
              perturb *= self.curr_epsilon
              potential_advs = x_advs + perturb
              potential_advs = np.clip(
                  potential_advs, clip_min, clip_max
              )
              preds = np.argmax(
                  self.estimator.predict(
                      potential_advs, batch_size=self.batch_size
                  ),
                  axis=1,
              )
  
              if self.targeted:
                  satisfied = preds == target
              else:
                  satisfied = preds != y_p
  
              epsilon_ratio = np.mean(satisfied)
  
              if epsilon_ratio < 0.2:
                  self.curr_epsilon *= self.step_adapt
              elif epsilon_ratio > 0.5:
                  self.curr_epsilon /= self.step_adapt
  
              if epsilon_ratio > 0:
                  x_adv = self._best_adv(
                      original_sample,
                      potential_advs[np.where(satisfied)[0]],
                  )
                  self.curr_adv = x_adv
                  break
          else:  # pragma: no cover
              logger.warning(
                  "Adversarial example found but not optimal."
              )
              return self._best_adv(original_sample, x_advs)
  
          if self.curr_epsilon < self.min_epsilon:
              return x_adv
  
      return x_adv
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import List, Optional, Tuple, TYPE_CHECKING
  import numpy
  from tqdm.auto import tqdm, 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 compute_success, to_categorical, check_and_transform_label_format, get_labels_np_array
label_desc: Use image node_id 4 for calling the BoundaryAttack obj's underlying member method code with example usage: obj._attack(initial_sample, original_sample, y_p, target, initial_delta, initial_epsilon, clip_min, clip_max) and returns: x_adv, x_adv, self, x_adv