class_docstr: Implementation of the composite adversarial attack on image classifiers in PyTorch. The attack is constructed by
  adversarially perturbing the hue component of the inputs. It uses order scheduling to search for the attack sequence
  and uses the iterative gradient sign method to optimize the perturbations in semantic space and Lp-ball (see
  `FastGradientMethod` and `BasicIterativeMethod`).
  
  | Note that this attack is intended for only PyTorch image classifiers with RGB images in the range [0, 1] as inputs
  
  | Paper link: https://arxiv.org/abs/2202.04235
class_docstr_tok: ["Implementation","of","the","composite","adversarial","attack","on","image","classifiers","in","PyTorch",".","The","attack","is","constructed","by","adversarially","perturbing","the","hue","component","of","the","inputs",".","It","uses","order","scheduling","to","search","for","the","attack","sequence","and","uses","the","iterative","gradient","sign","method","to","optimize","the","perturbations","in","semantic","space","and","Lp-ball","(","see","`","FastGradientMethod","`","and","`","BasicIterativeMethod","`",")",".","|","Note","that","this","attack","is","intended","for","only","PyTorch","image","classifiers","with","RGB","images","in","the","range","[","0",",","1","]","as","inputs","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/2202.04235"]
docstr: Update the specified attack ordering.
  
  :param images: A tensor of a batch of original inputs to be attacked.
  :param labels: A tensor of a batch of the original labels to be predicted.
  :param adv_val: Optional; A list of a batch of current attack parameters.
docstr_tok: ["Update","the","specified","attack","ordering",".",":","param","images",":","A","tensor","of","a","batch","of","original","inputs","to","be","attacked",".",":","param","labels",":","A","tensor","of","a","batch","of","the","original","labels","to","be","predicted",".",":","param","adv_val",":","Optional",";","A","list","of","a","batch","of","current","attack","parameters","."]
code: def update_attack_order(
      self,
      images: "torch.Tensor",
      labels: "torch.Tensor",
      adv_val: List,
  ) -> None:
      """
      Update the specified attack ordering.
  
      :param images: A tensor of a batch of original inputs to be attacked.
      :param labels: A tensor of a batch of the original labels to be predicted.
      :param adv_val: Optional; A list of a batch of current attack parameters.
      """
      import torch
      import torch.nn.functional as F
  
      def hungarian(matrix_batch):
          sol = torch.tensor(
              [-i for i in range(1, matrix_batch.shape[0] + 1)],
              dtype=torch.int32,
          )
          for i in range(matrix_batch.shape[0]):
              topk = 1
              sol[i] = torch.topk(matrix_batch[i], topk)[1][topk - 1]
              while sol.shape != torch.unique(sol).shape:
                  topk = topk + 1
                  sol[i] = torch.topk(matrix_batch[i], topk)[1][
                      topk - 1
                  ]
          return sol
  
      def sinkhorn_normalization(ori_dsm, n_iters=20):
          for _ in range(n_iters):
              ori_dsm /= ori_dsm.sum(dim=0, keepdim=True)
              ori_dsm /= ori_dsm.sum(dim=1, keepdim=True)
          return ori_dsm
  
      if self.attack_order == "fixed":
          if self.curr_seq.sum() == 0:
              self.fixed_order = tuple(
                  self.enabled_attack.index(i) for i in self.fixed_order
              )
              self.curr_seq = torch.tensor(
                  self.fixed_order, device=self.device
              )
      elif self.attack_order == "random":
          self.curr_seq = torch.randperm(self.seq_num)
      elif self.attack_order == "scheduled":
          if self.curr_seq.sum() == 0:
              self.curr_dsm = sinkhorn_normalization(
                  torch.rand((self.seq_num, self.seq_num))
              )
              self.curr_seq = hungarian(self.curr_dsm)
          self.curr_dsm = self.curr_dsm.detach().requires_grad_()
          adv_img = images.clone().detach().requires_grad_()
          original_iter_num = self.max_inner_iter
          self.max_inner_iter = 3
          self._is_scheduling = True
          for tdx in range(self.seq_num):
              prev_img = adv_img.clone()
              adv_img = torch.zeros_like(adv_img)
              for idx in range(self.seq_num):
                  _adv_img, _ = self.attack_dict[idx](
                      prev_img, adv_val[idx], labels
                  )
                  adv_img = adv_img + self.curr_dsm[tdx][idx] * _adv_img
          self._is_scheduling = False
          self.max_inner_iter = original_iter_num
          outputs = self.model(adv_img)
          with torch.enable_grad():
              cost = F.cross_entropy(outputs, labels)
  
          dsm_grad = torch.autograd.grad(cost, self.curr_dsm)[0]
  
          prev_seq = self.curr_seq.clone()
          dsm_noise = torch.zeros_like(self.curr_dsm)
          while torch.equal(prev_seq, self.curr_seq):
              self.curr_dsm = sinkhorn_normalization(
                  torch.exp(
                      self.curr_dsm + dsm_grad + dsm_noise
                  ).detach()
              )
              self.curr_seq = hungarian(self.curr_dsm.detach())
              dsm_noise = (
                  torch.randn_like(self.curr_dsm) + 1
              ) * 2  # Escaping local optimum
      else:
          raise ValueError()
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, Tuple, List, TYPE_CHECKING
  import numpy
  from tqdm.auto import tqdm
  from art.attacks.attack import EvasionAttack
  from art.config import ART_NUMPY_DTYPE
  from art.estimators.estimator import BaseEstimator, LossGradientsMixin
  from art.estimators.classification.classifier import ClassifierMixin
  from art.utils import compute_success, check_and_transform_label_format
label_desc: Use image node_id 13 for calling the CompositeAdversarialAttackPyTorch obj's underlying member method code with example usage: obj.update_attack_order(images, labels, adv_val) and returns: sol, ori_dsm