多准则决策分析器 mcda-analyzer

多准则决策分析器是一个AI驱动的决策支持工具,提供层次分析法(AHP)、TOPSIS逼近理想解排序法和加权评分方法等专业分析功能。该工具能够帮助用户进行复杂决策分析、方案排序、敏感性测试和可视化呈现,适用于项目评估、供应商选择、投资决策等多种场景。关键词:多准则决策分析,AHP层次分析法,TOPSIS排序,加权评分,决策支持系统,敏感性分析,方案评估,决策可视化。

AI应用 0 次安装 0 次浏览 更新于 2/25/2026

name: mcda-analyzer description: 多准则决策分析技能,包含AHP、TOPSIS和加权评分方法。 allowed-tools: Bash(*) Read Write Edit Glob Grep WebFetch metadata: author: babysitter-sdk version: “1.0.0” category: decision-analysis backlog-id: SK-IE-032

mcda-analyzer

你是 mcda-analyzer - 一个专门用于多准则决策分析的技能,包含AHP、TOPSIS和加权评分方法。

概述

此技能支持AI驱动的决策分析,包括:

  • 层次分析法(AHP)
  • TOPSIS(逼近理想解排序法)
  • 加权评分方法
  • 成对比较矩阵
  • 一致性比率计算
  • 敏感性分析
  • 决策可视化
  • 准则权重分配

能力

1. 层次分析法(AHP)

import numpy as np
import pandas as pd

def ahp_analysis(criteria: list, pairwise_matrix: np.ndarray):
    """
    用于准则权重分配的层次分析法

    criteria: 准则名称列表
    pairwise_matrix: n x n 成对比较矩阵
    """
    n = len(criteria)

    # 计算优先向量(主特征向量)
    # 简化:归一化列平均法
    col_sums = pairwise_matrix.sum(axis=0)
    normalized = pairwise_matrix / col_sums
    priorities = normalized.mean(axis=1)

    # 计算一致性
    weighted_sum = pairwise_matrix @ priorities
    lambda_max = np.mean(weighted_sum / priorities)

    # 一致性指数
    ci = (lambda_max - n) / (n - 1) if n > 1 else 0

    # 随机指数(n = 1 到 10)
    ri_values = {1: 0, 2: 0, 3: 0.58, 4: 0.90, 5: 1.12,
                 6: 1.24, 7: 1.32, 8: 1.41, 9: 1.45, 10: 1.49}
    ri = ri_values.get(n, 1.49)

    # 一致性比率
    cr = ci / ri if ri > 0 else 0

    return {
        "criteria": criteria,
        "priorities": dict(zip(criteria, priorities)),
        "lambda_max": round(lambda_max, 4),
        "consistency_index": round(ci, 4),
        "consistency_ratio": round(cr, 4),
        "is_consistent": cr < 0.10,
        "interpretation": "一致" if cr < 0.10 else "不一致 - 请修正判断"
    }

def create_pairwise_matrix(judgments: dict, criteria: list):
    """
    根据判断创建成对比较矩阵

    judgments: {(准则1, 准则2): 值},其中值为相对重要性
    标度:1=同等重要,3=稍微重要,5=明显重要,7=强烈重要,9=极端重要
    """
    n = len(criteria)
    matrix = np.ones((n, n))

    idx = {c: i for i, c in enumerate(criteria)}

    for (c1, c2), value in judgments.items():
        i, j = idx[c1], idx[c2]
        matrix[i, j] = value
        matrix[j, i] = 1 / value

    return matrix

2. TOPSIS分析

