class_docstr: A powerful adversarial attack that requires neither gradients
  nor probabilities.
  
  This is the reference implementation for the attack. [#Bren18]_
  
  Notes:
      Differences to the original reference implementation:
      * We do not perform internal operations with float64
      * The samples within a batch can currently influence each other a bit
      * We don't perform the additional convergence confirmation
      * The success rate tracking changed a bit
      * Some other changes due to batching and merged loops
  
  Args:
      init_attack : Attack to use to find a starting points. Defaults to
          LinearSearchBlendedUniformNoiseAttack. Only used if starting_points is None.
      steps : Maximum number of steps to run. Might converge and stop before that.
      spherical_step : Initial step size for the orthogonal (spherical) step.
      source_step : Initial step size for the step towards the target.
      source_step_convergance : Sets the threshold of the stop criterion:
          if source_step becomes smaller than this value during the attack,
          the attack has converged and will stop.
      step_adaptation : Factor by which the step sizes are multiplied or divided.
      tensorboard : The log directory for TensorBoard summaries. If False, TensorBoard
          summaries will be disabled (default). If None, the logdir will be
          runs/CURRENT_DATETIME_HOSTNAME.
      update_stats_every_k :
  
  References:
      .. [#Bren18] Wieland Brendel (*), Jonas Rauber (*), Matthias Bethge,
         "Decision-Based Adversarial Attacks: Reliable Attacks
         Against Black-Box Machine Learning Models",
         https://arxiv.org/abs/1712.04248
code: def __init__(
      self,
      init_attack: Optional[MinimizationAttack] = None,
      steps: int = 25000,
      spherical_step: float = 1e-2,
      source_step: float = 1e-2,
      source_step_convergance: float = 1e-7,
      step_adaptation: float = 1.5,
      tensorboard: Union[Literal[False], None, str] = False,
      update_stats_every_k: int = 10,
  ):
      if init_attack is not None and not isinstance(
          init_attack, MinimizationAttack
      ):
          raise NotImplementedError
      self.init_attack = init_attack
      self.steps = steps
      self.spherical_step = spherical_step
      self.source_step = source_step
      self.source_step_convergance = source_step_convergance
      self.step_adaptation = step_adaptation
      self.tensorboard = tensorboard
      self.update_stats_every_k = update_stats_every_k
  
imports: from typing import Union, Tuple, Optional, Any
  from typing_extensions import Literal
  import numpy
  import eagerpy
  import logging
  from ..devutils import flatten
  from ..devutils import atleast_kd
  from ..types import Bounds
  from ..models import Model
  from ..criteria import Criterion
  from ..distances import l2
  from ..tensorboard import TensorBoard
  from .blended_noise import LinearSearchBlendedUniformNoiseAttack
  from .base import MinimizationAttack
  from .base import T
  from .base import get_criterion
  from .base import get_is_adversarial
  from .base import raise_if_kwargs
  from .base import verify_input_bounds
label_desc: Use image node_id 1 to create a new BoundaryAttack object from inherited base classes: MinimizationAttack with example: obj = BoundaryAttack(init_attack, steps, spherical_step, source_step, source_step_convergance, step_adaptation, tensorboard, update_stats_every_k)