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

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转为float
			float[] 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)));
				} else
					count++;
			}
			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];// 创建输入大小的矩阵
		// 初始化矩阵元素为0
		for (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);
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值