AP算法java实现

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值