class_docstr: The Projected Gradient Descent attack is an iterative method in which, after each iteration, the perturbation is
  projected on an lp-ball of specified radius (in addition to clipping the values of the adversarial sample so that it
  lies in the permitted data range). This is the attack proposed by Madry et al. for adversarial training.
  
  | Paper link: https://arxiv.org/abs/1706.06083
docstr: Generate adversarial samples and return them in an array.
  
  :param x: An array with the original inputs.
  :param y: Target values (class labels) one-hot-encoded of shape `(nb_samples, nb_classes)` or indices of shape
            (nb_samples,). Only provide this parameter if you'd like to use true labels when crafting adversarial
            samples. Otherwise, model predictions are used as labels to avoid the "label leaking" effect
            (explained in this paper: https://arxiv.org/abs/1611.01236). Default is `None`.
  
  :param mask: An array with a mask broadcastable to input `x` defining where to apply adversarial perturbations.
               Shape needs to be broadcastable to the shape of x and can also be of the same shape as `x`. Any
               features for which the mask is zero will not be adversarially perturbed.
  :type mask: `np.ndarray`
  :return: An array holding the adversarial examples.
docstr_tok: ["Generate","adversarial","samples","and","return","them","in","an","array",".",":","param","x",":","An","array","with","the","original","inputs",".",":","param","y",":","Target","values","(","class","labels",")","one-hot-encoded","of","shape","`","(","nb_samples",",","nb_classes",")","`","or","indices","of","shape","(","nb_samples",",",")",".","Only","provide","this","parameter","if","you","'d","like","to","use","true","labels","when","crafting","adversarial","samples",".","Otherwise",",","model","predictions","are","used","as","labels","to","avoid","the","``","label","leaking","''","effect","(","explained","in","this","paper",":","https",":","\/\/arxiv.org\/abs\/1611.01236",")",".","Default","is","`","None","`",".",":","param","mask",":","An","array","with","a","mask","broadcastable","to","input","`","x","`","defining","where","to","apply","adversarial","perturbations",".","Shape","needs","to","be","broadcastable","to","the","shape","of","x","and","can","also","be","of","the","same","shape","as","`","x","`",".","Any","features","for","which","the","mask","is","zero","will","not","be","adversarially","perturbed",".",":","type","mask",":","`","np.ndarray","`",":","return",":","An","array","holding","the","adversarial","examples","."]
code: def generate(
      self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs
  ) -> np.ndarray:
      """
      Generate adversarial samples and return them in an array.
  
      :param x: An array with the original inputs.
      :param y: Target values (class labels) one-hot-encoded of shape `(nb_samples, nb_classes)` or indices of shape
                (nb_samples,). Only provide this parameter if you'd like to use true labels when crafting adversarial
                samples. Otherwise, model predictions are used as labels to avoid the "label leaking" effect
                (explained in this paper: https://arxiv.org/abs/1611.01236). Default is `None`.
  
      :param mask: An array with a mask broadcastable to input `x` defining where to apply adversarial perturbations.
                   Shape needs to be broadcastable to the shape of x and can also be of the same shape as `x`. Any
                   features for which the mask is zero will not be adversarially perturbed.
      :type mask: `np.ndarray`
      :return: An array holding the adversarial examples.
      """
      mask = self._get_mask(x, **kwargs)
  
      # Ensure eps is broadcastable
      self._check_compatibility_input_and_eps(x=x)
  
      # Check whether random eps is enabled
      self._random_eps()
  
      if isinstance(self.estimator, ClassifierMixin):
          # Set up targets
          targets = self._set_targets(x, y)
  
          # Start to compute adversarial examples
          adv_x = x.astype(ART_NUMPY_DTYPE)
  
          for batch_id in range(
              int(np.ceil(x.shape[0] / float(self.batch_size)))
          ):
              self._batch_id = batch_id
  
              for rand_init_num in trange(
                  max(1, self.num_random_init),
                  desc="PGD - Random Initializations",
                  disable=not self.verbose,
              ):
                  batch_index_1, batch_index_2 = (
                      batch_id * self.batch_size,
                      (batch_id + 1) * self.batch_size,
                  )
                  batch_index_2 = min(batch_index_2, x.shape[0])
                  batch = x[batch_index_1:batch_index_2]
                  batch_labels = targets[batch_index_1:batch_index_2]
                  mask_batch = mask
  
                  if mask is not None:
                      if len(mask.shape) == len(x.shape):
                          mask_batch = mask[batch_index_1:batch_index_2]
  
                  momentum = np.zeros(batch.shape)
  
                  for i_max_iter in trange(
                      self.max_iter,
                      desc="PGD - Iterations",
                      leave=False,
                      disable=not self.verbose,
                  ):
                      self._i_max_iter = i_max_iter
  
                      batch = self._compute(
                          batch,
                          x[batch_index_1:batch_index_2],
                          batch_labels,
                          mask_batch,
                          self.eps,
                          self.eps_step,
                          self._project,
                          self.num_random_init > 0 and i_max_iter == 0,
                          self._batch_id,
                          decay=self.decay,
                          momentum=momentum,
                      )
  
                  if rand_init_num == 0:
                      # initial (and possibly only) random restart: we only have this set of
                      # adversarial examples for now
                      adv_x[batch_index_1:batch_index_2] = np.copy(
                          batch
                      )
                  else:
                      # replace adversarial examples if they are successful
                      attack_success = compute_success_array(
                          self.estimator,  # type: ignore
                          x[batch_index_1:batch_index_2],
                          targets[batch_index_1:batch_index_2],
                          batch,
                          self.targeted,
                          batch_size=self.batch_size,
                      )
                      adv_x[batch_index_1:batch_index_2][
                          attack_success
                      ] = batch[attack_success]
  
          logger.info(
              "Success rate of attack: %.2f%%",
              100
              * compute_success(
                  self.estimator,  # type: ignore
                  x,
                  targets,
                  adv_x,
                  self.targeted,
                  batch_size=self.batch_size,  # type: ignore
              ),
          )
      else:
          if self.num_random_init > 0:  # pragma: no cover
              raise ValueError(
                  "Random initialisation is only supported for classification."
              )
  
          # Set up targets
          targets = self._set_targets(x, y, classifier_mixin=False)
  
          # Start to compute adversarial examples
          if x.dtype == object:
              adv_x = x.copy()
          else:
              adv_x = x.astype(ART_NUMPY_DTYPE)
  
          momentum = np.zeros(adv_x.shape)
  
          for i_max_iter in trange(
              self.max_iter,
              desc="PGD - Iterations",
              disable=not self.verbose,
          ):
              self._i_max_iter = i_max_iter
  
              adv_x = self._compute(
                  adv_x,
                  x,
                  targets,
                  mask,
                  self.eps,
                  self.eps_step,
                  self._project,
                  self.num_random_init > 0 and i_max_iter == 0,
                  decay=self.decay,
                  momentum=momentum,
              )
  
      if self.summary_writer is not None:
          self.summary_writer.reset()
  
      return adv_x
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, Union, TYPE_CHECKING
  import numpy
  from scipy.stats import truncnorm
  from tqdm.auto import trange
  from art.attacks.evasion.fast_gradient import FastGradientMethod
  from art.config import ART_NUMPY_DTYPE
  from art.estimators.classification.classifier import ClassifierMixin
  from art.estimators.estimator import BaseEstimator, LossGradientsMixin
  from art.utils import compute_success, get_labels_np_array, check_and_transform_label_format, compute_success_array
  from art.summary_writer import SummaryWriter
label_desc: Use image node_id 2 for calling the ProjectedGradientDescentNumpy obj's underlying member method code with example usage: obj.generate(x, y) and returns: adv_x