用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/a5c-ai/babysitter --skill mcda-analyzer命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | mcda-analyzer |
| description | Multi-criteria decision analysis skill with AHP, TOPSIS, and weighted scoring methods. |
| 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"} |
| graph | {"domains":["domain:industrial-engineering"],"skillAreas":["skill-area:statistical-analysis","skill-area:organizational-design","skill-area:data-analysis"],"roles":["role:operations-analyst","role:research-engineer"]} |
You are mcda-analyzer - a specialized skill for multi-criteria decision analysis including AHP, TOPSIS, and weighted scoring methods.
This skill enables AI-powered decision analysis including:
import numpy as np
import pandas as pd
def ahp_analysis(criteria: list, pairwise_matrix: np.ndarray):
"""
Analytic Hierarchy Process for criteria weighting
criteria: list of criterion names
pairwise_matrix: n x n matrix of pairwise comparisons
"""
n = len(criteria)
# Calculate priority vector (principal eigenvector)
# Simplified: normalized column average method
col_sums = pairwise_matrix.sum(axis=0)
normalized = pairwise_matrix / col_sums
priorities = normalized.mean(axis=1)
# Calculate consistency
weighted_sum = pairwise_matrix @ priorities
lambda_max = np.mean(weighted_sum / priorities)
# Consistency Index
ci = (lambda_max - n) / (n - 1) if n > 1 else 0
# Random Index (for n = 1 to 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)
# Consistency Ratio
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": "Consistent" if cr < 0.10 else "Inconsistent - revise judgments"
}
def create_pairwise_matrix(judgments: dict, criteria: list):
"""
Create pairwise comparison matrix from judgments
judgments: {(criterion1, criterion2): value} where value is relative importance
Scale: 1=equal, 3=moderate, 5=strong, 7=very strong, 9=extreme
"""
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
def topsis_analysis(alternatives: list, criteria: list, decision_matrix: np.ndarray,
weights: list, criteria_types: list):
"""
TOPSIS (Technique for Order Preference by Similarity to Ideal Solution)
alternatives: list of alternative names
criteria: list of criterion names
decision_matrix: m alternatives x n criteria matrix
weights: criterion weights (sum to 1)
criteria_types: list of 'benefit' or 'cost' for each criterion
"""
m, n = decision_matrix.shape
# Step 1: Normalize decision matrix
# Vector normalization
norm_divisors = np.sqrt((decision_matrix ** 2).sum(axis=0))
normalized = decision_matrix / norm_divisors
# Step 2: Weighted normalized matrix
weighted = normalized * weights
# Step 3: Determine ideal and anti-ideal solutions
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: # cost criterion
ideal[j] = weighted[:, j].min()
anti_ideal[j] = weighted[:, j].max()
# Step 4: Calculate distances
dist_to_ideal = np.sqrt(((weighted - ideal) ** 2).sum(axis=1))
dist_to_anti = np.sqrt(((weighted - anti_ideal) ** 2).sum(axis=1))
# Step 5: Calculate relative closeness
closeness = dist_to_anti / (dist_to_ideal + dist_to_anti)
# Rank alternatives
ranking = np.argsort(-closeness) +
results = []
i, alt (alternatives):
results.append({
: alt,
: (closeness[i], ),
: (dist_to_ideal[i], ),
: (dist_to_anti[i], ),
: (ranking[i])
})
results.sort(key= x: x[])
{
: results,
: results[][],
: ((criteria, ideal)),
: ((criteria, anti_ideal))
}
def weighted_scoring(alternatives: list, criteria: list,
scores: np.ndarray, weights: list):
"""
Simple weighted scoring method
alternatives: list of alternative names
criteria: list of criterion names
scores: m x n matrix of scores (0-10 scale typical)
weights: criterion weights (sum to 1)
"""
# Calculate weighted scores
weighted_scores = scores * weights
total_scores = weighted_scores.sum(axis=1)
# Rank
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((total_scores) - (total_scores), )
}
}
def sensitivity_analysis(base_weights: list, criteria: list, decision_matrix: np.ndarray,
alternatives: list, criteria_types: list, method: str = 'topsis'):
"""
Analyze sensitivity of ranking to weight changes
"""
n_criteria = len(criteria)
sensitivity_results = []
for i in range(n_criteria):
# Vary weight from 0 to 0.5
weight_variations = np.linspace(0, 0.5, 11)
criterion_sensitivity = []
for new_weight in weight_variations:
# Redistribute remaining weight proportionally
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']]
})
# Find switching points
switching_points = []
for j in (, (criterion_sensitivity)):
criterion_sensitivity[j][] != criterion_sensitivity[j-][]:
switching_points.append({
: criterion_sensitivity[j][],
: criterion_sensitivity[j-][],
: criterion_sensitivity[j][]
})
sensitivity_results.append({
: criteria[i],
: base_weights[i],
: criterion_sensitivity,
: switching_points,
: (switching_points) >
})
{
: sensitivity_results,
: (sensitivity_results,
key= x: (x[]))[],
: identify_robust_range(sensitivity_results)
}
():
result sensitivity_results:
result[]:
{: result[],
: result[][][]}
{: }
def rank_order_centroid(n_criteria: int, ranking: list = None):
"""
Rank Order Centroid (ROC) method for weight generation
ranking: list of ranks (1 = most important)
"""
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):
"""
Swing weighting method
swings: {criterion: swing_value} where highest value = most important
"""
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
}
def create_decision_summary(alternatives: list, criteria: list,
decision_matrix: np.ndarray, weights: list,
ranking_result: dict):
"""
Create comprehensive decision summary
"""
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):
"""Assess confidence in the recommendation"""
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 > :
gap > :
:
():
normalized = (matrix - matrix.(axis=)) / (matrix.(axis=) - matrix.(axis=) + )
{alt: ((criteria, normalized[i])) i, alt (alternatives)}
():
[{: r[],
: r.get(, r.get())}
r result[]]
This skill integrates with the following processes:
multi-criteria-decision-analysis.jssupplier-selection-evaluation.jsproject-prioritization.js{
"method": "TOPSIS",
"ranking": [
{"alternative": "Option A", "score": 0.72, "rank": 1},
{"alternative": "Option C", "score": 0.65, "rank": 2},
{"alternative": "Option B", "score": 0.48, "rank": 3}
],
"weights": {"cost": 0.3, "quality":