您的位置:首页 > 编程语言 > Java开发

AP算法java实现

2015-07-14 16:41 681 查看
AP近邻传播算法,关于其原理网上有很多,这就不做过多的介绍,具体的可以参照 http://blog.sina.com.cn/s/blog_6617c8c201013v25.html 关于最终的终止条件设置是小于200,用于给出的例子可以很好地进行聚类,也可以按照原算法思想设置终止条件,算法结果输出的是最终的最佳n个中心,其他的点可以根据距离进行最终的归类划分,的以下是具体实现源代码:

package com.gxw;

import java.io.BufferedReader;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.PrintStream;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

/**

* AP聚类算法

*

* @author gxw

*

*/

public class APMain {

public static void main(String[] args) {

List<List<Double>> data = getData(); // 获取文本数据

Double s[][] = getMatrix(data);

apOpreate(s);

}

private static void apOpreate(Double s[][]) {

double lam = 0.5;

int len = s.length;

//判定是否为中心点

int[] iscenter = new int[len];

Double r[][] = new Double[len][len];

Double a[][] = new Double[len][len];

Double oldr[][] = new Double[len][len];

Double olda[][] = new Double[len][len];

//初始化矩阵

for(int i = 0; i < len; i++)

{

for(int j = 0; j < len; j++)

{

olda[i][j] = 0.0;

a[i][j] = 0.0;

oldr[i][j] = 0.0;

r[i][j] = 0.0;

}

}

int times = 0;

while(times < 200)

{

//now to old

{

for(int i = 0; i < len; i++) {

for(int j = 0; j < len; j++) {

oldr[i][j] = r[i][j];

olda[i][j] = a[i][j];

}

}

}

//更新r.R(i,k)=S(i,k)- max{A(i,j)+S(i,j)}(j {1,2,……,N,但j≠k})

for(int i = 0; i < len; i++) {

for(int k = 0; k < len; k++) {

double max = -10000.0;

for(int j = 0; j < len; j++) {

if(j != k) {

max = max > (olda[i][j] + s[i][j]) ? max : (olda[i][j] + s[i][j] );

}

}

r[i][k] = s[i][k] - max;

}

}

//更新A(i,k)=min{0,R(k,k)+ (j {1,2,……,N,但j≠i且j≠k})

for(int i = 0; i < len; i++) {

for(int k = 0; k < len; k++) {

double sum = 0.0;

for(int j = 0; j < len; j++) {

if(j != i && j != k) {

if(oldr[j][k] > 0) {

sum += oldr[j][k];

}

}

}

if(i != k) {

a[i][k] = (0 < (oldr[k][k] + sum) ? 0 : (oldr[k][k] + sum));

}

else {

a[i][k] = sum;

}

}

}

// 加入阻尼系数

for(int i = 0; i < len; i++) {

for(int j = 0; j < len; j++) {

r[i][j] = (1 - lam) * r[i][j] + lam * oldr[i][j];

a[i][j] = (1 - lam) * a[i][j] + lam * olda[i][j];

}

}

//判断中心点

{

for (int k = 0; k < len; k++)

{

if (a[k][k] + r[k][k] > 0) //判定条件。。

{

System.out.println(k + 1 + " " + (a[k][k] + r[k][k]));

iscenter[k] = 1;

}

}

}

System.out.println();

times++;

}

}

/**

* 获取数据

* @return

*/

public static List<List<Double>> getData() {

List<List<Double>> ll = new ArrayList<List<Double>>();

try {

String path = System.getProperty("user.dir") + "/data1.txt";

FileReader fr = new FileReader(path);

BufferedReader br = new BufferedReader(fr);

String line = br.readLine();

while (line != null) {

String strs[] = line.split(" ");

List<Double> l = new ArrayList<Double>();

for (int i = 0; i < strs.length; i++) {

Double da = Double.parseDouble(strs[i]);

l.add(da);

}

ll.add(l);

line = br.readLine();

}

} catch (Exception e) {

System.out.println(e);

}

return ll;

}

/**

* 构建相似度矩阵

* @param data

* @return

*/

private static Double[][] getMatrix(List<List<Double>> data) {

int num = data.size(); // 数据个数

int dimen = data.get(0).size(); // 数据维度

Double s[][] = new Double[num][num];

Double tempData = 0.0;

int i = 0, j = 0, k = 0;

for (i = 0; i < num; i++) {

for (j = 0; j < num; j++) {

tempData = 0.0;

for (k = 0; k < dimen; k++) {

tempData += Math.pow(data.get(i).get(k)

- data.get(j).get(k), 2);

}

if(tempData == 0.0) {

s[i][j] = 0.0;

}

else {

s[i][j] = -Math.sqrt(tempData);

}

}

}

Double middleValue = getMiddle(s);

//重新设置 s[i][i] = middleValue;

for(i = 0; i < num; i++)

{

s[i][i] = middleValue;

}

return s;

}

/**

* 计算相似矩阵的中值

* @param s

* @return

*/

private static double getMiddle(Double s[][])

{

double res = 0.0;

int num = s.length;

List<Double> ld = new ArrayList<Double>();

for(int i = 0; i < num; i++)

{

for(int j = 0; j < num; j++)

{

ld.add(s[i][j]);

}

}

Collections.sort(ld, new Comparator<Double>() {

public int compare(Double a, Double b) {

return a.compareTo(b);

}

});

Double middleValue = 0.0;

if(num * num % 2 == 0)

middleValue = (ld.get(num * num / 2) + ld.get(num * num / 2 + 1)) / 2;

else

{

middleValue = ld.get(num * num / 2 + 1);

}

return middleValue;

}

}

//////原数据如下(二维坐标点), 在当前项目的根目录下新建data.txt,使用的eclipse创建的java项目:

0.02 0.61

0.18 0.46

0.23 0.35

0.40 0.43

0.41 0.20

0.45 0.19

0.46 0.19

0.48 0.01

0.62 0.02

0.61 0.82

0.74 0.93

0.79 0.74

0.93 0.85

0.89 0.67

0.91 0.53

0.92 0.44

0.76 0.20

0.82 0.28

0.89 0.14

0.95 0.05
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: