OD(攻防)评分法是HITS(超链接诱导主题搜索)算法的一个非线性情形下的类似算法。OD法顾名思义,就是有两个评分向量,一个评分向量能反映一支队伍的进攻能力,称为进攻向量,另一个评分向量能反映一支队伍的防守能力,称为防守向量。这两个向量相互依赖,与HITS评分算法中的枢纽评分和权威评分非常相似。
为了方便理解,举一个5只队伍比赛的简单例子。
设队伍数目为n,aij = 队伍 j 从队伍 i 身上取得的分数,进攻评分向量为o,防守评分向量为d。定义队伍j的攻击评分为oj = a1j/d1 + a2j/d2 + ... + anj/dn 。类似地,定义队伍j的防守评分为dj = aj1/o1 + aj2/o2 + ... + ajn/on 。攻击评分越大说明攻击力越强,防守评分最大说明防守能力越弱。若想得到一个单一的评分值,那么可以采取的一种方法是ri = oi / di,ri 越大越好。
攻防评分法的程序实现如下:
#include <cstdio> #include <cmath> int main() { const int n = 5; double A[][n] = {{0,52,24,38,45},{7,0,16,17,7},{21,34,0,5,30},{7,25,7,0,52},{0,27,3,14,0}}; /* 将矩阵A转置,得到矩阵W */ double W[n][n]; int i, j; for(i = 0; i < n; i++) { for(j = 0; j < n; j++) { W[i][j] = A[j][i]; } } /* 初始化防守向量d */ double d[n]; for(i = 0; i < n; i++) { d[i] = 1.0; } /* 迭代计算防守向量d */ double ep = 0.00001; double maxBias; double dNew[n]; double o[n]; do { maxBias = 0.0; /* 计算进攻向量的倒数向量 */ for(i = 0; i < n; i++) { o[i] = 0.0; for(j = 0; j < n; j++) { o[i] += W[i][j] / d[j]; } } /* 计算新的防守向量 */ for(i = 0; i < n; i++) { dNew[i] = 0.0; for(j = 0; j < n; j++) { dNew[i] += A[i][j] / o[j]; } } for(i = 0; i < n; i++) { if(fabs(dNew[i] - d[i]) > maxBias) maxBias = fabs(dNew[i] - d[i]); d[i] = dNew[i]; } }while(maxBias > ep); /* 计算进攻向量 */ for(i = 0; i < n; i++) { o[i] = 0.0; for(j = 0; j < n; j++) { o[i] += W[i][j] / d[j]; } } for(i = 0; i < n; i++) { printf("%d: %-10.4lf%-10.4lf\t%-10.4lf\n", i, d[i], o[i], o[i]/d[i]); } return 0; }
程序运行结果如下:
每行表示一支队伍的得分,第一列是队伍编号,第二列是防守评分,第三列是进攻评分,第四列是总分,即进攻评分 / 防守评分。由结果易看出队伍0(Duke)的防守分数最大(1.6913),防守能力最弱,攻击分数最小(33.9893),攻击能力最弱,总分最低,实力最差。由总分可以对五支队伍的实力排序,由强到弱依次为队伍4、队伍1、队伍3、队伍2、队伍0,相应的队伍名称依次为VT 、Miami 、UVA 、UNC 、Duke 。