数据挖掘——PageRank算法Java

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class PageRank {
    private static final double ALPHA = 0.85; //阻尼因子
    private static final double DISTANCE = 0.1; // 修改收敛的值

    public static void main(String[] args) {
        System.out.println("alpha的值为: " + ALPHA);
        List<Double> q1 = new ArrayList<Double>();
        q1.add(new Double(1));
        q1.add(new Double(1));
        q1.add(new Double(1));
        q1.add(new Double(1));

        System.out.println("初始的向量q为:");
        printVec(q1);
        System.out.println("初始的矩阵G为:");
        printMatrix(getG(ALPHA));
        List<Double> pageRank = calPageRank(q1, ALPHA);
        System.out.println("PageRank为:");
        printVec(pageRank);
        System.out.println();

        // 对网页的重要性进行排序
        List<String> webPages = new ArrayList<>();
        webPages.add("A");
        webPages.add("B");
        webPages.add("C");
        webPages.add("D");
        sortPageRank(webPages, pageRank);
    }

    /**
     * 打印输出一个矩阵
     * @param m
     */
    public static void printMatrix(List<List<Double>> m) {
        for (int i = 0; i < m.size(); i++) {
            for (int j = 0; j < m.get(i).size(); j++) {
                System.out.printf("%.2f, ", m.get(i).get(j));
            }
            System.out.println();
        }
    }

    /**
     * 打印输出一个向量
     * @param v
     */
    public static void printVec(List<Double> v) {
        for (int i = 0; i < v.size(); i++) {
            System.out.printf("%.2f, ", v.get(i));
        }
        System.out.println();
    }


    /**
     * 计算两个向量之间的距离
     * @param q1 第一个向量
     * @param q2 第二个向量
     * @return 两个向量之间的距离
     */
    public static double calDistance(List<Double> q1, List<Double> q2) {
        double sum = 0;
        if (q1.size() != q2.size()) {
            return -1;
        }
        for (int i = 0; i < q1.size(); i++) {
            sum += Math.abs(q1.get(i).doubleValue() - q2.get(i).doubleValue());
        }
        return sum;
    }

    /**
     * 计算PageRank值
     * @param q1 初始向量q
     * @param a  alpha的值
     * @return PageRank向量
     */
    public static List<Double> calPageRank(List<Double> q1, double a) {
        List<List<Double>> g = getG(a);
        List<Double> q = null;
        int iterCount = 0;
        while (true) {
            q = vectorMulMatrix(g, q1);
            double dis = calDistance(q, q1);

            System.out.println("第" + (iterCount + 1) + "次迭代的距离为:" + dis);
            System.out.println("第" + (iterCount + 1) + "次的PageRank向量为:");
            printVec(q);
            System.out.println();
            iterCount++;//计数器

            if (dis <= DISTANCE) {
                System.out.println("收敛于第" + iterCount + "次迭代。");
                break;
            }
            q1 = q;
        }
        return q;
    }

    /**
     * 计算获得初始的G矩阵
     * @param a 为alpha的值,0.85
     * @return 初始矩阵G
     */
    //计算公式:R = a * R + (1-a) * E / n
    public static List<List<Double>> getG(double a) {

        int n = getS().size();
        List<List<Double>> aS = numberMulMatrix(getS(), a);
        List<List<Double>> nU = numberMulMatrix(getU(), (1 - a) / n);
        List<List<Double>> g = addMatrix(aS, nU);
        return g;
    }

    /**
     * 计算一个矩阵乘以一个向量
     * @param m 一个矩阵
     * @param v 一个向量
     * @return 返回一个新的向量
     */
    public static List<Double> vectorMulMatrix(List<List<Double>> m, List<Double> v) {
        if (m == null || v == null || m.size() <= 0 || m.get(0).size() != v.size()) {
            return null;
        }

        List<Double> list = new ArrayList<Double>();
        for (int i = 0; i < m.size(); i++) {
            double sum = 0;
            for (int j = 0; j < m.get(i).size(); j++) {
                //将矩阵m的第i行第j列的元素与向量v的第j个元素相乘,得到临时变量temp。
                double temp = m.get(i).get(j).doubleValue() * v.get(j).doubleValue();
                sum += temp;
            }
            list.add(sum);
        }

        return list;
    }

    /**
     * 计算两个矩阵的和
     * @param list1 第一个矩阵
     * @param list2 第二个矩阵
     * @return 两个矩阵的和
     */
    public static List<List<Double>> addMatrix(List<List<Double>> list1, List<List<Double>> list2) {
        List<List<Double>> list = new ArrayList<List<Double>>();
        if (list1.size() != list2.size() || list1.size() <= 0 || list2.size() <= 0) {
            return null;
        }
        for (int i = 0; i < list1.size(); i++) {
            list.add(new ArrayList<Double>());
            for (int j = 0; j < list1.get(i).size(); j++) {
                double temp = list1.get(i).get(j).doubleValue() + list2.get(i).get(j).doubleValue();
                list.get(i).add(new Double(temp));
            }
        }
        return list;
    }

    /**
     * 计算一个数乘以矩阵
     * @param s 矩阵s
     * @param a double类型的数
     * @return 一个新的矩阵
     */
    public static List<List<Double>> numberMulMatrix(List<List<Double>> s, double a) {
        List<List<Double>> list = new ArrayList<List<Double>>();

        for (int i = 0; i < s.size(); i++) {
            list.add(new ArrayList<Double>());
            for (int j = 0; j < s.get(i).size(); j++) {
                double temp = a * s.get(i).get(j).doubleValue();
                list.get(i).add(new Double(temp));
            }
        }
        return list;
    }

    /**
     * 初始化S矩阵
     * @return S
     */
    public static List<List<Double>> getS() {
        List<Double> row1 = new ArrayList<Double>();
        row1.add(new Double(0));
        row1.add(new Double(1 / 2.0));
        row1.add(new Double(0));
        row1.add(new Double(1 / 2.0));
        List<Double> row2 = new ArrayList<Double>();
        row2.add(new Double(1 / 3.0));
        row2.add(new Double(0));
        row2.add(new Double(0));
        row2.add(new Double(1 / 2.0));
        List<Double> row3 = new ArrayList<Double>();
        row3.add(new Double(1 / 3.0));
        row3.add(new Double(1 / 2.0));
        row3.add(new Double(0));
        row3.add(new Double(0));
        List<Double> row4 = new ArrayList<Double>();
        row4.add(new Double(1 / 3.0));
        row4.add(new Double(0));
        row4.add(new Double(1));
        row4.add(new Double(0));

        List<List<Double>> s = new ArrayList<List<Double>>();
        s.add(row1);
        s.add(row2);
        s.add(row3);
        s.add(row4);

        return s;
    }

    /**
     * 初始化U矩阵,全1
     * @return U
     */
    public static List<List<Double>> getU() {
        List<List<Double>> u = new ArrayList<>();

        try (BufferedReader br = new BufferedReader(new FileReader("src/main/Data mining/u"))) {
            String line;
            while ((line = br.readLine()) != null) {
                String[] values = line.split("[\\s,]+");
                List<Double> row = new ArrayList<>();
                for (String value : values) {
                    row.add(Double.parseDouble(value));
                }
                u.add(row);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return u;
    }
    /**
     * 对网页的重要性进行排序
     * @param webPages 网页名称列表
     * @param pageRank PageRank值列表
     */
    public static void sortPageRank(List<String> webPages, List<Double> pageRank) {
        // 创建一个Map来存储网页名称和对应的PageRank值
        Map<String, Double> pageRankMap = new HashMap<>();
        for (int i = 0; i < webPages.size(); i++) {
            pageRankMap.put(webPages.get(i), pageRank.get(i));
        }

        // 对PageRank值进行排序,对列表中的元素按照value进行降序排序。
        List<Map.Entry<String, Double>> list = new ArrayList<>(pageRankMap.entrySet());
        list.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));

        // 输出排序后的网页重要性
        System.out.println("网页重要性排序:");
        for (Map.Entry<String, Double> entry : list) {
            System.out.println("网页 " + entry.getKey() + " "+entry.getValue());
        }
    }
}

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值