"""
分类指标分析模块; 用于教学模拟用

给定分类场景和指标分析现实合理性并进行可行解的推断
"""

import typing

import warnings
from dataclasses import dataclass
from typing import Dict, List, Optional, Tuple, Union

import numpy as np
from scipy.optimize import minimize


@dataclass
class ClassificationSpec:
    """分类问题规格"""

    n_samples: int
    n_classes: int
    class_distribution: Optional[List[float]] = None  # 类别分布比例

    # 给定的指标
    accuracy: Optional[float] = None
    precision: Optional[Union[float, List[float]]] = None
    recall: Optional[Union[float, List[float]]] = None
    f1_score: Optional[Union[float, List[float]]] = None
    specificity: Optional[Union[float, List[float]]] = None

    # 随机种子
    random_seed: Optional[int] = None


@dataclass
class ValidationResult:
    """验证结果"""

    is_feasible: bool
    error_message: Optional[str] = None
    inferred_metrics: Optional[Dict[str, float]] = None
    confusion_matrix: Optional[np.ndarray] = None


class ClassificationMetricsValidator:
    """分类指标验证器"""

    def __init__(self, spec: ClassificationSpec):
        self.spec = spec
        self.rng = np.random.RandomState(spec.random_seed)

    def validate_and_infer(self) -> ValidationResult:
        """验证指标可行性并推断缺失指标"""

        # 1. 基础验证
        basic_validation = self._validate_basic_constraints()
        if not basic_validation.is_feasible:
            return basic_validation

        # 2. 设置默认类别分布（避免修改原对象）
        class_dist = self.spec.class_distribution
        if class_dist is None:
            class_dist = [1.0 / self.spec.n_classes] * self.spec.n_classes
        else:
            class_dist = class_dist.copy()  # 创建副本避免修改原对象

        # 3. 归一化类别分布
        total_ratio = sum(class_dist)
        normalized_dist = [r / total_ratio for r in class_dist]

        # 4. 根据类别数选择验证策略
        if self.spec.n_classes == 2:
            return self._validate_binary_classification(normalized_dist)
        else:
            return self._validate_multiclass_classification(normalized_dist)

    def _validate_basic_constraints(self) -> ValidationResult:
        """验证基础约束"""

        if self.spec.n_samples <= 0:
            return ValidationResult(False, '样本数必须为正数')

        if self.spec.n_classes < 2:
            return ValidationResult(False, '类别数必须至少为2')

        # 验证指标范围
        for metric_name, metric_value in [
            ('accuracy', self.spec.accuracy),
            ('precision', self.spec.precision),
            ('recall', self.spec.recall),
            ('f1_score', self.spec.f1_score),
            ('specificity', self.spec.specificity),
        ]:
            if metric_value is not None:
                if isinstance(metric_value, (list, np.ndarray)):
                    if any(v < 0 or v > 1 for v in metric_value):
                        return ValidationResult(False, f'{metric_name}必须在[0,1]范围内')
                else:
                    if metric_value < 0 or metric_value > 1:
                        return ValidationResult(False, f'{metric_name}必须在[0,1]范围内')

        return ValidationResult(True)

    def _validate_binary_classification(
        self, class_distribution: typing.Sequence[float]
    ) -> ValidationResult:
        """验证二分类问题"""

        # 计算类别样本数
        n_pos = round(self.spec.n_samples * class_distribution[1])
        n_neg = self.spec.n_samples - n_pos

        # 检查极端情况
        if n_pos == 0 or n_neg == 0:
            return ValidationResult(
                False, f'类别分布导致某类样本数为0（正类：{n_pos}，负类：{n_neg}）'
            )

        # 收集已知指标
        known_metrics = {}
        for metric_name, metric_value in [
            ('accuracy', self.spec.accuracy),
            ('precision', self.spec.precision),
            ('recall', self.spec.recall),
            ('f1_score', self.spec.f1_score),
            ('specificity', self.spec.specificity),
        ]:
            if metric_value is not None:
                known_metrics[metric_name] = metric_value

        # 验证指标组合的数学可行性
        feasibility_check = self._check_mathematical_feasibility(
            n_pos, n_neg, known_metrics
        )
        if not feasibility_check.is_feasible:
            return feasibility_check

        # 推断混淆矩阵
        try:
            confusion_matrix, inferred_metrics = self._infer_binary_confusion_matrix(
                n_pos, n_neg, known_metrics
            )

            # 验证推断结果的数学一致性
            validation_result = self._validate_inferred_metrics(
                known_metrics, inferred_metrics
            )
            if not validation_result.is_feasible:
                return validation_result

            return ValidationResult(
                True, inferred_metrics=inferred_metrics, confusion_matrix=confusion_matrix
            )

        except Exception as e:
            return ValidationResult(False, f'推断过程出错: {str(e)}')

    def _check_mathematical_feasibility(
        self, n_pos: int, n_neg: int, known_metrics: typing.Mapping[str, float]
    ) -> ValidationResult:
        """检查指标组合的数学可行性"""

        # 如果同时给定了precision, recall, accuracy，需要检查是否兼容
        if all(k in known_metrics for k in ['accuracy', 'precision', 'recall']):
            return self._check_precision_recall_accuracy_compatibility(
                n_pos, n_neg, known_metrics
            )

        # 如果给定了F1和其他指标，检查兼容性
        if 'f1_score' in known_metrics and (
            'precision' in known_metrics or 'recall' in known_metrics
        ):
            return self._check_f1_compatibility(known_metrics)

        return ValidationResult(True)

    def _check_precision_recall_accuracy_compatibility(
        self, n_pos: int, n_neg: int, known_metrics: typing.Mapping[str, float]
    ) -> ValidationResult:
        """检查precision, recall, accuracy三者的兼容性"""

        accuracy = known_metrics['accuracy']
        precision = known_metrics['precision']
        recall = known_metrics['recall']

        # 根据recall计算TP的理论值
        tp_from_recall = recall * n_pos
        fn_from_recall = (1 - recall) * n_pos

        # 根据precision计算FP的理论值
        if precision == 0:
            if tp_from_recall > 0:
                return ValidationResult(False, 'precision=0但recall>0，数学上不可能')
            tp_theoretical = 0
            fp_theoretical = 0
        else:
            tp_theoretical = tp_from_recall
            fp_theoretical = tp_from_recall / precision - tp_from_recall

        # 根据accuracy计算TN的理论值
        tn_from_accuracy = accuracy * (n_pos + n_neg) - tp_theoretical

        # 检查TN + FP = n_neg的约束
        total_neg_predictions = tn_from_accuracy + fp_theoretical

        # 允许一定的数值误差和整数舍入误差
        tolerance = 1.5  # 考虑到整数舍入的误差

        if abs(total_neg_predictions - n_neg) > tolerance:
            return ValidationResult(
                False,
                f'指标组合不可行：根据给定指标推算的负样本数({total_neg_predictions:.2f})与实际负样本数({n_neg})不符，'
                f'差异为{abs(total_neg_predictions - n_neg):.2f}，超过容忍范围{tolerance}',
            )

        # 检查所有值是否为非负
        if any(
            v < -tolerance
            for v in [tp_theoretical, fp_theoretical, tn_from_accuracy, fn_from_recall]
        ):
            return ValidationResult(False, '推导出的混淆矩阵包含负值，指标组合不可行')

        # 检查整数约束的可行性
        # 对于小样本，检查是否能找到合理的整数解
        if n_pos <= 20 or n_neg <= 20:  # 小样本情况
            integer_solution = self._find_integer_solution(
                n_pos, n_neg, accuracy, precision, recall
            )
            if integer_solution is None:
                return ValidationResult(False, '在整数约束下找不到满足所有指标的解')

        return ValidationResult(True)

    def _find_integer_solution(
        self, n_pos: int, n_neg: int, accuracy: float, precision: float, recall: float
    ) -> Optional[Tuple[int, int, int, int]]:
        """尝试找到满足整数约束的解"""

        # 枚举所有可能的TP值
        for tp in range(n_pos + 1):
            fn = n_pos - tp

            # 根据precision计算FP
            if precision == 0:
                if tp > 0:
                    continue
                fp = 0
            else:
                if tp == 0:
                    continue
                fp_exact = tp / precision - tp
                fp = round(fp_exact)
                if fp < 0 or fp > n_neg:
                    continue

                # 检查precision约束
                if abs(tp / (tp + fp) - precision) > 0.1:  # 10%的容忍度
                    continue

            tn = n_neg - fp
            if tn < 0:
                continue

            # 检查recall约束
            if tp + fn > 0:
                calc_recall = tp / (tp + fn)
                if abs(calc_recall - recall) > 0.1:  # 10%的容忍度
                    continue

            # 检查accuracy约束
            calc_accuracy = (tp + tn) / (n_pos + n_neg)
            if abs(calc_accuracy - accuracy) > 0.05:  # 5%的容忍度
                continue

            return (tp, fp, fn, tn)

        return None

    def _check_f1_compatibility(
        self, known_metrics: typing.Mapping[str, float]
    ) -> ValidationResult:
        """检查F1分数与precision/recall的兼容性"""

        f1 = known_metrics['f1_score']

        if 'precision' in known_metrics and 'recall' in known_metrics:
            precision = known_metrics['precision']
            recall = known_metrics['recall']

            # 计算理论F1值
            if precision + recall == 0:
                expected_f1 = 0
            else:
                expected_f1 = 2 * precision * recall / (precision + recall)

            if abs(f1 - expected_f1) > 0.01:  # 1%的容忍度
                return ValidationResult(
                    False,
                    f'F1分数({f1})与precision({precision})和recall({recall})不兼容，'
                    f'期望F1值为{expected_f1:.3f}',
                )

        return ValidationResult(True)

    def _infer_binary_confusion_matrix(
        self, n_pos: int, n_neg: int, known_metrics: typing.Mapping[str, float]
    ) -> Tuple[np.ndarray, Dict[str, float]]:
        """推断二分类混淆矩阵"""

        # 如果有足够的约束，直接求解
        if self._has_sufficient_constraints(known_metrics):
            return self._solve_confusion_matrix_directly(n_pos, n_neg, known_metrics)

        # 否则使用优化方法或随机生成
        return self._generate_feasible_confusion_matrix(n_pos, n_neg, known_metrics)

    def _generate_feasible_confusion_matrix(
        self, n_pos: int, n_neg: int, known_metrics: typing.Mapping[str, float]
    ) -> Tuple[np.ndarray, Dict[str, float]]:
        """生成一个满足当前约束的二分类混淆矩阵近似解。"""
        return self._solve_confusion_matrix_directly(n_pos, n_neg, known_metrics)

    def _has_sufficient_constraints(
        self, known_metrics: typing.Mapping[str, float]
    ) -> bool:
        """检查是否有足够的约束来确定混淆矩阵"""

        # 需要至少2个独立的约束
        sufficient_combinations = [
            {'accuracy', 'precision'},
            {'accuracy', 'recall'},
            {'accuracy', 'specificity'},
            {'precision', 'recall'},
            {'precision', 'specificity'},
            {'recall', 'specificity'},
        ]

        known_set = set(known_metrics.keys())
        return any(combo.issubset(known_set) for combo in sufficient_combinations)

    def _solve_confusion_matrix_directly(
        self, n_pos: int, n_neg: int, known_metrics: typing.Mapping[str, float]
    ) -> Tuple[np.ndarray, Dict[str, float]]:
        """直接求解混淆矩阵"""

        if 'precision' in known_metrics and 'recall' in known_metrics:
            # 原有的 precision + recall 组合
            precision = known_metrics['precision']
            recall = known_metrics['recall']

            # 从recall计算TP
            tp = recall * n_pos
            fn = n_pos - tp

            # 从precision计算FP
            if precision == 0:
                if tp > 0:
                    raise ValueError('precision=0但recall>0，数学上不可能')
                fp = 0
            else:
                fp = tp / precision - tp

            tn = n_neg - fp

        elif 'accuracy' in known_metrics and 'precision' in known_metrics:
            # accuracy + precision 组合
            accuracy = known_metrics['accuracy']
            precision = known_metrics['precision']

            n_samples = n_pos + n_neg

            if precision == 0:
                # precision=0 意味着 TP=0
                tp = 0
                fp = 0
                fn = n_pos
                tn = accuracy * n_samples
            elif abs(precision - 0.5) < 1e-9:
                # precision ≈ 0.5 的特殊情况
                if abs(n_neg - accuracy * n_samples) > 1e-9:
                    raise ValueError(
                        f'指标组合不可行: 当 precision=0.5 时，'
                        f'必须满足 n_neg ({n_neg}) ≈ accuracy * n_samples ({accuracy * n_samples:.2f})，'
                        f'但实际差异为 {abs(n_neg - accuracy * n_samples):.2f}'
                    )
                # 欠约束情况，生成一个合理的解
                warnings.warn(
                    '指标组合欠约束: precision=0.5 且约束条件满足时，'
                    '存在多个解，已生成一个可能的解（假设 recall=0.5）'
                )
                tp = n_pos * 0.5
                fn = n_pos - tp
                tn = accuracy * n_samples - tp
                fp = n_neg - tn
            else:
                # 标准情况：求解线性方程组
                denominator = 1 - 2 * precision
                tp = precision * (n_neg - accuracy * n_samples) / denominator
                tn = accuracy * n_samples - tp
                fp = n_neg - tn
                fn = n_pos - tp

        elif 'accuracy' in known_metrics and 'recall' in known_metrics:
            # accuracy + recall 组合
            accuracy = known_metrics['accuracy']
            recall = known_metrics['recall']

            n_samples = n_pos + n_neg

            # TP = recall * n_pos
            tp = recall * n_pos
            fn = n_pos - tp

            # TN = accuracy * n_samples - TP
            tn = accuracy * n_samples - tp
            fp = n_neg - tn

        elif 'accuracy' in known_metrics and 'specificity' in known_metrics:
            # accuracy + specificity 组合
            accuracy = known_metrics['accuracy']
            specificity = known_metrics['specificity']

            n_samples = n_pos + n_neg

            # TN = specificity * n_neg
            tn = specificity * n_neg
            fp = n_neg - tn

            # TP = accuracy * n_samples - TN
            tp = accuracy * n_samples - tn
            fn = n_pos - tp

        elif 'precision' in known_metrics and 'specificity' in known_metrics:
            # precision + specificity 组合
            precision = known_metrics['precision']
            specificity = known_metrics['specificity']

            # TN = specificity * n_neg
            tn = specificity * n_neg
            fp = n_neg - tn

            if precision == 0:
                tp = 0
            elif abs(precision - 1.0) < 1e-9:
                # precision ≈ 1.0 的特殊情况
                if abs(fp) > 1e-9:
                    raise ValueError(
                        f'指标组合不可行: precision=1 要求 FP=0，'
                        f'但根据 specificity 推断 FP={fp:.2f}'
                    )
                # 欠约束情况，生成一个合理的解
                warnings.warn(
                    '指标组合欠约束: precision=1 且 FP=0 时，'
                    '存在多个解，已生成一个可能的解（假设 recall=1）'
                )
                tp = n_pos  # 假设完美分类器
                fn = 0
            else:
                # 标准情况
                tp = precision * fp / (1 - precision)
                fn = n_pos - tp

        elif 'recall' in known_metrics and 'specificity' in known_metrics:
            # recall + specificity 组合
            recall = known_metrics['recall']
            specificity = known_metrics['specificity']

            # TP = recall * n_pos
            tp = recall * n_pos
            fn = n_pos - tp

            # TN = specificity * n_neg
            tn = specificity * n_neg
            fp = n_neg - tn

        else:
            # 其他组合暂未实现
            available_combinations = [
                'precision + recall',
                'accuracy + precision',
                'accuracy + recall',
                'accuracy + specificity',
                'precision + specificity',
                'recall + specificity',
            ]
            current_metrics = list(known_metrics.keys())
            raise NotImplementedError(
                f'约束组合 {current_metrics} 暂未实现。'
                f'支持的组合包括: {available_combinations}'
            )

        # 验证推导出的浮点值是否在理论范围内
        self._validate_derived_values(tp, fp, fn, tn, n_pos, n_neg)

        # 舍入到整数并确保非负
        tp, fp, fn, tn = [max(0, round(x)) for x in [tp, fp, fn, tn]]

        # 调整以严格满足样本数约束
        if tp + fn != n_pos:
            fn = n_pos - tp
            if fn < 0:
                fn = 0
                tp = n_pos

        if fp + tn != n_neg:
            tn = n_neg - fp
            if tn < 0:
                tn = 0
                fp = n_neg

        # 验证结果的合理性
        if tp < 0 or fp < 0 or fn < 0 or tn < 0:
            raise ValueError(f'求解得到负值: TP={tp}, FP={fp}, FN={fn}, TN={tn}')

        confusion_matrix = np.array([[tn, fp], [fn, tp]], dtype=int)
        inferred_metrics = self._calculate_all_metrics_binary(confusion_matrix)

        return confusion_matrix, inferred_metrics

    def _validate_derived_values(
        self, tp: float, fp: float, fn: float, tn: float, n_pos: int, n_neg: int
    ) -> None:
        """验证推导出的混淆矩阵元素是否在合理范围内

        Parameters
        ----------
        - `tp` : `float`
            - 真正例数量
        - `fp` : `float`
            - 假正例数量
        - `fn` : `float`
            - 假负例数量
        - `tn` : `float`
            - 真负例数量
        - `n_pos` : `int`
            - 正样本总数
        - `n_neg` : `int`
            - 负样本总数

        Raises
        ------
        ValueError
            当推导出的值超出合理范围时
        """
        # 允许小的负容忍度以应对浮点误差
        tolerance = 1e-9

        # 检查每个值是否在合理范围内
        if (
            tp > n_pos + tolerance
            or tp < -tolerance
            or fn > n_pos + tolerance
            or fn < -tolerance
            or fp > n_neg + tolerance
            or fp < -tolerance
            or tn > n_neg + tolerance
            or tn < -tolerance
        ):
            raise ValueError(
                f'指标组合不可行: 推导出的混淆矩阵元素超出范围 '
                f'(TP={tp:.2f}, FP={fp:.2f}, FN={fn:.2f}, TN={tn:.2f})。'
                f'有效范围: TP,FN ∈ [0,{n_pos}], FP,TN ∈ [0,{n_neg}]'
            )

        # 检查行列和是否正确
        if abs((tp + fn) - n_pos) > tolerance:
            raise ValueError(
                f'指标组合不可行: 正样本分布不一致 '
                f'(TP + FN = {tp + fn:.2f}, 期望 = {n_pos})'
            )

        if abs((fp + tn) - n_neg) > tolerance:
            raise ValueError(
                f'指标组合不可行: 负样本分布不一致 '
                f'(FP + TN = {fp + tn:.2f}, 期望 = {n_neg})'
            )

    def _calculate_all_metrics_binary(
        self, confusion_matrix: np.ndarray
    ) -> Dict[str, float]:
        """计算所有二分类指标"""

        tn, fp, fn, tp = confusion_matrix.ravel()

        metrics = {}
        total = tp + tn + fp + fn

        metrics['accuracy'] = (tp + tn) / total if total > 0 else 0
        metrics['precision'] = tp / (tp + fp) if (tp + fp) > 0 else 0
        metrics['recall'] = tp / (tp + fn) if (tp + fn) > 0 else 0
        metrics['specificity'] = tn / (tn + fp) if (tn + fp) > 0 else 0

        if metrics['precision'] + metrics['recall'] > 0:
            metrics['f1_score'] = (
                2
                * metrics['precision']
                * metrics['recall']
                / (metrics['precision'] + metrics['recall'])
            )
        else:
            metrics['f1_score'] = 0

        return metrics

    def _validate_inferred_metrics(
        self,
        known_metrics: typing.Mapping[str, float],
        inferred_metrics: typing.Mapping[str, float],
    ) -> ValidationResult:
        """验证推断结果是否与已知指标一致"""

        tolerance = 0.05  # 5%的容忍度

        for metric_name, expected_value in known_metrics.items():
            if metric_name in inferred_metrics:
                actual_value = inferred_metrics[metric_name]
                if abs(actual_value - expected_value) > tolerance:
                    return ValidationResult(
                        False,
                        f'推断的{metric_name}({actual_value:.3f})与期望值({expected_value:.3f})差异过大',
                    )

        return ValidationResult(True)

    def _validate_multiclass_classification(
        self, class_distribution: typing.Sequence[float]
    ) -> ValidationResult:
        """验证多分类问题（简化实现）"""

        # 计算各类别样本数
        class_counts = [
            round(self.spec.n_samples * ratio) for ratio in class_distribution
        ]

        # 调整确保总和正确
        diff = self.spec.n_samples - sum(class_counts)
        class_counts[0] += diff

        try:
            confusion_matrix = self._generate_feasible_multiclass_confusion_matrix(
                class_counts
            )
            inferred_metrics = self._calculate_all_metrics_multiclass(confusion_matrix)

            return ValidationResult(
                True, inferred_metrics=inferred_metrics, confusion_matrix=confusion_matrix
            )
        except Exception as e:
            return ValidationResult(False, f'多分类指标组合不可行: {str(e)}')

    def _generate_feasible_multiclass_confusion_matrix(
        self, class_counts: typing.Sequence[int]
    ) -> np.ndarray:
        """生成可行的多分类混淆矩阵"""

        n_classes = len(class_counts)
        confusion_matrix = np.zeros((n_classes, n_classes), dtype=int)

        target_accuracy = self.spec.accuracy if self.spec.accuracy is not None else 0.8

        for i in range(n_classes):
            class_size = class_counts[i]
            if class_size == 0:
                continue

            # 正确分类的数量
            correct_count = max(0, min(class_size, round(class_size * target_accuracy)))
            incorrect_count = class_size - correct_count

            # 分配正确分类
            confusion_matrix[i, i] = correct_count

            # 分配错误分类
            if incorrect_count > 0:
                other_classes = [j for j in range(n_classes) if j != i]
                if other_classes:
                    errors = self.rng.multinomial(
                        incorrect_count, [1 / len(other_classes)] * len(other_classes)
                    )
                    for j, error_count in enumerate(errors):
                        confusion_matrix[i, other_classes[j]] = error_count

        return confusion_matrix

    def _calculate_all_metrics_multiclass(
        self, confusion_matrix: np.ndarray
    ) -> Dict[str, float]:
        """计算多分类指标"""

        n_classes = confusion_matrix.shape[0]
        metrics = {}

        # 总体准确率
        metrics['accuracy'] = np.trace(confusion_matrix) / np.sum(confusion_matrix)

        # 每类指标
        precisions = []
        recalls = []
        f1_scores = []

        for i in range(n_classes):
            tp = confusion_matrix[i, i]
            fp = np.sum(confusion_matrix[:, i]) - tp
            fn = np.sum(confusion_matrix[i, :]) - tp

            precision = tp / (tp + fp) if (tp + fp) > 0 else 0
            recall = tp / (tp + fn) if (tp + fn) > 0 else 0
            f1 = (
                2 * precision * recall / (precision + recall)
                if (precision + recall) > 0
                else 0
            )

            precisions.append(precision)
            recalls.append(recall)
            f1_scores.append(f1)

        metrics['precision_macro'] = np.mean(precisions)
        metrics['recall_macro'] = np.mean(recalls)
        metrics['f1_score_macro'] = np.mean(f1_scores)

        return metrics


