对于两个系统之间的因素,其随时间或不同对象而变化的关联性大小的量度,称为关联度。在系统发展过程中,若两个因素变化的趋势具有一致性,即同步变化程度较高,即可谓二者关联程度较高;反之,则较低。因此,灰色关联分析方法,是根据因素之间发展趋势的相似或相异程度,亦即“灰色关联度”,作为衡量因素间关联程度的一种方法。
(引自:https://baike.baidu.com/item/%E7%81%B0%E8%89%B2%E5%85%B3%E8%81%94%E5%BA%A6%E5%88%86%E6%9E%90%E6%B3%95/4894483)
(1)确定反映系统行为特征的参考数列和影响系统行为的比较数列。
(2)对参考数列和比较数列进行无量纲化处理。
(3)求参考数列与比较数列的灰色关联系数。
(4)求权重系数关联度,计算出权重
(5)对权重值进行归一化处理。
public class CalculateWeight extends Calculate {
public static void main(String[] args) {
String matrixStr = "{\"array\":[{\"name\":\"x1\",\"index\": [1.0,4.0,3.0,4.0,3.0,4.0,4.0,4.0,4.0,4.0,4.0,4.0,3.0,3.0,3.0,3.0,4.0,5.0,3.0,3.0,3.0,3.0,2.0,2.0,3.0,3.0,3.0,3.0,3.0,5.0]},{\"name\":\"x2\",\"index\":[0.5,1.0,1.0,1.0,5.0,6.0,6.0,6.0,3.5,2.0,5.0,5.0,5.0,8.0,8.0,8.0,6.0,3.0,5.0,5.0,2.0,2.0,0.5,0.5,1.0,2.0,2.0,2.0,0.5,0.5]},{\"name\":\"x3\",\"index\":[3.0,3.0,3.0,3.0,5.0,5.0,3.0,3.0,3.0,3.0,5.0,4.0,5.0,5.0,3.0,3.0,3.0,2.0,4.0,3.0,2.0,2.0,2.0,2.0,2.0,2.0,5.0,5.0,2.0,5.0]},{\"name\":\"x4\",\"index\":[1.0,3.5,3.5,2.0,6.0,8.0,2.5,2.5,5.0,5.0,4.5,3.0,0.5,6.0,8.0,5.0,2.0,2.0,5.0,3.0,2.0,1.5,1.0,0.5,3.5,2.0,2.0,1.0,0.5,8.0]},{\"name\":\"x5\",\"index\":[0.0,3.0,3.0,3.0,4.0,3.0,3.0,3.0,3.0,3.0,4.0,3.0,3.0,3.0,3.0,3.0,3.0,3.0,4.0,3.0,3.0,3.0,4.0,4.0,5.0,4.0,4.0,4.0,5.0,3.0]}],\"coefficient\":0.5}";
CalculateWeight calculateWeight = new CalculateWeight();
double[] weightArray = calculateWeight.getWeight(matrixStr);
Arrays.stream(weightArray).forEach(System.out::println);
}
/**
* 计算中间节点的权重
*
* @param matrixStr 重要性矩阵字符串
* @return 权重值数组
*/
@Override
public double[] getWeight(String matrixStr) {
// String paramList = this.getParamList();
if (StringUtils.isEmpty(matrixStr)) {
double[] weight = new double[0];
return weight;
}
JSONObject jsonObject = JSON.parseObject(matrixStr);
// 分辨系数
Double coefficient = jsonObject.getDouble("coefficient");
JSONArray array = jsonObject.getJSONArray("array");
List<List<Double>> lists = new ArrayList<>();
// 0,解析指标权重矩阵
System.out.println("原始数据列,最后一个元素是最值");
for (int i = 0; i < array.size(); i++) {
JSONObject object = array.getJSONObject(i);
JSONArray index = object.getJSONArray("index");
// 1. 构建list并寻找最值 // 2. 确定参考序列
List<Double> doubles = this.jsonArrayToList(index);
lists.add(doubles);
System.out.println(doubles);
}
// 3. 求各个指标序列x1,x2......xn与参考数据列x0直接的距离
for (int k = 0; k < lists.size(); k++) {
List<Double> list = lists.get(k);
this.getDistance(list);
}
System.out.println("计算各个指标序列x1,x2......xn与参考数据列x0直接的距离");
lists.forEach(System.out::println);
// 4. 求各个指标的权重
// 4.1 对新矩阵求最大值和最小值
List<Double> mostValues = new ArrayList<>();
lists.forEach(item -> {
double max = item.stream().mapToDouble(Double::doubleValue).max().getAsDouble();
double min = item.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
mostValues.add(max);
mostValues.add(min);
});
Double max = Collections.max(mostValues);
// System.out.println("max = " + max);
Double min = Collections.min(mostValues);
// System.out.println("min = " + min);
// 4.2 求各个指标的权重关联系数
System.out.println("计算各个指标的权重关联系数");
for (int i = 0; i < lists.size(); i++) {
List<Double> list = lists.get(i);
for (int j = 0; j < list.size(); j++) {
Double k = list.get(j);
double ik = min + (coefficient * max) / (k + (coefficient * max));
int index = j;
list.remove(j);
list.add(index, ik);
}
System.out.println(list);
}
// 5. 求各个指标的归一化权重
// 5.1 控制循环次数
List<Double> foreachNum = lists.get(0);
//用于存放每种指标的最终权重系数
double[] weightArray = new double[foreachNum.size()];
List<Double> weightList = new ArrayList<>();
List<Double> iks = null;
for (int k = 0; k < foreachNum.size(); k++) {
iks = new ArrayList<>();
for (int i = 0; i < lists.size(); i++) {
List<Double> list = lists.get(i);
Double aDouble = list.get(k);
iks.add(aDouble);
}
// 专家人数
double n = lists.size();
double sum = iks.stream().mapToDouble(Double::doubleValue).sum();
double ri = (1d / n) * sum;
// 将计算出的权重添加到集合
weightList.add(ri);
}
// 将权重值归一化
double weightSum = weightList.stream().mapToDouble(Double::doubleValue).sum();
for (int i = 0; i < weightList.size(); i++) {
double weightNormaliation = weightList.get(i) / weightSum;
weightNormaliation = new BigDecimal(weightNormaliation).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue();
weightArray[i] = weightNormaliation;
}
System.out.println("各个指标权重值");
Arrays.stream(weightArray).forEach(System.out::println);
return weightArray;
}
/**
* 计算各个指标序列x1,x2,x3......xn与参考数据类型x0直接的距离
*
* @param list 返回计算以后的指标序列
*/
public void getDistance(List<Double> list) {
for (int i = 0; i < list.size(); i++) {
// 最后一个是x0,不用比较
if (i == list.size() - 1) {
list.remove(i);
continue;
}
double v = list.get(i) - list.get(list.size() - 1);
int index = i;
list.remove(i);
list.add(index, Math.abs(v));
}
}
/**
* 转换数据结构
*
* @param index array
* @return 权重系数矩阵
*/
public List<Double> jsonArrayToList(JSONArray index) {
List<Double> doubles = new ArrayList<>();
for (int i = 0; i < index.size(); i++) {
doubles.add(index.getDouble(i));
}
// 寻找最值
Double max = Collections.max(doubles);
// 放在最后
doubles.add(max);
return doubles;
}
}
灰色关联分析法弥补了采用数理统计方法作系统分析所导致的遗憾。它对样本量的多少和样本有无规律都同样适用,而且计算量小,十分方便,更不会出现量化结果与定性分析结果不符的情况。但是要利用该方法,这个系统必须是灰色系统。灰色系统中灰的主要含义是信息不完全性(部分性)和非唯一性,其中的“非唯一性”是灰色系统的重要特征,非唯一性原理在决策上的体现是灰靶思想,即体现的是决策多目标、方法多途径,处理态度灵活机动。