# Buggy code
def class_gradient(self, x, label=None, logits=False):
    """
    Compute per-class derivatives w.r.t. `x`.

    :param x: Sample input with shape as expected by the model.
    :type x: `np.ndarray`
    :param label: Index of a specific per-class derivative. If an integer is provided, the gradient of that class
                  output is computed for all samples. If multiple values as provided, the first dimension should
                  match the batch size of `x`, and each value will be used as target for its corresponding sample in
                  `x`. If `None`, then gradients for all classes will be computed for each sample.
    :type label: `int` or `list`
    :param logits: `True` if the prediction should be done at the logits layer.
    :type logits: `bool`
    :return: Array of gradients of input features w.r.t. each class in the form
             `(batch_size, nb_classes, input_shape)` when computing for all classes, otherwise shape becomes
             `(batch_size, 1, input_shape)` when `label` parameter is specified.
    :rtype: `np.ndarray`
    """
    # Check value of label for computing gradients
    if not (
        label is None
        or (isinstance(label, (int, np.integer)) and label in range(self.nb_classes))
        or (
            isinstance(label, np.ndarray)
            and len(label.shape) == 1
            and (label < self._nb_classes).all()
            and label.shape[0] == x.shape[0]
        )
    ):
        raise ValueError("Label %s is out of range." % label)

    self._init_class_grads(label=label, logits=logits)

    x_ = self._apply_processing(x)

    # Compute the gradient and return
    if label is None:
        # Compute the gradients w.r.t. all classes
        if logits:
            grads = self._sess.run(
                self._logit_class_grads, feed_dict={self._input_ph: x_}
            )
        else:
            grads = self._sess.run(self._class_grads, feed_dict={self._input_ph: x_})

        grads = np.swapaxes(np.array(grads), 0, 1)
        grads = self._apply_processing_gradient(grads)

    elif isinstance(label, (int, np.integer)):
        # Compute the gradients only w.r.t. the provided label
        if logits:
            grads = self._sess.run(
                self._logit_class_grads[label], feed_dict={self._input_ph: x_}
            )
        else:
            grads = self._sess.run(
                self._class_grads[label], feed_dict={self._input_ph: x_}
            )

        grads = grads[None, ...]
        grads = np.swapaxes(np.array(grads), 0, 1)
        grads = self._apply_processing_gradient(grads)

    else:
        # For each sample, compute the gradients w.r.t. the indicated target class (possibly distinct)
        unique_label = list(np.unique(label))
        if logits:
            grads = self._sess.run(
                [self._logit_class_grads[l] for l in unique_label],
                feed_dict={self._input_ph: x_},
            )
        else:
            grads = self._sess.run(
                [self._class_grads[l] for l in unique_label],
                feed_dict={self._input_ph: x_},
            )

        grads = np.swapaxes(np.array(grads), 0, 1)
        lst = [unique_label.index(i) for i in label]
        grads = np.expand_dims(grads[np.arange(len(grads)), lst], axis=1)

        grads = self._apply_processing_gradient(grads)

    return grads


# Traceback (IndexError)
Traceback (most recent call last):
File "cw_pytorch.py", line 172, in <module>
x_test_adv = cl2m.generate(inputs, **params)
File "/home/weitian/anaconda3/envs/xnor/lib/python3.6/site-packages/art/attacks/carlini.py", line 380, in generate
x_adv_batch_tanh[active_and_update_adv] = x_adv_batch_tanh[update_adv] + \
IndexError: boolean index did not match indexed array along dimension 0; dimension is 18 but corresponding boolean dimension is 17

# Fixed code
def class_gradient(self, x, label=None, logits=False):
    """
    Compute per-class derivatives w.r.t. `x`.

    :param x: Sample input with shape as expected by the model.
    :type x: `np.ndarray`
    :param label: Index of a specific per-class derivative. If an integer is provided, the gradient of that class
                  output is computed for all samples. If multiple values as provided, the first dimension should
                  match the batch size of `x`, and each value will be used as target for its corresponding sample in
                  `x`. If `None`, then gradients for all classes will be computed for each sample.
    :type label: `int` or `list`
    :param logits: `True` if the prediction should be done at the logits layer.
    :type logits: `bool`
    :return: Array of gradients of input features w.r.t. each class in the form
             `(batch_size, nb_classes, input_shape)` when computing for all classes, otherwise shape becomes
             `(batch_size, 1, input_shape)` when `label` parameter is specified.
    :rtype: `np.ndarray`
    """
    # Check value of label for computing gradients
    if not (
        label is None
        or (isinstance(label, (int, np.integer)) and label in range(self.nb_classes))
        or (
            isinstance(label, np.ndarray)
            and len(label.shape) == 1
            and (label < self._nb_classes).all()
            and label.shape[0] == x.shape[0]
        )
    ):
        raise ValueError("Label %s is out of range." % label)

    self._init_class_grads(label=label, logits=logits)

    x_ = self._apply_processing(x)

    # Create feed_dict
    fd = {self._input_ph: x_}
    fd.update(self._feed_dict)

    # Compute the gradient and return
    if label is None:
        # Compute the gradients w.r.t. all classes
        if logits:
            grads = self._sess.run(self._logit_class_grads, feed_dict=fd)
        else:
            grads = self._sess.run(self._class_grads, feed_dict=fd)

        grads = np.swapaxes(np.array(grads), 0, 1)
        grads = self._apply_processing_gradient(grads)

    elif isinstance(label, (int, np.integer)):
        # Compute the gradients only w.r.t. the provided label
        if logits:
            grads = self._sess.run(self._logit_class_grads[label], feed_dict=fd)
        else:
            grads = self._sess.run(self._class_grads[label], feed_dict=fd)

        grads = grads[None, ...]
        grads = np.swapaxes(np.array(grads), 0, 1)
        grads = self._apply_processing_gradient(grads)

    else:
        # For each sample, compute the gradients w.r.t. the indicated target class (possibly distinct)
        unique_label = list(np.unique(label))
        if logits:
            grads = self._sess.run(
                [self._logit_class_grads[l] for l in unique_label], feed_dict=fd
            )
        else:
            grads = self._sess.run(
                [self._class_grads[l] for l in unique_label], feed_dict=fd
            )

        grads = np.swapaxes(np.array(grads), 0, 1)
        lst = [unique_label.index(i) for i in label]
        grads = np.expand_dims(grads[np.arange(len(grads)), lst], axis=1)

        grads = self._apply_processing_gradient(grads)

    return grads