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: Create an orthogonal perturbation.
  
  :param delta: Initial step size for the orthogonal step.
  :param current_sample: Current adversarial example.
  :param original_sample: The original input.
  :return: a possible perturbation.
docstr_tok: ["Create","an","orthogonal","perturbation",".",":","param","delta",":","Initial","step","size","for","the","orthogonal","step",".",":","param","current_sample",":","Current","adversarial","example",".",":","param","original_sample",":","The","original","input",".",":","return",":","a","possible","perturbation","."]
code: def _orthogonal_perturb(
      self,
      delta: float,
      current_sample: np.ndarray,
      original_sample: np.ndarray,
  ) -> np.ndarray:
      """
      Create an orthogonal perturbation.
  
      :param delta: Initial step size for the orthogonal step.
      :param current_sample: Current adversarial example.
      :param original_sample: The original input.
      :return: a possible perturbation.
      """
      # Generate perturbation randomly
      perturb = np.random.randn(*self.estimator.input_shape).astype(
          ART_NUMPY_DTYPE
      )
  
      # Rescale the perturbation
      perturb /= np.linalg.norm(perturb)
      perturb *= delta * np.linalg.norm(
          original_sample - current_sample
      )
  
      # Project the perturbation onto sphere
      direction = original_sample - current_sample
  
      direction_flat = direction.flatten()
      perturb_flat = perturb.flatten()
  
      direction_flat /= np.linalg.norm(direction_flat)
      perturb_flat -= (
          np.dot(perturb_flat, direction_flat.T) * direction_flat
      )
      perturb = perturb_flat.reshape(self.estimator.input_shape)
  
      hypotenuse = np.sqrt(1 + delta**2)
      perturb = (
          (1 - hypotenuse) * (current_sample - original_sample)
          + perturb
      ) / hypotenuse
      return perturb
  
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 5 for calling the BoundaryAttack obj's underlying member method code with example usage: obj._orthogonal_perturb(delta, current_sample, original_sample) and returns: perturb