# 依赖: numpy import numpy as np def topsis(X, w, benefit=None): X, w = np.asarray(X, float), np.asarray(w, float) if X.ndim != 2 or min(X.shape) < 1 or not np.isfinite(X).all(): raise ValueError('输入必须是非空、有限的二维矩阵') if w.shape != (X.shape[1],) or not np.isfinite(w).all() or np.any(w < 0) or w.sum() <= 0: raise ValueError('权重须与列数对应、非负且总和为正') benefit = np.ones(X.shape[1], bool) if benefit is None else np.asarray(benefit, bool) if benefit.shape != (X.shape[1],): raise ValueError('指标方向数量与列数不一致') norm = np.linalg.norm(X, axis=0) Z = X / np.where(norm > 0, norm, 1) # 全零列保持为 0 Z[:, ~benefit] *= -1 V = Z * (w / w.sum()) d_best = np.linalg.norm(V - V.max(axis=0), axis=1) d_worst = np.linalg.norm(V - V.min(axis=0), axis=1) total = d_best + d_worst # 所有方案无差异时约定同分 0.5,不制造 NaN 或虚假的排序。 return np.divide(d_worst, total, out=np.full(len(X), .5), where=total > 1e-12) print(topsis([[9, 3], [7, 5], [6, 8]], w=[.6, .4], benefit=[True, False]).round(4))