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 。