class_docstr: The elastic net attack of Pin-Yu Chen et al. (2018).
  
  | Paper link: https://arxiv.org/abs/1709.04114
docstr: Compute the gradient of the loss function.
  
  :param target: An array with the target class (one-hot encoded).
  :param x: An array with the original input.
  :param x_adv: An array with the adversarial input.
  :param c_weight: Weight of the loss term aiming for classification as target.
  :return: An array with the gradient of the loss function.
docstr_tok: ["Compute","the","gradient","of","the","loss","function",".",":","param","target",":","An","array","with","the","target","class","(","one-hot","encoded",")",".",":","param","x",":","An","array","with","the","original","input",".",":","param","x_adv",":","An","array","with","the","adversarial","input",".",":","param","c_weight",":","Weight","of","the","loss","term","aiming","for","classification","as","target",".",":","return",":","An","array","with","the","gradient","of","the","loss","function","."]
code: def _gradient_of_loss(
      self,
      target: np.ndarray,
      x: np.ndarray,
      x_adv: np.ndarray,
      c_weight: np.ndarray,
  ) -> np.ndarray:
      """
      Compute the gradient of the loss function.
  
      :param target: An array with the target class (one-hot encoded).
      :param x: An array with the original input.
      :param x_adv: An array with the adversarial input.
      :param c_weight: Weight of the loss term aiming for classification as target.
      :return: An array with the gradient of the loss function.
      """
      # Compute the current predictions
      predictions = self.estimator.predict(
          np.array(x_adv, dtype=ART_NUMPY_DTYPE),
          batch_size=self.batch_size,
      )
  
      if self.targeted:
          i_sub = np.argmax(target, axis=1)
          i_add = np.argmax(
              predictions * (1 - target)
              + (np.min(predictions, axis=1) - 1)[:, np.newaxis]
              * target,
              axis=1,
          )
      else:
          i_add = np.argmax(target, axis=1)
          i_sub = np.argmax(
              predictions * (1 - target)
              + (np.min(predictions, axis=1) - 1)[:, np.newaxis]
              * target,
              axis=1,
          )
  
      loss_gradient = self.estimator.class_gradient(x_adv, label=i_add)
      loss_gradient -= self.estimator.class_gradient(x_adv, label=i_sub)
      loss_gradient = loss_gradient.reshape(x.shape)
  
      c_mult = c_weight
      for _ in range(len(x.shape) - 1):
          c_mult = c_mult[:, np.newaxis]
  
      loss_gradient *= c_mult
      loss_gradient += 2 * (x_adv - x)
  
      # Set gradients where loss is constant to zero
      cond = (
          predictions[np.arange(x.shape[0]), i_add]
          - predictions[np.arange(x.shape[0]), i_sub]
          + self.confidence
      ) < 0
      loss_gradient[cond] = 0.0
  
      return loss_gradient
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, Tuple, TYPE_CHECKING
  import numpy
  import six
  from tqdm.auto import trange
  from art.config import ART_NUMPY_DTYPE
  from art.attacks.attack import EvasionAttack
  from art.estimators.estimator import BaseEstimator
  from art.estimators.classification.classifier import ClassGradientsMixin
  from art.utils import compute_success, get_labels_np_array, check_and_transform_label_format
label_desc: Use image node_id 3 for calling the ElasticNet obj's underlying member method code with example usage: obj._gradient_of_loss(target, x, x_adv, c_weight) and returns: loss_gradient