def _comp_pgd(
        self,
        data: "torch.Tensor",
        labels: "torch.Tensor",
        attack_idx: int,
        attack_parameter: "torch.Tensor",
        ori_is_attacked: "torch.Tensor",
    ) -> tuple["torch.Tensor", "torch.Tensor"]:
        """
        Compute the adversarial examples for each attack component.

        :param data: 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 attack_idx: The index of the attack component (one of the enabled attacks) in the attack pool.
        :param attack_parameter: Specify the parameter of the attack component. For example, hue shift angle, saturation
         factor, etc.
        :param ori_is_attacked: Specify whether the perturbed data is already attacked.
        :return: The perturbed data and the corresponding attack parameter.
        """
        import torch
        import torch.nn.functional as F

        adv_data = self.attack_pool_base[attack_idx](data, attack_parameter)
        for _ in range(self.max_inner_iter):
            outputs = self.model(adv_data)

            if not self._is_scheduling and self.early_stop:
                cur_pred = outputs.max(1, keepdim=True)[1].squeeze()
                self.is_attacked = torch.logical_or(
                    ori_is_attacked, cur_pred != labels.max(1, keepdim=True)[1].squeeze()
                )

            with torch.enable_grad():
                cost = F.cross_entropy(outputs, labels)
            _grad = torch.autograd.grad(cost, attack_parameter)[0]
            if not self._is_scheduling:
                _grad[self.is_attacked] = 0
            attack_parameter = (
                torch.clamp(
                    attack_parameter + torch.sign(_grad) * self.step_size_pool[attack_idx],
                    self.eps_pool[attack_idx][0],
                    self.eps_pool[attack_idx][1],
                )
                .detach()
                .requires_grad_()
            )
            adv_data = self.attack_pool_base[attack_idx](data, attack_parameter)

        return adv_data, attack_parameter

        Compute the adversarial examples for each attack component.

        :param data: 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 attack_idx: The index of the attack component (one of the enabled attacks) in the attack pool.
        :param attack_parameter: Specify the parameter of the attack component. For example, hue shift angle, saturation
         factor, etc.
        :param ori_is_attacked: Specify whether the perturbed data is already attacked.
        :return: The perturbed data and the corresponding attack parameter.
        
art/attacks/evasion/composite_adversarial_attack.py