-
 FastGradientMethod
      "norm",
        "eps",
        "eps_step",
        "targeted",
        "num_random_init",
        "batch_size",
        "minimal",
        "summary_writer",
FrameSaliencyAttack
       "attacker",
        "method",
        "frame_index",
        "batch_size",
        "verbose",
FeatureAdversariesPyTorch
        "delta",
        "optimizer",
        "optimizer_kwargs",
        "lambda_",
        "layer",
        "max_iter",
        "batch_size",
        "step_size",
        "random_start",
        "verbose",
GeoDA
        "batch_size",
        "norm",
        "sub_dim",
        "max_iter",
        "bin_search_tol",
        "lambda_param",
        "sigma",
        "verbose",

GRAPHITEBlackbox
        "noise_size",
        "net_size",
        "heat_patch_size",
        "heat_patch_stride",
        "heatmap_mode",
        "tr_lo",
        "tr_hi",
        "num_xforms_mask",
        "max_mask_size",
        "rotation_range",
        "beta",
        "eta",
        "num_xforms_boost",
        "num_boost_queries",
        "dist_range",
        "gamma_range",
        "crop_percent_range",
        "off_x_range",
        "off_y_range",
        "blur_kernels",
        "batch_size",

GRAPHITEWhiteboxPyTorch
        "net_size",
        "min_tr",
        "num_xforms",
        "step_size",
        "steps",
        "first_steps",
        "patch_removal_size",
        "patch_removal_interval",
        "num_patches_to_remove",
        "rand_start_epsilon_range",
        "rotation_range",
        "dist_range",
        "gamma_range",
        "crop_percent_range",
        "off_x_range",
        "off_y_range",
        "blur_kernels",
        "batch_size",

 HopSkipJump
        "targeted",
        "norm",
        "max_iter",
        "max_eval",
        "init_eval",
        "init_size",
        "curr_iter",
        "batch_size",
        "verbose",

BasicIterativeMethod
        eps: int | float | np.ndarray = 0.3,
        eps_step: int | float | np.ndarray = 0.1,
        max_iter: int = 100,
        targeted: bool = False,
        batch_size: int = 32,
        verbose: bool = True,
LaserAttack 
        "iterations",
        "laser_generator",
        "image_generator",
        "random_initializations",
        "optimisation_algorithm",
        "debug",
LowProFool
        "n_steps",
        "threshold",
        "lambd",
        "eta",
        "eta_decay",
        "eta_min",
        "norm",
        "importance",
        "verbose",
 MomentumIterativeMethod
         norm: int | float | str = np.inf,
        eps: int | float | np.ndarray = 0.3,
        eps_step: int | float | np.ndarray = 0.1,
        decay: float = 1.0,
        max_iter: int = 100,
        targeted: bool = False,
        batch_size: int = 32,
        verbose: bool = True,

NewtonFool
       max_iter: int = 100,
        eta: float = 0.01,
        batch_size: int = 1,
        verbose: bool = True,

 OverloadPyTorch
        "eps",
        "max_iter",
        "num_grid",
        "batch_size",
PixelAttack 
        th: int | None = None,
        es: int = 1,
        max_iter: int = 100,
        targeted: bool = False,
        verbose: bool = False,
ProjectedGradientDescent
        "norm",
        "eps",
        "eps_step",
        "decay",
        "targeted",
        "num_random_init",
        "batch_size",
        "max_iter",
        "random_eps",
        "summary_writer",
        "verbose",
OverTheAirFlickeringPyTorch
        "eps_step",
        "max_iter",
        "beta_0",
        "beta_1",
        "beta_2",
        "loss_margin",
        "batch_size",
        "start_frame_index",
        "num_frames",
        "round_samples",
        "targeted",
        "verbose",
SaliencyMapMethod
        theta: float = 0.1,
        gamma: float = 1.0,
        batch_size: int = 1,
        verbose: bool = True,
ShadowAttack
        "sigma",
        "nb_steps",
        "learning_rate",
        "lambda_tv",
        "lambda_c",
        "lambda_s",
        "batch_size",
        "targeted",
        "verbose",
