'Return a tensor that constructs adversarial examples for the given
input. Generate uses tf.py_func in order to operate over tensors.
:param x: (required) A tensor with the inputs.
:param y: (optional) A tensor with the true labels for an untargeted
attack. If None (and y_target is None) then use the
original labels the classifier assigns.
:param y_target: (optional) A tensor with the target labels for a
targeted attack.
:param nb_classes: The number of classes the model has.
:param confidence: Confidence of adversarial examples: higher produces
examples with larger l2 distortion, but more
strongly classified as adversarial.
:param batch_size: Number of attacks to run simultaneously.
:param learning_rate: The learning rate for the attack algorithm.
Smaller values produce better results but are
slower to converge.
:param binary_search_steps: The number of times we perform binary
search to find the optimal tradeoff-
constant between norm of the purturbation
and confidence of the classification.
:param max_iterations: The maximum number of iterations. Setting this
to a larger value will produce lower distortion
results. Using only a few iterations requires
a larger learning rate, and will produce larger
distortion results.
:param abort_early: If true, allows early aborts if gradient descent
is unable to make progress (i.e., gets stuck in
a local minimum).
:param initial_const: The initial tradeoff-constant to use to tune the
relative importance of size of the pururbation
and confidence of classification.
If binary_search_steps is large, the initial
constant is not important. A smaller value of
this constant gives lower distortion results.
:param clip_min: (optional float) Minimum input component value
:param clip_max: (optional float) Maximum input component value'

def __init__(self, sess, model, batch_size, confidence, targeted, learning_rate, binary_search_steps, max_iterations, abort_early, initial_const, clip_min, clip_max, num_labels, shape):

    self.sess = sess
    self.TARGETED = targeted
    self.LEARNING_RATE = learning_rate
    self.MAX_ITERATIONS = max_iterations
    self.BINARY_SEARCH_STEPS = binary_search_steps
    self.ABORT_EARLY = abort_early
    self.CONFIDENCE = confidence
    self.initial_const = initial_const
    self.batch_size = batch_size
    self.clip_min = clip_min
    self.clip_max = clip_max
    self.model = model
    self.repeat = (binary_search_steps >= 10)
    self.shape = shape = tuple(([batch_size] + list(shape)))
    modifier = tf.Variable(np.zeros(shape, dtype=np.float32))
    self.timg = tf.Variable(np.zeros(shape), dtype=tf.float32, name=u'timg')
    self.tlab = tf.Variable(np.zeros((batch_size, num_labels)), dtype=tf.float32, name=u'tlab')
    self.const = tf.Variable(np.zeros(batch_size), dtype=tf.float32, name=u'const')
    self.assign_timg = tf.placeholder(tf.float32, shape, name=u'assign_timg')
    self.assign_tlab = tf.placeholder(tf.float32, (batch_size, num_labels), name=u'assign_tlab')
    self.assign_const = tf.placeholder(tf.float32, [batch_size], name=u'assign_const')
    self.newimg = ((tf.tanh((modifier + self.timg)) + 1) / 2)
    self.newimg = ((self.newimg * (clip_max - clip_min)) + clip_min)
    self.output = model.get_logits(self.newimg)
    self.other = ((((tf.tanh(self.timg) + 1) / 2) * (clip_max - clip_min)) + clip_min)
    self.l2dist = tf.reduce_sum(tf.square((self.newimg - self.other)), list(range(1, len(shape))))
    real = tf.reduce_sum((self.tlab * self.output), 1)
    other = tf.reduce_max((((1 - self.tlab) * self.output) - (self.tlab * 10000)), 1)
    if self.TARGETED:
        loss1 = tf.maximum(0.0, ((other - real) + self.CONFIDENCE))
    else:
        loss1 = tf.maximum(0.0, ((real - other) + self.CONFIDENCE))
    self.loss2 = tf.reduce_sum(self.l2dist)
    self.loss1 = tf.reduce_sum((self.const * loss1))
    self.loss = (self.loss1 + self.loss2)
    start_vars = set((x.name for x in tf.global_variables()))
    optimizer = tf.train.AdamOptimizer(self.LEARNING_RATE)
    self.train = optimizer.minimize(self.loss, var_list=[modifier])
    end_vars = tf.global_variables()
    new_vars = [x for x in end_vars if (x.name not in start_vars)]
    self.setup = []
    self.setup.append(self.timg.assign(self.assign_timg))
    self.setup.append(self.tlab.assign(self.assign_tlab))
    self.setup.append(self.const.assign(self.assign_const))
    self.init = tf.variables_initializer(var_list=([modifier] + new_vars))