def validate_classification_metrics(spec: ClassificationSpec) -> ValidationResult:
    """验证分类指标并推断缺失值"""
    validator = ClassificationMetricsValidator(spec)
    return validator.validate_and_infer()


# 测试示例
if __name__ == '__main__':
    # 示例1: 二分类，给定accuracy和precision
    print('=== 示例1: 可行的指标组合 ===')
    spec1 = ClassificationSpec(
        n_samples=1000,
        n_classes=2,
        class_distribution=[0.6, 0.4],
        accuracy=0.85,
        precision=0.80,
        random_seed=42,
    )

    result1 = validate_classification_metrics(spec1)
    print(f'可行性: {result1.is_feasible}')
    if result1.is_feasible:
        print(f'推断指标: {result1.inferred_metrics}')
        print(f'混淆矩阵:\n{result1.confusion_matrix}')
    else:
        print(f'错误: {result1.error_message}')

    # 示例2: 不可行的指标组合
    print('\n=== 示例2: 不可行的指标组合 ===')
    spec2 = ClassificationSpec(
        n_samples=100,
        n_classes=2,
        accuracy=0.95,
        precision=0.50,
        recall=0.95,
        random_seed=42,
    )

    result2 = validate_classification_metrics(spec2)
    print(f'可行性: {result2.is_feasible}')
    if not result2.is_feasible:
        print(f'错误: {result2.error_message}')
    else:
        print(f'推断指标: {result2.inferred_metrics}')
        print(f'混淆矩阵:\n{result2.confusion_matrix}')

    # 示例3: 另一个不可行的组合
    print('\n=== 示例3: 另一个不可行的组合 ===')
    spec3 = ClassificationSpec(
        n_samples=50,
        n_classes=2,
        accuracy=0.99,
        precision=0.10,
        recall=0.99,
        random_seed=42,
    )

    result3 = validate_classification_metrics(spec3)
    print(f'可行性: {result3.is_feasible}')
    if not result3.is_feasible:
        print(f'错误: {result3.error_message}')
    else:
        print(f'推断指标: {result3.inferred_metrics}')