ShapeShifter
        "random_transform",
        "box_classifier_weight",
        "box_localizer_weight",
        "rpn_classifier_weight",
        "rpn_localizer_weight",
        "box_iou_threshold",
        "box_victim_weight",
        "box_target_weight",
        "box_victim_cw_weight",
        "box_victim_cw_confidence",
        "box_target_cw_weight",
        "box_target_cw_confidence",
        "rpn_iou_threshold",
        "rpn_background_weight",
        "rpn_foreground_weight",
        "rpn_cw_weight",
        "rpn_cw_confidence",
        "similarity_weight",
        "learning_rate",
        "optimizer",
        "momentum",
        "decay",
        "sign_gradients",
        "random_size",
        "max_iter",
        "texture_as_input",
        "use_spectral",
        "soft_clip",
update code 
import sys
import logging
from pathlib import Path
from typing import Any, Dict, List, Tuple, Type, Optional

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from art.estimators.classification import PyTorchClassifier

# Adjust the system path to include the parent directory
sys.path.append(str(Path(__file__).resolve().parents[0]))

from attacks import (
    AdversarialPatch,
    AdversarialPatchNumpy,
    AdversarialPatchTensorFlowV2,
    AdversarialPatchPyTorch,
    AdversarialTexturePyTorch,
    CarliniWagnerASR,
    AutoAttack,
    AutoProjectedGradientDescent,
    AutoConjugateGradient,
    BrendelBethgeAttack,
    BoundaryAttack,
    CompositeAdversarialAttackPyTorch,
    CarliniL2Method,
    CarliniLInfMethod,
    CarliniL0Method,
    DecisionTreeAttack,
    DeepFool,
    DPatch,
    RobustDPatch,
    ElasticNet,
    FastGradientMethod,
    FrameSaliencyAttack,
    FeatureAdversariesNumpy,
    FeatureAdversariesPyTorch,
    FeatureAdversariesTensorFlowV2,
    GeoDA,
    GRAPHITEBlackbox,
    GRAPHITEWhiteboxPyTorch,
    HighConfidenceLowUncertainty,
    HopSkipJump,
    ImperceptibleASR,
    ImperceptibleASRPyTorch,
    BasicIterativeMethod,
    LaserAttack,
    LowProFool,
    MomentumIterativeMethod,
    NewtonFool,
    OverloadPyTorch,
    MalwareGDTensorFlow,
    PixelAttack,
    ProjectedGradientDescent,
    ProjectedGradientDescentNumpy,
    ProjectedGradientDescentPyTorch,
    ProjectedGradientDescentTensorFlowV2,
    OverTheAirFlickeringPyTorch,
    SaliencyMapMethod,
    ShadowAttack,
    ShapeShifter,
    SimBA,
    SpatialTransformation,
    SquareAttack,
    ThresholdAttack,
    UniversalPerturbation,
    TargetedUniversalPerturbation,
    VirtualAdversarialMethod,
    Wasserstein,
    ZooAttack,
    SignOPTAttack,
)


# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[logging.StreamHandler(sys.stdout)],
)
logger = logging.getLogger(__name__)


class SimpleCNN(nn.Module):
    """A simple convolutional neural network."""

    def __init__(self, num_classes: int) -> None:
        """Initialize the CNN architecture.

        Args:
            num_classes (int): Number of output classes.
        """
        super(SimpleCNN, self).__init__()
        self.conv1: nn.Conv2d = nn.Conv2d(
            in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1
        )
        self.conv2: nn.Conv2d = nn.Conv2d(
            in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1
        )
        self.adaptive_pool: nn.AdaptiveAvgPool2d = nn.AdaptiveAvgPool2d((32, 32))
        self.fc1: nn.Linear = nn.Linear(64 * 32 * 32, 128)
        self.fc2: nn.Linear = nn.Linear(128, num_classes)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        """Define the forward pass.

        Args:
            x (torch.Tensor): Input tensor.

        Returns:
            torch.Tensor: Output logits.
        """
        x = torch.relu(self.conv1(x))
        x = torch.relu(self.conv2(x))
        x = self.adaptive_pool(x)
        x = torch.flatten(x, 1)
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x


def initialize_model(num_classes: int) -> nn.Module:
    """Initialize the CNN model.

    Args:
        num_classes (int): Number of output classes.

    Returns:
        nn.Module: Initialized model.
    """
    try:
        model = SimpleCNN(num_classes=num_classes)
        logger.info("Model initialized successfully.")
        return model
    except Exception as e:
        logger.error(f"Error initializing model: {e}")
        sys.exit(1)


