利用灰色关联法确定指标权重

利用灰色关联法确定指标权重

1. 基本思想

对于两个系统之间的因素,其随时间或不同对象而变化的关联性大小的量度,称为关联度。在系统发展过程中,若两个因素变化的趋势具有一致性,即同步变化程度较高,即可谓二者关联程度较高;反之,则较低。因此,灰色关联分析方法,是根据因素之间发展趋势的相似或相异程度,亦即“灰色关联度”,作为衡量因素间关联程度的一种方法。
(引自: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)

2. 计算步骤

(1)确定反映系统行为特征的参考数列和影响系统行为的比较数列。
(2)对参考数列和比较数列进行无量纲化处理。
(3)求参考数列与比较数列的灰色关联系数。
(4)求权重系数关联度,计算出权重
(5)对权重值进行归一化处理。

3. 代码实现

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;
    }
}

4. 总结

灰色关联分析法弥补了采用数理统计方法作系统分析所导致的遗憾。它对样本量的多少和样本有无规律都同样适用,而且计算量小,十分方便,更不会出现量化结果与定性分析结果不符的情况。但是要利用该方法,这个系统必须是灰色系统。灰色系统中灰的主要含义是信息不完全性(部分性)和非唯一性,其中的“非唯一性”是灰色系统的重要特征,非唯一性原理在决策上的体现是灰靶思想,即体现的是决策多目标、方法多途径,处理态度灵活机动。

你可能感兴趣的:(Java,矩阵,java)