PageRank的Java代码实现及图形操作(带详细注释)!

来源:互联网 发布:php ldap bind 编辑:程序博客网 时间:2024/05/06 12:55

PageRank的Java代码实现及图形操作(带详细注释)!

从Git上找到的一段代码,修改了一些东西,加了一些自己遇到的问题的注释以及增加了阻尼系数变量。

废话不说直接上代码:


package cn.wx.PageRank;import java.awt.FlowLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.BufferedReader;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import javax.swing.JButton;import javax.swing.JFileChooser;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;/** * 求取PageRank值的代码 用户可以通过文件选择器选择读入指定的文件进行计算,文件的第一行为初始PR值, *  * 余下的行为矩阵,其中矩阵行元素间用“,”隔开,行与行之间无需分隔符。 *  * 也可以通过选择随机来输入矩阵的维数、初始PR值以及矩阵的复杂度(矩阵中有多少个1)生成矩阵进行计算。 */public class newPageRank {static JTextField jtf;// 显示文件路径的框static JTextArea jta;// 显示计算结果的框static JFrame jf;// 显示的窗体static JFrame jf1;// 显示输入矩阵的窗体static float[] data;// 存数输入数据的数组static int time = 20;// 指定的运行次数static float alpha = 0.85f; // 阻尼系数d或称为alpha public static void main(String[] args) {newPageRank mine = new newPageRank();mine.showUI();}/** * 展示计算结果的界面 */public void showUI() {// 初始化界面以及按钮、输入框等jf = new JFrame();jf.setTitle("PR值计算~~");jf.setSize(500, 500);jf.setDefaultCloseOperation(3);jf.setResizable(false);jf.setLayout(null);jf.setLocationRelativeTo(null);JButton btn = new JButton("打开");btn.setActionCommand("Open");btn.setBounds(20, 20, 80, 30);JButton btn1 = new JButton("随机");btn1.setActionCommand("Input");btn1.setBounds(110, 20, 80, 30);jtf = new JTextField();jtf.setBounds(200, 20, 260, 30);jtf.setEditable(true);jtf.setActionCommand("Over");jta = new JTextArea();jta.setEditable(false);jta.setLineWrap(true);jta.setAutoscrolls(true);JScrollPane jsp = new JScrollPane(jta);// 创建滚动条jsp.setBounds(20, 70, 460, 380);// 添加监听器ActionListener al = new ActionListener() {public void actionPerformed(ActionEvent e) {if (e.getActionCommand().equals("Open")) {// 弹出选择框jta.setText("");// 每次重新选择之前清空输入框JFileChooser fc = new JFileChooser();int value = fc.showOpenDialog(null);fc.setFileSelectionMode(JFileChooser.FILES_ONLY);if (value == JFileChooser.CANCEL_OPTION) {return;}File file = fc.getSelectedFile();jtf.setText(file.getAbsolutePath());readFile(file);}if (e.getActionCommand().equals("Input")) {init();// 初始化窗体,获取值}if (e.getActionCommand().equals("Over")) {jta.setText("");// 输入路径结束,执行以下操作File file = new File(jtf.getText());readFile(file);}}};jf.add(btn);jf.add(btn1);jf.add(jtf);jf.add(jsp);btn.addActionListener(al);btn1.addActionListener(al);jtf.addActionListener(al);jf.setVisible(true);}/** * 读取相应路径文件的方法 定义文件中第一行是节点对应的初始化PR值, * 接下来是N*N的矩阵 同行数据之间均通过","分隔,不同行无需分隔符 *  * @param file *            :文件 */public static void readFile(File file) {try {// 创建读文件的流FileReader fr = new FileReader(file);BufferedReader br = new BufferedReader(fr);String PR = br.readLine();String[] sPR = PR.split(",");// 将第一行PR值存入对应数组// 将读取的PR值从String转为floatfloat[] initPR = new float[sPR.length];for (int i = 0; i < sPR.length; i++) {initPR[i] = Float.parseFloat(sPR[i]);}jta.append("各页面的初始PR值………………………………………………………………" + "\n");for (int i = 0; i < initPR.length; i++) {jta.append(initPR[i] + "\t");// 打印出PR值}jta.append("\n");// 读取并创建N*N矩阵,在这里使用float,精度为小数点后7位float[][] array = new float[initPR.length][initPR.length];int count = 0;// 用计数器控制行的变化// 当行数小于指定数N时进行读取while (count < initPR.length) {String value = br.readLine();// 读取一行的值String[] rowV = value.split(",");// 对第count行第i列赋值for (int i = 0; i < initPR.length; i++) {array[count][i] = Float.parseFloat(rowV[i]);}count++;}jta.append("原始矩阵为………………………………………………………" + "\n");print(array);// 打印出矩阵// 读取完成后,调用计算的函数对矩阵进行计算long start = System.currentTimeMillis();calculate(initPR, array);long end = System.currentTimeMillis();jta.append("total time is:" + (end - start));br.close(); // 关闭流} catch (FileNotFoundException e) {javax.swing.JOptionPane.showMessageDialog(jf, "文件未找到,请重试!");} catch (IOException e) {javax.swing.JOptionPane.showMessageDialog(jf, "文件读取有误,请重试!");}}/** * 打印矩阵的方法 *  * @param s */static void print(float[][] f) {for (int i = 0; i < f.length; i++) {for (int j = 0; j < f.length; j++) {jta.append(f[i][j] + "\t");}jta.append("\n");}}/** * 计算矩阵特征值以及特征向量的方法 *  * @param initPR *            :存储初始的PR值的float数组 * @param array *            :存储初始矩阵的float二维数组 */static void calculate(float[] initPR, float[][] array) {array = changeRC(array);// 转置矩阵jta.append("转置后的矩阵…………………………………………………………");jta.append("\n");print(array);array = randomization(array);// 概率化矩阵jta.append("\n");jta.append("概率化后的矩阵………………………………………………………………");jta.append("\n");print(array);for (int i = 1; i <= time; i++) {initPR = formular(initPR, array);jta.append("\n");jta.append("经过" + i + "次计算,PR值为………………………………………………");jta.append("\n");for (int j = 0; j < initPR.length; j++) {jta.append("PR[" + j + "]的值为:" + initPR[j]);jta.append("\n");}}jta.repaint();}/** * 转置矩阵的方法 *  * @param array *            :需要转置的矩阵 * @return:将转置后的矩阵返回 */static float[][] changeRC(float[][] array) {float temp = 0;// 临时变量,用于交换for (int i = 0; i < array.length; i++) {for (int j = 0; j < array.length; j++) {// 对矩阵的每一行、列遍历,如果下标i<j就倒换if (i < j) {temp = array[i][j];array[i][j] = array[j][i];array[j][i] = temp;}}}return array;}/** * 概率化矩阵的方法 *  * @param array *            :需要概率化的矩阵 * @return:返回已经概率化的矩阵 */static float[][] randomization(float[][] array) {int count = 0;// 控制列变化的计数器int size = 0;// 计量列中连接为1的元素数量的计数器while (count < array.length) {size = 0;// 每次计数之前要清零for (int i = 0; i < array.length; i++) {if (array[i][count] == 1) {size++;// 先统计出数量为多少}}jta.append("the size of " + count + " is:" + size + "    ");for (int i = 0; i < array.length; i++) {if (array[i][count] == 1) {array[i][count] = (float) 1 / size;}}count++;}return array;}/** * 通过公式计算PR值 *  * @param initPR *            :初始PR值 * @param array *            :经处理的矩阵 * @return:返回计算后的PR值 */static float[] formular(float[] initPR, float[][] array) {for (int i = 0; i < initPR.length; i++) {initPR[i] = 0;// 重算一个PR之前,将其清零int count = 0;// 计量每一行0元素个数            for (int j = 0; j < initPR.length; j++) {if (i != j && array[i][j] != 0) {initPR[i] = (float) (initPR[i] + ((initPR[j] * array[i][j]) * alpha + (1.0f-alpha)));} elsecount++;}if (count == initPR.length) {initPR[i] = (float) 0.15;}}return initPR;}static void input(float[] data) {float size = data[0];float complex = data[1];float[] initPR = new float[data.length - 2];for (int i = 0; i < initPR.length; i++) {initPR[i] = data[i + 2];}float[][] array = new float[(int) size][(int) size];// 创建输入大小的矩阵// 初始化矩阵元素为0for (int i = 0; i < array.length; i++) {for (int j = 0; j < array.length; j++) {array[i][j] = 0;}}int num = (int) (complex / 100 * array.length * array.length);// 需要被赋为1的元素个数// 为矩阵按照复杂程度赋值while (num > 0) {int row = (int) (Math.random() * (array.length));int column = (int) (Math.random() * (array.length));// 随机生成行列数if (row != column && array[row][column] != 1) {array[row][column] = 1;num--;}}// 打印随机生成的PR和矩阵jta.append("各页面的初始PR值………………………………………………………………" + "\n");for (int i = 0; i < initPR.length; i++) {jta.append(initPR[i] + "\t");// 打印出PR值}jta.append("\n");jta.append("生成的矩阵…………………………………………………………………………" + "\n");print(array);// 将计算好的初始PR数组和矩阵传入计算long start = System.currentTimeMillis();calculate(initPR, array);long end = System.currentTimeMillis();jta.append("total time is:" + (end - start));}/** * 初始化一个输入值的窗体 */static void init() {jf1 = new JFrame("生成随机矩阵");jf1.setSize(300, 160);jf1.setResizable(false);jf1.setDefaultCloseOperation(2);jf1.setLocationRelativeTo(null);jf1.setLayout(new FlowLayout());JLabel lb = new JLabel("矩阵维度:");final JTextField jtf = new JTextField(15);JLabel lb1 = new JLabel("初始PR值:");final JTextField jtf1 = new JTextField(15);JLabel lb2 = new JLabel("    复杂度:  ");final JTextField jtf2 = new JTextField(15);jtf2.setActionCommand("sure");JLabel lb3 = new JLabel("% ");JButton btn = new JButton("确认");btn.setActionCommand("sure");JButton btn1 = new JButton("取消");btn1.setActionCommand("cancle");ActionListener al = new ActionListener() {public void actionPerformed(ActionEvent e) {if (e.getActionCommand().equals("sure")) {// 点击确认后,存储输入值float size = Integer.parseInt(jtf.getText());// 取值String[] s = jtf1.getText().split(",");float complex = Integer.parseInt(jtf2.getText());// 初始化数组,将输入框中的值存入数组data = new float[s.length + 2];// 先存入矩阵维度,再放入复杂度,最后存入各个初始值data[0] = size;data[1] = complex;for (int i = 0; i < s.length; i++) {data[2 + i] = Float.parseFloat(s[i]);}jf1.dispose();input(data);}if (e.getActionCommand().equals("cancle")) {jf1.dispose();}}};jf1.add(lb);jf1.add(jtf);jf1.add(lb1);jf1.add(jtf1);jf1.add(lb2);jf1.add(jtf2);jf1.add(lb3);jf1.add(btn);jf1.add(btn1);jtf2.addActionListener(al);btn.addActionListener(al);btn1.addActionListener(al);jf1.setVisible(true);}}


0 0