def initialize_classifier(
    model: nn.Module,
    input_shape: Tuple[int, int, int],
    nb_classes: int,
    clip_values: Tuple[float, float],
    learning_rate: float = 0.001,
) -> PyTorchClassifier:
    """Initialize the ART PyTorchClassifier.

    Args:
        model (nn.Module): PyTorch model.
        input_shape (Tuple[int, int, int]): Shape of input data.
        nb_classes (int): Number of classes.
        clip_values (Tuple[float, float]): Min and max values for input data.
        learning_rate (float, optional): Learning rate for optimizer. Defaults to 0.001.

    Returns:
        PyTorchClassifier: Wrapped classifier.
    """
    try:
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=learning_rate)
        classifier = PyTorchClassifier(
            model=model,
            loss=loss_fn,
            optimizer=optimizer,
            input_shape=input_shape,
            nb_classes=nb_classes,
            clip_values=clip_values,
        )
        logger.info("Classifier initialized successfully.")
        return classifier
    except Exception as e:
        logger.error(f"Error initializing classifier: {e}")
        sys.exit(1)


def generate_dummy_data(batch_size: int = 1) -> Tuple[np.ndarray, np.ndarray]:
    """Generate dummy input data and labels.

    Args:
        batch_size (int, optional): Number of samples. Defaults to 1.

    Returns:
        Tuple[np.ndarray, np.ndarray]: Inputs and labels.
    """
    try:
        # Generate random inputs as NumPy arrays
        inputs = np.random.randn(batch_size, 3, 32, 32).astype(np.float32)
        # Generate random labels between 0 and nb_classes - 1
        labels = np.random.randint(0, 1000, size=(batch_size,))
        logger.info("Dummy data generated successfully.")
        return inputs, labels
    except Exception as e:
        logger.error(f"Error generating dummy data: {e}")
        sys.exit(1)


AttackType = Type[Any]  # Define a generic type for attacks