def topsis_analysis(alternatives: list, criteria: list, decision_matrix: np.ndarray,
                   weights: list, criteria_types: list):
    """
    TOPSIS(逼近理想解排序法)

    alternatives: 备选方案名称列表
    criteria: 准则名称列表
    decision_matrix: m个备选方案 x n个准则的矩阵
    weights: 准则权重(总和为1)
    criteria_types: 每个准则的类型列表,'benefit'(效益型)或'cost'(成本型)
    """
    m, n = decision_matrix.shape

    # 步骤1:归一化决策矩阵
    # 向量归一化
    norm_divisors = np.sqrt((decision_matrix ** 2).sum(axis=0))
    normalized = decision_matrix / norm_divisors

    # 步骤2:加权归一化矩阵
    weighted = normalized * weights

    # 步骤3:确定理想解和反理想解
    ideal = np.zeros(n)
    anti_ideal = np.zeros(n)

    for j in range(n):
        if criteria_types[j] == 'benefit':
            ideal[j] = weighted[:, j].max()
            anti_ideal[j] = weighted[:, j].min()
        else:  # 成本型准则
            ideal[j] = weighted[:, j].min()
            anti_ideal[j] = weighted[:, j].max()

    # 步骤4:计算距离
    dist_to_ideal = np.sqrt(((weighted - ideal) ** 2).sum(axis=1))
    dist_to_anti = np.sqrt(((weighted - anti_ideal) ** 2).sum(axis=1))

    # 步骤5:计算相对贴近度
    closeness = dist_to_anti / (dist_to_ideal + dist_to_anti)

    # 备选方案排序
    ranking = np.argsort(-closeness) + 1  # 1为最佳

    results = []
    for i, alt in enumerate(alternatives):
        results.append({
            'alternative': alt,
            'closeness_coefficient': round(closeness[i], 4),
            'distance_to_ideal': round(dist_to_ideal[i], 4),
            'distance_to_anti_ideal': round(dist_to_anti[i], 4),
            'rank': int(ranking[i])
        })

    results.sort(key=lambda x: x['rank'])

    return {
        "ranking": results,
        "best_alternative": results[0]['alternative'],
        "ideal_solution": dict(zip(criteria, ideal)),
        "anti_ideal_solution": dict(zip(criteria, anti_ideal))
    }

3. 加权评分方法

def weighted_scoring(alternatives: list, criteria: list,
                    scores: np.ndarray, weights: list):
    """
    简单加权评分方法

    alternatives: 备选方案名称列表
    criteria: 准则名称列表
    scores: m x n 分数矩阵(通常为0-10分制)
    weights: 准则权重(总和为1)
    """
    # 计算加权分数
    weighted_scores = scores * weights
    total_scores = weighted_scores.sum(axis=1)

    # 排序
    ranking = np.argsort(-total_scores) + 1

    results = []
    for i, alt in enumerate(alternatives):
        criterion_contributions = dict(zip(criteria, weighted_scores[i]))
        results.append({
            'alternative': alt,
            'total_score': round(total_scores[i], 2),
            'criterion_scores': criterion_contributions,
            'rank': int(ranking[i])
        })

    results.sort(key=lambda x: x['rank'])

    return {
        "ranking": results,
        "best_alternative": results[0]['alternative'],
        "score_range": {
            "max": round(max(total_scores), 2),
            "min": round(min(total_scores), 2),
            "spread": round(max(total_scores) - min(total_scores), 2)
        }
    }

4. 敏感性分析

def sensitivity_analysis(base_weights: list, criteria: list, decision_matrix: np.ndarray,
                        alternatives: list, criteria_types: list, method: str = 'topsis'):
    """
    分析排序对权重变化的敏感性
    """
    n_criteria = len(criteria)
    sensitivity_results = []

    for i in range(n_criteria):
        # 权重从0到0.5变化
        weight_variations = np.linspace(0, 0.5, 11)

        criterion_sensitivity = []
        for new_weight in weight_variations:
            # 按比例重新分配剩余权重
            remaining = 1 - new_weight
            modified_weights = np.array(base_weights) * (remaining / (1 - base_weights[i]))
            modified_weights[i] = new_weight

            if method == 'topsis':
                result = topsis_analysis(alternatives, criteria, decision_matrix,
                                        modified_weights, criteria_types)
            else:
                result = weighted_scoring(alternatives, criteria, decision_matrix,
                                         modified_weights)

            criterion_sensitivity.append({
                'weight': new_weight,
                'best_alternative': result['best_alternative'],
                'ranking': [r['alternative'] for r in result['ranking']]
            })

        # 查找切换点
        switching_points = []
        for j in range(1, len(criterion_sensitivity)):
            if criterion_sensitivity[j]['best_alternative'] != criterion_sensitivity[j-1]['best_alternative']:
                switching_points.append({
                    'weight': criterion_sensitivity[j]['weight'],
                    'from': criterion_sensitivity[j-1]['best_alternative'],
                    'to': criterion_sensitivity[j]['best_alternative']
                })

        sensitivity_results.append({
            'criterion': criteria[i],
            'base_weight': base_weights[i],
            'variations': criterion_sensitivity,
            'switching_points': switching_points,
            'is_sensitive': len(switching_points) > 0
        })

    return {
        "sensitivity": sensitivity_results,
        "most_sensitive_criterion": max(sensitivity_results,
                                        key=lambda x: len(x['switching_points']))['criterion'],
        "robust_range": identify_robust_range(sensitivity_results)
    }

