class_docstr: Close implementation of Papernot's attack on decision trees following Algorithm 2 and communication with the
  authors.
  
  | Paper link: https://arxiv.org/abs/1605.07277
docstr: Generate adversarial examples and return them as 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","examples","and","return","them","as","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 examples and return them as 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,
              return_one_hot=False,
          )
      x_adv = x.copy()
  
      for index in trange(
          x_adv.shape[0],
          desc="Decision tree attack",
          disable=not self.verbose,
      ):
          path = self.estimator.get_decision_path(x_adv[index])
          legitimate_class = int(
              np.argmax(
                  self.estimator.predict(x_adv[index].reshape(1, -1))
              )
          )
          position = -2
          adv_path = [-1]
          ancestor = path[position]
          while np.abs(position) < (len(path) - 1) or adv_path[0] == -1:
              ancestor = path[position]
              current_child = path[position + 1]
              # search in right subtree
              if current_child == self.estimator.get_left_child(
                  ancestor
              ):
                  if y is None:
                      adv_path = self._df_subtree(
                          self.estimator.get_right_child(ancestor),
                          legitimate_class,
                      )
                  else:
                      adv_path = self._df_subtree(
                          self.estimator.get_right_child(ancestor),
                          legitimate_class,
                          y[index],
                      )
              else:  # search in left subtree
                  if y is None:
                      adv_path = self._df_subtree(
                          self.estimator.get_left_child(ancestor),
                          legitimate_class,
                      )
                  else:
                      adv_path = self._df_subtree(
                          self.estimator.get_left_child(ancestor),
                          legitimate_class,
                          y[index],
                      )
              position = (
                  position - 1
              )  # we are going the decision path upwards
          adv_path.append(ancestor)
          # we figured out which is the way to the target, now perturb
          # first one is leaf-> no threshold, cannot be perturbed
          for i in range(1, 1 + len(adv_path[1:])):
              go_for = adv_path[i - 1]
              threshold = self.estimator.get_threshold_at_node(
                  adv_path[i]
              )
              feature = self.estimator.get_feature_at_node(adv_path[i])
              # only perturb if the feature is actually wrong
              if x_adv[index][
                  feature
              ] > threshold and go_for == self.estimator.get_left_child(
                  adv_path[i]
              ):
                  x_adv[index][feature] = threshold - self.offset
              elif x_adv[index][
                  feature
              ] <= threshold and go_for == self.estimator.get_right_child(
                  adv_path[i]
              ):
                  x_adv[index][feature] = threshold + self.offset
  
      return x_adv
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/decision_tree_attack.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import List, Optional, Union
  import numpy
  from tqdm.auto import trange
  from art.attacks.attack import EvasionAttack
  from art.estimators.classification.scikitlearn import ScikitlearnDecisionTreeClassifier
  from art.utils import check_and_transform_label_format
label_desc: Use image node_id 3 for calling the DecisionTreeAttack obj's underlying member method code with example usage: obj.generate(x, y) and returns: x_adv