code: def bandit_attack(
      x,
      loss_fn,
      order,
      projector,
      delta_init=None,
      prior_init=None,
      fd_eta=0.01,
      exploration=0.01,
      online_lr=0.1,
      nb_iter=40,
      eps_iter=0.01,
  ):
      """
      Performs the BanditAttack
      Paper: https://arxiv.org/pdf/1807.07978.pdf
  
      :param x: input data.
      :param loss_fn: loss function.
      :param eps: maximum distortion.
      :param order: (optional) the order of maximum distortion (2 or inf).
      :param projector: function to project the perturbation into the eps-ball
          - must accept tensors of shape [nbatch, pop_size, ndim]
      :param delta_init: (default None)
      :param prior_init: (default None)
      :param fd_eta: step-size used for fd grad estimate (default 0.01)
      :param exploration: scales the exploration around prior (default 0.01)
      :param online_lr: learning rate for the prior (default 0.1)
      :param nb_iter: number of iterations (default 40)
      :param eps_iter: attack step size (default 0.01)
  
      :return: tuple of tensors containing (1) the adv example, (2) the prior
      """
      ndim = np.prod(list(x.shape[1:]))
  
      if delta_init is None:
          adv = x.clone()
      else:
          adv = x + delta_init
  
      if prior_init is None:
          prior = torch.zeros_like(x)
      else:
          prior = prior_init.clone()
  
      for t in range(nb_iter):
          # before: # [nbatch, ndim, nsamples]
          # now: # [nbatch, ndim]
          exp_noise = (
              exploration * torch.randn_like(prior) / (ndim**0.5)
          )
  
          # Query deltas for finite difference estimator
          q1 = F.normalize(prior + exp_noise, dim=-1)
          q2 = F.normalize(prior - exp_noise, dim=-1)
          # Loss points for finite difference estimator
          L1 = loss_fn(adv + fd_eta * q1)  # L(prior + c*noise)
          L2 = loss_fn(adv + fd_eta * q2)  # L(prior - c*noise)
  
          delta_L = (L1 - L2) / (fd_eta * exploration)  # [nbatch]
  
          grad_est = delta_L[:, None] * exp_noise
          if order == 2:
              # update prior
              prior = prior + online_lr * grad_est
              # make step with prior
              # note the (+): this indicates gradient ascent on the loss
              adv = adv + eps_iter * F.normalize(prior, dim=-1)
              # project
              delta = adv - x
              delta = projector(delta[:, None, :]).squeeze(1)
          elif order == inf:
              # update prior (exponentiated gradients)
              prior = (prior + 1) / 2  # from [-1, 1] to [0, 1]
              pos = prior * torch.exp(online_lr * grad_est)
              neg = (1 - prior) * torch.exp(-online_lr * grad_est)
              prior = 2 * pos / (pos + neg) - 1
              # make step with prior
              adv = adv + eps_iter * torch.sign(prior)
              # project
              delta = adv - x
              delta = projector(delta[:, None, :]).squeeze(1)
          else:
              error = "Only order=inf, order=2 have been implemented"
              raise NotImplementedError(error)
  
          adv = x + delta
  
      return adv, prior
  
file_path: advertorch/advertorch/attacks/blackbox/bandits.py
imports: import warnings
  from math import inf
  from typing import Optional
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from advertorch.attacks.base import Attack
  from advertorch.attacks.base import LabelMixin
  from .utils import _check_param, _flatten, _make_projector
label_desc: Use image node_id 1 for calling a global function with example usage: bandit_attack(x, loss_fn, order, projector, delta_init, prior_init, fd_eta, exploration, online_lr, nb_iter, eps_iter) and returns: adv,  prior