class_docstr: Implementation of the Jacobian-based Saliency Map Attack (Papernot et al. 2016).
  
  | Paper link: https://arxiv.org/abs/1511.07528
class_docstr_tok: ["Implementation","of","the","Jacobian-based","Saliency","Map","Attack","(","Papernot","et","al",".","2016",")",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1511.07528"]
docstr: Generate adversarial samples and return them in an array.
  
  :param x: An array with the original inputs to be attacked.
  :param y: Target values (class labels) one-hot-encoded of shape `(nb_samples, nb_classes)` or indices of shape
            `(nb_samples,)`.
  :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","to","be","attacked",".",":","param","y",":","Target","values","(","class","labels",")","one-hot-encoded","of","shape","`","(","nb_samples",",","nb_classes",")","`","or","indices","of","shape","`","(","nb_samples",",",")","`",".",":","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 to be attacked.
      :param y: Target values (class labels) one-hot-encoded of shape `(nb_samples, nb_classes)` or indices of shape
                `(nb_samples,)`.
      :return: An array holding the adversarial examples.
      """
      if y is not None:
          y = check_and_transform_label_format(
              y, nb_classes=self.estimator.nb_classes
          )
  
      # Initialize variables
      dims = list(x.shape[1:])
      self._nb_features = np.product(dims)
      x_adv = np.reshape(
          x.astype(ART_NUMPY_DTYPE), (-1, self._nb_features)
      )
      preds = np.argmax(
          self.estimator.predict(x, batch_size=self.batch_size), axis=1
      )
  
      # Determine target classes for attack
      if y is None:
          # Randomly choose target from the incorrect classes for each sample
          from art.utils import random_targets
  
          targets = np.argmax(
              random_targets(preds, self.estimator.nb_classes), axis=1
          )
      else:
          if (
              self.estimator.nb_classes == 2 and y.shape[1] == 1
          ):  # pragma: no cover
              raise ValueError(
                  "This attack has not yet been tested for binary classification with a single output classifier."
              )
  
          targets = np.argmax(y, axis=1)
  
      # Compute perturbation with implicit batching
      for batch_id in trange(
          int(np.ceil(x_adv.shape[0] / float(self.batch_size))),
          desc="JSMA",
          disable=not self.verbose,
      ):
          batch_index_1, batch_index_2 = (
              batch_id * self.batch_size,
              (batch_id + 1) * self.batch_size,
          )
          batch = x_adv[batch_index_1:batch_index_2]
  
          # Main algorithm for each batch
          # Initialize the search space; optimize to remove features that can't be changed
          if self.estimator.clip_values is not None:
              search_space = np.zeros(batch.shape)
              clip_min, clip_max = self.estimator.clip_values
              if self.theta > 0:
                  search_space[batch < clip_max] = 1
              else:  # pragma: no cover
                  search_space[batch > clip_min] = 1
          else:
              search_space = np.ones(batch.shape)
  
          # Get current predictions
          current_pred = preds[batch_index_1:batch_index_2]
          target = targets[batch_index_1:batch_index_2]
          active_indices = np.where(current_pred != target)[0]
          all_feat = np.zeros_like(batch)
  
          while active_indices.size != 0:
              # Compute saliency map
              feat_ind = self._saliency_map(
                  np.reshape(batch, [batch.shape[0]] + dims)[
                      active_indices
                  ],
                  target[active_indices],
                  search_space[active_indices],
              )
  
              # Update used features
              all_feat[active_indices, feat_ind[:, 0]] = 1
              all_feat[active_indices, feat_ind[:, 1]] = 1
  
              # Apply attack with clipping
              if self.estimator.clip_values is not None:
                  # Prepare update depending of theta
                  if self.theta > 0:
                      clip_func, clip_value = np.minimum, clip_max  # type: ignore
                  else:  # pragma: no cover
                      clip_func, clip_value = np.maximum, clip_min  # type: ignore
  
                  # Update adversarial examples
                  tmp_batch = batch[active_indices]
                  tmp_batch[
                      np.arange(len(active_indices)), feat_ind[:, 0]
                  ] = clip_func(
                      clip_value,
                      tmp_batch[
                          np.arange(len(active_indices)), feat_ind[:, 0]
                      ]
                      + self.theta,
                  )
                  tmp_batch[
                      np.arange(len(active_indices)), feat_ind[:, 1]
                  ] = clip_func(
                      clip_value,
                      tmp_batch[
                          np.arange(len(active_indices)), feat_ind[:, 1]
                      ]
                      + self.theta,
                  )
                  batch[active_indices] = tmp_batch
  
                  # Remove indices from search space if max/min values were reached
                  search_space[batch == clip_value] = 0
  
              # Apply attack without clipping
              else:
                  tmp_batch = batch[active_indices]
                  tmp_batch[
                      np.arange(len(active_indices)), feat_ind[:, 0]
                  ] += self.theta
                  tmp_batch[
                      np.arange(len(active_indices)), feat_ind[:, 1]
                  ] += self.theta
                  batch[active_indices] = tmp_batch
  
              # Recompute model prediction
              current_pred = np.argmax(
                  self.estimator.predict(
                      np.reshape(batch, [batch.shape[0]] + dims)
                  ),
                  axis=1,
              )
  
              # Update active_indices
              active_indices = np.where(
                  (current_pred != target)
                  * (
                      np.sum(all_feat, axis=1) / self._nb_features
                      <= self.gamma
                  )
                  * (np.sum(search_space, axis=1) > 0)
              )[0]
  
          x_adv[batch_index_1:batch_index_2] = batch
  
      x_adv = np.reshape(x_adv, x.shape)
  
      return x_adv
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/saliency_map.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, Union, TYPE_CHECKING
  import numpy
  from tqdm.auto import 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 ClassGradientsMixin
  from art.utils import check_and_transform_label_format
label_desc: Use image node_id 2 for calling the SaliencyMapMethod obj's underlying member method code with example usage: obj.generate(x, y) and returns: x_adv