def empirical_robustness(
    classifier: "CLASSIFIER_TYPE",
    x: np.ndarray,
    attack_name: str,
    attack_params: dict[str, Any] | None = None,
) -> float | np.ndarray:
    """
    Compute the Empirical Robustness of a classifier object over the sample `x` for a given adversarial crafting
    method `attack`. This is equivalent to computing the minimal perturbation that the attacker must introduce for a
    successful attack.

    | Paper link: https://arxiv.org/abs/1511.04599

    :param classifier: A trained model.
    :param x: Data sample of shape that can be fed into `classifier`.
    :param attack_name: A string specifying the attack to be used as a key to `art.metrics.metrics.SUPPORTED_METHODS`.
    :param attack_params: A dictionary with attack-specific parameters. If the attack has a norm attribute, then it will
                          be used as the norm for calculating the robustness; otherwise the standard Euclidean distance
                          is used (norm=2).
    :return: The average empirical robustness computed on `x`.
    """
    crafter = get_crafter(classifier, attack_name, attack_params)
    crafter.set_params(**{"minimal": True})
    adv_x = crafter.generate(x)

    # Predict the labels for adversarial examples
    y = classifier.predict(x)
    y_pred = classifier.predict(adv_x)

    idxs = np.argmax(y_pred, axis=1) != np.argmax(y, axis=1)
    if np.sum(idxs) == 0.0:
        return 0.0

    norm_type = 2
    if hasattr(crafter, "norm"):
        norm_type = crafter.norm  # type: ignore
    perts_norm = la.norm((adv_x - x).reshape(x.shape[0], -1), ord=norm_type, axis=1)
    perts_norm = perts_norm[idxs]

    return np.mean(perts_norm / la.norm(x[idxs].reshape(np.sum(idxs), -1), ord=norm_type, axis=1))

    Compute the Empirical Robustness of a classifier object over the sample `x` for a given adversarial crafting
    method `attack`. This is equivalent to computing the minimal perturbation that the attacker must introduce for a
    successful attack.

    | Paper link: https://arxiv.org/abs/1511.04599

    :param classifier: A trained model.
    :param x: Data sample of shape that can be fed into `classifier`.
    :param attack_name: A string specifying the attack to be used as a key to `art.metrics.metrics.SUPPORTED_METHODS`.
    :param attack_params: A dictionary with attack-specific parameters. If the attack has a norm attribute, then it will
                          be used as the norm for calculating the robustness; otherwise the standard Euclidean distance
                          is used (norm=2).
    :return: The average empirical robustness computed on `x`.
    
art/metrics/metrics.py