def get_attack_parameters(attack: AttackType) -> Dict[str, Any]:
    """Retrieve default parameters for each attack.

    Args:
        attack (AttackType): The attack class.

    Returns:
        Dict[str, Any]: Dictionary of parameters.
    """
    # Define default parameters for each attack
    default_params: Dict[Type[Any], Dict[str, Any]] = {
        # 1) AdversarialPatch
        AdversarialPatch: {
            "rotation_max": 30,
            "scale_min": 0.5,
            "scale_max": 1.5,
            "learning_rate": 0.01,
            "max_iter": 1000,
            "batch_size": 32,
            "targeted": False,
            "verbose": True,
            "patch_shape": (3, 10, 10),
        },
        AdversarialPatchNumpy: {
            "rotation_max": 30,
            "scale_min": 0.5,
            "scale_max": 1.5,
            "learning_rate": 0.01,
            "max_iter": 1000,
            "batch_size": 32,
            "targeted": False,
            "verbose": True,
            "patch_shape": (3, 10, 10),
        },
        AdversarialPatchTensorFlowV2: {
            "rotation_max": 30,
            "scale_min": 0.5,
            "scale_max": 1.5,
            "learning_rate": 0.01,
            "max_iter": 1000,
            "batch_size": 32,
            "targeted": False,
            "verbose": True,
            "patch_shape": (3, 10, 10),
        },
        AdversarialPatchPyTorch: {
            "rotation_max": 30,
            "scale_min": 0.5,
            "scale_max": 1.5,
            "learning_rate": 0.01,
            "max_iter": 1000,
            "batch_size": 32,
            "targeted": False,
            "verbose": True,
            "patch_shape": (3, 10, 10),
        },
        # 2) AdversarialTexturePyTorch
        AdversarialTexturePyTorch: {
            "patch_height": 10,
            "patch_width": 10,
            "xmin": 0,
            "ymin": 0,
            "step_size": 1.0,
            "max_iter": 1000,
            "batch_size": 32,
            "verbose": True,
        },
        # 3) AutoAttack
        AutoAttack: {
            "norm": "L2",
            "eps": 0.3,
            "eps_step": 0.01,
            "attacks": ["apgd-ce", "apgd-t"],
            "batch_size": 32,
            "estimator_orig": None,  # Should be set to the classifier
            "targeted": False,
            "parallel": True,
        },
        # 4) AutoProjectedGradientDescent
        AutoProjectedGradientDescent: {
            "norm": 2,
            "eps": 0.3,
            "eps_step": 0.01,
            "max_iter": 100,
            "targeted": False,
            "nb_random_init": 5,
            "batch_size": 32,
            "loss_type": "cross_entropy",
            "verbose": True,
        },
        # 5) AutoConjugateGradient
        AutoConjugateGradient: {
            "norm": 2,
            "eps": 0.3,
            "eps_step": 0.01,
            "max_iter": 100,
            "targeted": False,
            "nb_random_init": 5,
            "batch_size": 32,
            "loss_type": "cross_entropy",
            "verbose": True,
        },
        # 6) BrendelBethgeAttack
        BrendelBethgeAttack: {
            "norm": "L2",
            "targeted": False,
            "init_attack": FastGradientMethod,
            "overshoot": 0.02,
            "steps": 10,
            "lr": 0.1,
            "lr_decay": 0.1,
            "lr_num_decay": 5,
            "momentum": 0.9,
            "binary_search_steps": 5,
            "init_size": 0.5,
        },
        # 7) BoundaryAttack
        BoundaryAttack: {
            "targeted": False,
            "delta": 0.01,
            "epsilon": 0.1,
            "step_adapt": 1.0,
            "max_iter": 1000,
            "num_trial": 10,
            "sample_size": 10,
            "init_size": 0.1,
            "batch_size": 32,
            "verbose": True,
        },
        # 8) CompositeAdversarialAttackPyTorch
        CompositeAdversarialAttackPyTorch: {
            "enabled_attack": ["AutoAttack", "DeepFool"],
            "hue_epsilon": 0.05,
            "sat_epsilon": 0.05,
            "rot_epsilon": 0.05,
            "bri_epsilon": 0.05,
            "con_epsilon": 0.05,
            "pgd_epsilon": 0.3,
            "early_stop": True,
            "max_iter": 1000,
            "max_inner_iter": 100,
            "schedule": "linear",
            "batch_size": 32,
            "verbose": True,
        },
        # 9) CarliniL2Method
        CarliniL2Method: {
            "confidence": 0.0,
            "targeted": False,
            "learning_rate": 0.01,
            "max_iter": 1000,
            "binary_search_steps": 9,
            "initial_const": 0.001,
            "max_halving": 10,
            "max_doubling": 5,
            "batch_size": 32,
            "verbose": True,
        },
        # 10) CarliniLInfMethod
        CarliniLInfMethod: {
            "confidence": 0.0,
            "targeted": False,
            "learning_rate": 0.01,
            "max_iter": 1000,
            "binary_search_steps": 9,
            "initial_const": 0.001,
            "max_halving": 10,
            "max_doubling": 5,
            "batch_size": 32,
            "verbose": True,
        },
        # 11) CarliniL0Method
        CarliniL0Method: {
            "confidence": 0.0,
            "targeted": False,
            "learning_rate": 0.01,
            "max_iter": 1000,
            "binary_search_steps": 9,
            "initial_const": 0.001,
            "max_halving": 10,
            "max_doubling": 5,
            "batch_size": 32,
            "verbose": True,
        },
        # 12) DeepFool
        DeepFool: {
            "max_iter": 50,
            "epsilon": 0.02,
            "nb_grads": 10,
            "batch_size": 32,
            "verbose": True,
        },
        # 13) DPatch
        DPatch: {
            "patch_shape": (3, 10, 10),
            "learning_rate": 0.01,
            "max_iter": 1000,
            "batch_size": 32,
            "verbose": True,
        },
        # 14) RobustDPatch
        RobustDPatch: {
            "patch_shape": (3, 10, 10),
            "learning_rate": 0.01,
            "max_iter": 1000,
            "batch_size": 32,
            "patch_location": (16, 16),
            "crop_range": (0.8, 1.2),
            "brightness_range": (0.9, 1.1),
            "rotation_weights": [0.1, 0.2, 0.3],
            "sample_size": 100,
            "targeted": False,
            "summary_writer": None,  # Should be set to a TensorBoard writer if needed
            "verbose": True,
        },
        # 15) ElasticNet
        ElasticNet: {
            "confidence": 0.0,
            "targeted": False,
            "learning_rate": 0.01,
            "max_iter": 1000,
            "beta": 1.0,
            "binary_search_steps": 9,
            "initial_const": 0.001,
            "batch_size": 32,
            "decision_rule": "ENET",
            "verbose": True,
        },
        # Additional attacks and their parameters can be added here
    }
    return default_params.get(attack, {})