def identify_robust_range(sensitivity_results):
    """识别排序稳定的权重范围"""
    # 简化 - 查找最窄的切换间隙
    for result in sensitivity_results:
        if result['switching_points']:
            return {"criterion": result['criterion'],
                   "stable_up_to": result['switching_points'][0]['weight']}
    return {"status": "排序在所有权重变化中均稳健"}

5. 准则权重分配方法

def rank_order_centroid(n_criteria: int, ranking: list = None):
    """
    排序中心法(ROC)用于权重生成

    ranking: 排序列表(1 = 最重要)
    """
    if ranking is None:
        ranking = list(range(1, n_criteria + 1))

    weights = []
    for rank in ranking:
        weight = sum(1/j for j in range(rank, n_criteria + 1)) / n_criteria
        weights.append(weight)

    return {
        "method": "ROC",
        "weights": weights,
        "normalized_weights": [w / sum(weights) for w in weights]
    }

def swing_weights(criteria: list, swings: dict):
    """
    摆动权重法

    swings: {准则: 摆动值},其中最高值 = 最重要
    """
    max_swing = max(swings.values())
    weights = {c: swings[c] / max_swing for c in criteria}
    total = sum(weights.values())
    normalized = {c: w / total for c, w in weights.items()}

    return {
        "method": "Swing Weights",
        "raw_weights": weights,
        "normalized_weights": normalized
    }

6. 决策矩阵可视化

def create_decision_summary(alternatives: list, criteria: list,
                           decision_matrix: np.ndarray, weights: list,
                           ranking_result: dict):
    """
    创建综合决策摘要
    """
    summary = {
        "decision_matrix": pd.DataFrame(
            decision_matrix,
            index=alternatives,
            columns=criteria
        ).to_dict(),
        "criteria_weights": dict(zip(criteria, weights)),
        "ranking": ranking_result['ranking'],
        "recommendation": {
            "best_choice": ranking_result['best_alternative'],
            "confidence": assess_confidence(ranking_result)
        },
        "visualization_data": {
            "spider_chart": prepare_spider_chart_data(alternatives, criteria, decision_matrix),
            "bar_chart": prepare_bar_chart_data(ranking_result)
        }
    }

    return summary

def assess_confidence(result):
    """评估建议的置信度"""
    scores = [r['total_score'] if 'total_score' in r else r['closeness_coefficient']
              for r in result['ranking']]
    if len(scores) >= 2:
        gap = scores[0] - scores[1]
        if gap > 0.2:
            return "高 - 明显优胜者"
        elif gap > 0.1:
            return "中 - 有一定区分度"
        else:
            return "低 - 备选方案接近"
    return "N/A"

def prepare_spider_chart_data(alternatives, criteria, matrix):
    """为蜘蛛图/雷达图准备数据"""
    # 归一化到0-1范围以便可视化
    normalized = (matrix - matrix.min(axis=0)) / (matrix.max(axis=0) - matrix.min(axis=0) + 0.0001)
    return {alt: dict(zip(criteria, normalized[i])) for i, alt in enumerate(alternatives)}

def prepare_bar_chart_data(result):
    """为排序条形图准备数据"""
    return [{"alternative": r['alternative'],
             "score": r.get('total_score', r.get('closeness_coefficient'))}
            for r in result['ranking']]

流程集成

此技能与以下流程集成:

  • multi-criteria-decision-analysis.js
  • supplier-selection-evaluation.js
  • project-prioritization.js

输出格式

{
  "method": "TOPSIS",
  "ranking": [
    {"alternative": "选项A", "score": 0.72, "rank": 1},
    {"alternative": "选项C", "score": 0.65, "rank": 2},
    {"alternative": "选项B", "score": 0.48, "rank": 3}
  ],
  "weights": {"成本": 0.3, "质量": 0.4, "交付": 0.3},
  "sensitivity": {
    "most_sensitive": "质量",
    "robust": true
  },
  "recommendation": {
    "best_choice": "选项A",
    "confidence": "高"
  }
}

最佳实践

  1. 明确定义准则 - 可衡量、独立的准则
  2. 利益相关者参与 - 就权重达成共识
  3. 测试敏感性 - 理解稳健性
  4. 记录理由 - 记录判断依据
  5. 考虑多种方法 - 比较结果
  6. 必要时迭代 - 基于洞察进行优化

约束

  • AHP有效准则数量限制在约9个
  • 需要一致的判断
  • 权重确定可能具有主观性
  • 结果取决于准则选择