docstr: Constructor method.
  
  Args:
      model: KerasClassifier classification model
      arg_mode(str): 'PP' or 'PN'
      AE: Auto-encoder model
      batch_size(int): Number of samples in a batch
      kappa(double): Confidence gap between desired class and other classes
      init_learning_rate(double): Initial learning rate
      binary_search_steps(int): Number of search steps
      max_iterations(int): For each weighting of loss function number of iterations to search
      initial_const(double): Initial weighting of loss function
      beta (double): Weighting of L1 loss
      gamma (double): Weighting of auto-encoder
      alpha (double): Weighting of L2 loss
      threshold (double): automatically turn off all features less than threshold since nothing to turn off
      offset (double): example is in [0,1]. we subtract offset when passed to classifier
docstr_tok: ["Constructor","method",".","Args",":","model",":","KerasClassifier","classification","model","arg_mode","(","str",")",":","'PP","'","or","'PN'","AE",":","Auto-encoder","model","batch_size","(","int",")",":","Number","of","samples","in","a","batch","kappa","(","double",")",":","Confidence","gap","between","desired","class","and","other","classes","init_learning_rate","(","double",")",":","Initial","learning","rate","binary_search_steps","(","int",")",":","Number","of","search","steps","max_iterations","(","int",")",":","For","each","weighting","of","loss","function","number","of","iterations","to","search","initial_const","(","double",")",":","Initial","weighting","of","loss","function","beta","(","double",")",":","Weighting","of","L1","loss","gamma","(","double",")",":","Weighting","of","auto-encoder","alpha","(","double",")",":","Weighting","of","L2","loss","threshold","(","double",")",":","automatically","turn","off","all","features","less","than","threshold","since","nothing","to","turn","off","offset","(","double",")",":","example","is","in","[","0,1","]",".","we","subtract","offset","when","passed","to","classifier"]
code: def __init__(
      self,
      model,
      shape,
      mode,
      AE,
      batch_size,
      kappa,
      init_learning_rate,
      binary_search_steps,
      max_iterations,
      initial_const,
      beta,
      gamma,
      alpha=0,
      threshold=1,
      offset=0,
  ):
      """
      Constructor method.
  
      Args:
          model: KerasClassifier classification model
          arg_mode(str): 'PP' or 'PN'
          AE: Auto-encoder model
          batch_size(int): Number of samples in a batch
          kappa(double): Confidence gap between desired class and other classes
          init_learning_rate(double): Initial learning rate
          binary_search_steps(int): Number of search steps
          max_iterations(int): For each weighting of loss function number of iterations to search
          initial_const(double): Initial weighting of loss function
          beta (double): Weighting of L1 loss
          gamma (double): Weighting of auto-encoder
          alpha (double): Weighting of L2 loss
          threshold (double): automatically turn off all features less than threshold since nothing to turn off
          offset (double): example is in [0,1]. we subtract offset when passed to classifier
      """
  
      num_classes = model._nb_classes
      tf_sum = list(range(1, len(shape)))
  
      self.sess = K.get_session()
  
      self.INIT_LEARNING_RATE = init_learning_rate
      self.MAX_ITERATIONS = max_iterations
      self.BINARY_SEARCH_STEPS = binary_search_steps
      self.kappa = kappa
      self.init_const = initial_const
      self.batch_size = batch_size
      self.AE = AE
      self.mode = mode
      self.beta = beta
      self.gamma = gamma
      self.alpha = alpha
      self.offset = offset
      self.threshold = threshold
  
      # these are variables to be more efficient in sending data to tf
      self.orig_img = tf.Variable(np.zeros(shape), dtype=tf.float32)
      self.adv_img = tf.Variable(np.zeros(shape), dtype=tf.float32)
      self.adv_img_s = tf.Variable(np.zeros(shape), dtype=tf.float32)
      self.target_lab = tf.Variable(
          np.zeros((batch_size, num_classes)), dtype=tf.float32
      )
      self.const = tf.Variable(np.zeros(batch_size), dtype=tf.float32)
      self.global_step = tf.Variable(0.0, trainable=False)
  
      # and here's what we use to assign them
      self.assign_orig_img = tf.placeholder(tf.float32, shape)
      self.assign_adv_img = tf.placeholder(tf.float32, shape)
      self.assign_adv_img_s = tf.placeholder(tf.float32, shape)
      self.assign_target_lab = tf.placeholder(
          tf.float32, (batch_size, num_classes)
      )
      self.assign_const = tf.placeholder(tf.float32, [batch_size])
  
      """Fast Iterative Soft Thresholding"""
      """--------------------------------"""
      self.zt = tf.divide(
          self.global_step, self.global_step + tf.cast(3, tf.float32)
      )
  
      # These conditions do shrinkage threshold - note that sparsity is on orig_img-adv_img_s so a change of variables just shrinkage on adv_img - orig_img
      cond1 = tf.cast(
          tf.greater(
              tf.subtract(self.adv_img_s, self.orig_img), self.beta
          ),
          tf.float32,
      )
      cond2 = tf.cast(
          tf.less_equal(
              tf.abs(tf.subtract(self.adv_img_s, self.orig_img)),
              self.beta,
          ),
          tf.float32,
      )
      cond3 = tf.cast(
          tf.less(
              tf.subtract(self.adv_img_s, self.orig_img),
              tf.negative(self.beta),
          ),
          tf.float32,
      )
      #        upper = tf.minimum(tf.subtract(self.adv_img_s, self.beta), tf.cast(0.5, tf.float32))
      #        lower = tf.maximum(tf.add(self.adv_img_s, self.beta), tf.cast(-0.5, tf.float32))
      upper = tf.subtract(
          self.adv_img_s, self.beta
      )  # RL: removed the bounds
      lower = tf.add(self.adv_img_s, self.beta)
      self.assign_adv_img = (
          tf.multiply(cond1, upper)
          + tf.multiply(cond2, self.orig_img)
          + tf.multiply(cond3, lower)
      )
  
      if self.mode == "PP":
          cond8 = tf.cast(
              tf.greater(
                  tf.subtract(self.orig_img, self.assign_adv_img),
                  tf.cast(1.0, tf.float32),
              ),
              tf.float32,
          )
          cond9 = tf.cast(
              tf.less(
                  tf.subtract(self.orig_img, self.assign_adv_img),
                  tf.cast(0.0, tf.float32),
              ),
              tf.float32,
          )
          cond10 = tf.cast(
              tf.logical_and(
                  tf.greater_equal(
                      tf.subtract(self.orig_img, self.assign_adv_img),
                      tf.cast(0.0, tf.float32),
                  ),
                  tf.less_equal(
                      tf.subtract(self.orig_img, self.assign_adv_img),
                      tf.cast(1.0, tf.float32),
                  ),
              ),
              tf.float32,
          )
          self.assign_adv_img = (
              tf.multiply(
                  cond8,
                  tf.subtract(self.orig_img, tf.cast(1.0, tf.float32)),
              )
              + tf.multiply(cond9, self.orig_img)
              + tf.multiply(cond10, self.assign_adv_img)
          )
      elif self.mode == "PN":
          cond8_pn = tf.cast(
              tf.greater(self.assign_adv_img, tf.cast(1.0, tf.float32)),
              tf.float32,
          )
          cond9_pn = tf.cast(
              tf.less(self.assign_adv_img, tf.cast(0.0, tf.float32)),
              tf.float32,
          )
          cond10_pn = tf.cast(
              tf.logical_and(
                  tf.greater_equal(
                      self.assign_adv_img, tf.cast(0.0, tf.float32)
                  ),
                  tf.less_equal(
                      self.assign_adv_img, tf.cast(1.0, tf.float32)
                  ),
              ),
              tf.float32,
          )
          self.assign_adv_img = (
              tf.multiply(cond8_pn, tf.cast(1.0, tf.float32))
              + tf.multiply(cond9_pn, tf.cast(0.0, tf.float32))
              + tf.multiply(cond10_pn, self.assign_adv_img)
          )
  
      # if self.threshold < 1, use it to turn off features less than the threshold
      if (self.mode == "PP") and (self.threshold < 1.0):
          cond_thresh1a = tf.cast(
              tf.less(
                  tf.subtract(self.orig_img, self.assign_adv_img),
                  tf.cast(self.threshold, tf.float32),
              ),
              tf.float32,
          )
          cond_thresh1b = tf.cast(
              tf.greater_equal(
                  tf.subtract(self.orig_img, self.assign_adv_img),
                  tf.cast(self.threshold, tf.float32),
              ),
              tf.float32,
          )
          self.assign_adv_img = tf.multiply(
              cond_thresh1b, self.assign_adv_img
          ) + tf.multiply(
              cond_thresh1a, self.orig_img
          )  # theshold delta to 0 if <= self.threshold
      elif self.mode == "PN" and (self.threshold < 1.0):
          cond_thresh1a = tf.cast(
              tf.greater_equal(
                  self.assign_adv_img,
                  tf.cast(self.threshold, tf.float32),
              ),
              tf.float32,
          )
          self.assign_adv_img = tf.multiply(
              cond_thresh1a, self.assign_adv_img
          )
  
      if self.mode == "PP":
          self.assign_adv_img = tf.maximum(
              self.assign_adv_img, tf.cast(0.0, tf.float32)
          )  # PP's cannot increase a data point
      elif self.mode == "PN":
          self.assign_adv_img = tf.maximum(
              self.assign_adv_img, self.orig_img
          )  # PN's cannot remove part of a data point
  
      # Removing cond4 and cond5 since no more projection needed here
      # These conditions threshold the variable after shrinkage to the proper space
      # cond4 = tf.cast(tf.greater(tf.subtract(self.assign_adv_img, self.orig_img), 0), tf.float32)
      # cond5 = tf.cast(tf.less_equal(tf.subtract(self.assign_adv_img, self.orig_img), 0), tf.float32)
      # if self.mode == "PP" or self.mode == "PP_PATH":
      #     self.assign_adv_img = tf.multiply(cond5, self.assign_adv_img) + tf.multiply(cond4, self.orig_img)
      # elif self.mode == "PN":
      #     self.assign_adv_img = tf.multiply(cond4, self.assign_adv_img) + tf.multiply(cond5, self.orig_img)
  
      # This is how to take a step in FISTA
      self.assign_adv_img_s = self.assign_adv_img + tf.multiply(
          self.zt, self.assign_adv_img - self.adv_img
      )
  
      # Replacing cond6 and cond7 with same projections as before FISTA step but for self.asign_adv_img_s
      if self.mode == "PP":
          cond11 = tf.cast(
              tf.greater(
                  tf.subtract(self.orig_img, self.assign_adv_img_s),
                  tf.cast(1.0, tf.float32),
              ),
              tf.float32,
          )
          cond12 = tf.cast(
              tf.less(
                  tf.subtract(self.orig_img, self.assign_adv_img_s),
                  tf.cast(0.0, tf.float32),
              ),
              tf.float32,
          )
          cond13 = tf.cast(
              tf.logical_and(
                  tf.greater_equal(
                      tf.subtract(self.orig_img, self.assign_adv_img_s),
                      tf.cast(0.0, tf.float32),
                  ),
                  tf.less_equal(
                      tf.subtract(self.orig_img, self.assign_adv_img_s),
                      tf.cast(1.0, tf.float32),
                  ),
              ),
              tf.float32,
          )
          self.assign_adv_img_s = (
              tf.multiply(
                  cond11,
                  tf.subtract(self.orig_img, tf.cast(1.0, tf.float32)),
              )
              + tf.multiply(cond12, self.orig_img)
              + tf.multiply(cond13, self.assign_adv_img_s)
          )
      elif self.mode == "PN":
          cond11_pn = tf.cast(
              tf.greater(
                  self.assign_adv_img_s, tf.cast(1.0, tf.float32)
              ),
              tf.float32,
          )
          cond12_pn = tf.cast(
              tf.less(self.assign_adv_img_s, tf.cast(0.0, tf.float32)),
              tf.float32,
          )
          cond13_pn = tf.cast(
              tf.logical_and(
                  tf.greater_equal(
                      self.assign_adv_img_s, tf.cast(0.0, tf.float32)
                  ),
                  tf.less_equal(
                      self.assign_adv_img_s, tf.cast(1.0, tf.float32)
                  ),
              ),
              tf.float32,
          )
          self.assign_adv_img_s = (
              tf.multiply(cond11_pn, tf.cast(1.0, tf.float32))
              + tf.multiply(cond12_pn, tf.cast(0.0, tf.float32))
              + tf.multiply(cond13_pn, self.assign_adv_img_s)
          )
  
      # if self.threshold < 1, use it to turn off features less than the threshold
      if (self.mode == "PP") and (self.threshold < 1.0):
          cond_thresh2a = tf.cast(
              tf.less(
                  tf.subtract(self.orig_img, self.assign_adv_img_s),
                  tf.cast(self.threshold, tf.float32),
              ),
              tf.float32,
          )
          cond_thresh2b = tf.cast(
              tf.greater_equal(
                  tf.subtract(self.orig_img, self.assign_adv_img_s),
                  tf.cast(self.threshold, tf.float32),
              ),
              tf.float32,
          )
          self.assign_adv_img_s = tf.multiply(
              cond_thresh2b, self.assign_adv_img
          ) + tf.multiply(
              cond_thresh2a, self.orig_img
          )  # theshold delta to 0 if <= self.threshold
      elif self.mode == "PN" and (self.threshold < 1.0):
          cond_thresh1a = tf.cast(
              tf.greater_equal(
                  self.assign_adv_img_s,
                  tf.cast(self.threshold, tf.float32),
              ),
              tf.float32,
          )
          self.assign_adv_img_s = tf.multiply(
              cond_thresh1a, self.assign_adv_img_s
          )
  
      if self.mode == "PP":
          self.assign_adv_img_s = tf.maximum(
              self.assign_adv_img_s, tf.cast(0.0, tf.float32)
          )  # PP's cannot increase a data point
      elif self.mode == "PN":
          self.assign_adv_img_s = tf.maximum(
              self.assign_adv_img_s, self.orig_img
          )  # PN's cannot remove part of a data point
  
      # These conditions threshold the variable after taking a step in FISTA
      # cond6 = tf.cast(tf.greater(tf.subtract(self.assign_adv_img_s, self.orig_img), 0), tf.float32)
      # cond7 = tf.cast(tf.less_equal(tf.subtract(self.assign_adv_img_s, self.orig_img), 0), tf.float32)
      # if self.mode == "PP" or self.mode == "PP_PATH":
      #     self.assign_adv_img_s = tf.multiply(cond7, self.assign_adv_img_s) + tf.multiply(cond6, self.orig_img)
      # elif self.mode == "PN":
      #     self.assign_adv_img_s = tf.multiply(cond6, self.assign_adv_img_s) + tf.multiply(cond7, self.orig_img)
  
      self.adv_updater = tf.assign(self.adv_img, self.assign_adv_img)
      self.adv_updater_s = tf.assign(
          self.adv_img_s, self.assign_adv_img_s
      )
  
      """--------------------------------"""
      # prediction BEFORE-SOFTMAX of the model
      self.delta_img = self.orig_img - self.adv_img
      self.delta_img_s = self.orig_img - self.adv_img_s
      # %%change%%
      if self.mode == "PP":
          # self.ImgToEnforceLabel_Score = model.predict(self.delta_img)
          # self.ImgToEnforceLabel_Score_s = model.predict(self.delta_img_s)
          self.ImgToEnforceLabel_Score = model.predictsym(
              tf.subtract(
                  self.delta_img, tf.cast(self.offset, tf.float32)
              )
          )
          self.ImgToEnforceLabel_Score_s = model.predictsym(
              tf.subtract(
                  self.delta_img_s, tf.cast(self.offset, tf.float32)
              )
          )
      elif self.mode == "PN":
          # self.ImgToEnforceLabel_Score = model.predict(self.adv_img)
          # self.ImgToEnforceLabel_Score_s = model.predict(self.adv_img_s)
          self.ImgToEnforceLabel_Score = model.predictsym(
              tf.subtract(
                  self.adv_img, tf.cast(self.offset, tf.float32)
              )
          )
          self.ImgToEnforceLabel_Score_s = model.predictsym(
              tf.subtract(
                  self.adv_img_s, tf.cast(self.offset, tf.float32)
              )
          )
  
      self.L2_dist = tf.reduce_sum(
          tf.square(self.delta_img), axis=tf_sum
      )
      self.L2_dist_s = tf.reduce_sum(
          tf.square(self.delta_img_s), axis=tf_sum
      )
      self.L1_dist = tf.reduce_sum(tf.abs(self.delta_img), axis=tf_sum)
      self.L1_dist_s = tf.reduce_sum(
          tf.abs(self.delta_img_s), axis=tf_sum
      )
  
      self.EN_dist = (
          tf.multiply(self.L2_dist, self.alpha)
          + self.L2_dist
          + tf.multiply(self.L1_dist, self.beta)
      )
      self.EN_dist_s = tf.multiply(
          self.L2_dist_s, self.alpha
      ) + tf.multiply(self.L1_dist_s, self.beta)
  
      # compute the probability of the label class versus the maximum other
      self.target_lab_score = tf.reduce_sum(
          (self.target_lab) * self.ImgToEnforceLabel_Score, 1
      )
      target_lab_score_s = tf.reduce_sum(
          (self.target_lab) * self.ImgToEnforceLabel_Score_s, 1
      )
      self.max_nontarget_lab_score = tf.reduce_max(
          (1 - self.target_lab) * self.ImgToEnforceLabel_Score
          - (self.target_lab * 10000),
          1,
      )
      max_nontarget_lab_score_s = tf.reduce_max(
          (1 - self.target_lab) * self.ImgToEnforceLabel_Score_s
          - (self.target_lab * 10000),
          1,
      )
      if self.mode == "PP":
          Loss_Attack = tf.maximum(
              0.0,
              self.max_nontarget_lab_score
              - self.target_lab_score
              + self.kappa,
          )
          Loss_Attack_s = tf.maximum(
              0.0,
              max_nontarget_lab_score_s
              - target_lab_score_s
              + self.kappa,
          )
      elif self.mode == "PN":
          Loss_Attack = tf.maximum(
              0.0,
              -self.max_nontarget_lab_score
              + self.target_lab_score
              + self.kappa,
          )
          Loss_Attack_s = tf.maximum(
              0.0,
              -max_nontarget_lab_score_s
              + target_lab_score_s
              + self.kappa,
          )
      # sum up the losses
      self.Loss_L1Dist = tf.reduce_sum(self.L1_dist)
      self.Loss_L1Dist_s = tf.reduce_sum(self.L1_dist_s)
      self.Loss_L2Dist = tf.reduce_sum(self.L2_dist)
      self.Loss_L2Dist_s = tf.reduce_sum(self.L2_dist_s)
      self.Loss_Attack = tf.reduce_sum(self.const * Loss_Attack)
      self.Loss_Attack_s = tf.reduce_sum(self.const * Loss_Attack_s)
  
      if self.mode == "PP" and callable(self.AE):
          self.Loss_AE_Dist = self.gamma * tf.square(
              tf.norm(self.AE(self.delta_img) - self.delta_img)
          )
          self.Loss_AE_Dist_s = self.gamma * tf.square(
              tf.norm(self.AE(self.delta_img) - self.delta_img_s)
          )
      elif self.mode == "PN" and callable(self.AE):
          self.Loss_AE_Dist = self.gamma * tf.square(
              tf.norm(self.AE(self.adv_img) - self.adv_img)
          )
          self.Loss_AE_Dist_s = self.gamma * tf.square(
              tf.norm(self.AE(self.adv_img_s) - self.adv_img_s)
          )
      else:
          self.Loss_AE_Dist = tf.constant(0.0)
          self.Loss_AE_Dist_s = tf.constant(0.0)
  
      self.Loss_ToOptimize = (
          self.Loss_Attack_s + self.Loss_L2Dist_s + self.Loss_AE_Dist_s
      )
      self.Loss_Overall = (
          self.Loss_Attack
          + self.Loss_L2Dist
          + self.Loss_AE_Dist
          + tf.multiply(self.beta, self.Loss_L1Dist)
      )
  
      self.learning_rate = tf.train.polynomial_decay(
          self.INIT_LEARNING_RATE,
          self.global_step,
          self.MAX_ITERATIONS,
          0,
          power=0.5,
      )
      optimizer = tf.train.GradientDescentOptimizer(self.learning_rate)
      start_vars = set(x.name for x in tf.global_variables())
      self.train = optimizer.minimize(
          self.Loss_ToOptimize,
          var_list=[self.adv_img_s],
          global_step=self.global_step,
      )  # gradient of g(delta) in paper is subtracted from self.adv_img_s
      end_vars = tf.global_variables()
      new_vars = [x for x in end_vars if x.name not in start_vars]
  
      # these are the variables to initialize when we run
      self.setup = []
      self.setup.append(self.orig_img.assign(self.assign_orig_img))
      self.setup.append(self.target_lab.assign(self.assign_target_lab))
      self.setup.append(self.const.assign(self.assign_const))
      self.setup.append(self.adv_img.assign(self.assign_adv_img))
      self.setup.append(self.adv_img_s.assign(self.assign_adv_img_s))
  
      self.init = tf.variables_initializer(
          var_list=[self.global_step]
          + [self.adv_img_s]
          + [self.adv_img]
          + new_vars
      )
  
imports: import sys
  import numpy
  import tensorflow
  import keras.backend
label_desc: Use image node_id 1 to create a new AEADEN object  with example: obj = AEADEN(model, shape, mode, AE, batch_size, kappa, init_learning_rate, binary_search_steps, max_iterations, initial_const, beta, gamma, alpha, threshold, offset)