def test_attack(
    attack_class: AttackType,
    classifier: PyTorchClassifier,
    inputs: np.ndarray,
    labels: np.ndarray,
) -> None:
    """Test a single adversarial attack.

    Args:
        attack_class (AttackType): The attack class to test.
        classifier (PyTorchClassifier): The classifier to attack.
        inputs (np.ndarray): Input data.
        labels (np.ndarray): True labels.
    """
    attack_name = attack_class.__name__
    logger.info(f"Testing attack: {attack_name}")

    try:
        params = get_attack_parameters(attack_class)

        # Handle special parameters if necessary
        if attack_name in ["AutoAttack"]:
            # Specifically set the estimator_orig parameter if required
            params["estimator_orig"] = classifier

        attack = attack_class(classifier=classifier, **params)
        adversarial_examples = attack.generate(x=inputs, y=labels)
        logger.info(f"{attack_name} performed successfully.")
        # Optionally, you can add more checks or validations here
    except NotImplementedError:
        logger.warning(f"{attack_name} is not implemented for PyTorchClassifier.")
    except TypeError as te:
        logger.error(
            f"Type error while initializing {attack_name}: {te}. Check parameter compatibility."
        )
    except Exception as e:
        logger.error(f"Error performing {attack_name}: {e}")


def get_all_attacks() -> List[AttackType]:
    """Retrieve all attack classes to be tested.

    Returns:
        List[AttackType]: List of attack classes.
    """
    return [
        AdversarialPatch,
        AdversarialPatchNumpy,
        AdversarialPatchTensorFlowV2,
        AdversarialPatchPyTorch,
        AdversarialTexturePyTorch,
        AutoAttack,
        AutoProjectedGradientDescent,
        AutoConjugateGradient,
        BrendelBethgeAttack,
        BoundaryAttack,
        CompositeAdversarialAttackPyTorch,
        CarliniL2Method,
        CarliniLInfMethod,
        CarliniL0Method,
        DeepFool,
        DPatch,
        RobustDPatch,
        ElasticNet,
        FastGradientMethod,
        FrameSaliencyAttack,
        FeatureAdversariesPyTorch,
        GeoDA,
        GRAPHITEBlackbox,
        GRAPHITEWhiteboxPyTorch,
        HighConfidenceLowUncertainty,
        HopSkipJump,
        BasicIterativeMethod,
        LaserAttack,
        LowProFool,
        MomentumIterativeMethod,
        NewtonFool,
        OverloadPyTorch,
        PixelAttack,
        ProjectedGradientDescent,

        ProjectedGradientDescentPyTorch,
        OverTheAirFlickeringPyTorch,
        SaliencyMapMethod,
        ShadowAttack,
        ShapeShifter,
        SimBA,
        SpatialTransformation,
        SquareAttack,
        ThresholdAttack,
        UniversalPerturbation,
        TargetedUniversalPerturbation,
        VirtualAdversarialMethod,
        Wasserstein,
        ZooAttack,
        SignOPTAttack,
    ]


def main() -> None:
    """Main function to execute the end-to-end attack tests."""
    logger.info("Starting end-to-end adversarial attack tests.")

    # Initialize model
    num_classes = 1000
    model = initialize_model(num_classes=num_classes)

    # Initialize classifier
    input_shape = (3, 32, 32)
    clip_values = (0.0, 1.0)
    classifier = initialize_classifier(
        model=model,
        input_shape=input_shape,
        nb_classes=num_classes,
        clip_values=clip_values,
    )

    # Generate dummy data
    inputs, labels = generate_dummy_data(batch_size=1)

    # Retrieve all attacks
    attacks = get_all_attacks()

    # Test each attack
    for attack_class in attacks:
        test_attack(attack_class, classifier, inputs, labels)

    logger.info("All adversarial attack tests completed.")


if __name__ == "__main__":
    main()\