本文为加权GN算法的Java实现,具体算法原理请参考前一篇文章GN算法的简介,整个代码可从http://download.csdn.net/detail/u012483487/9447115下载,如有不对,敬请指正。

加权GN 算法求解的具体实现过程为:

(1)忽略边的权重,以无权网络计算网络中所有连接边的边介数;

(2)将边介数除以对应边的权重得到边权比;

(3)找到边权比最高的边将它移除,并计算网络的模块性 Q 函数,在计算中当边权比最高的边有多条时,同时移除这些边,并将此时移除的边和Q值进行存储;

(4)重复步骤(1),(2),直到网络中所有的边均被移除。

(5)GN算法划分结束后,取出Q值最大时的序号,在原始矩阵中依次去除截止到该次划分的边。得出最终连通矩阵,矩阵的值为权值。

现在使用JAVA对上述算法进行简单的实现,声明全局变量:

 private double[][] linkMatrix;//原始数据,在算法中不断删除边private double[][] originMatrix;//用于存储原始数据public List<Double> Qlist;//Q的集合public List<edgeInfo> deleteEgdes;//删除的边public ArrayList<nodeInfo>  previousNodes;//Gn算法中一次已经成功入队的节点public ArrayList<nodeInfo> currentNodes;//Gn算法中的当前节点public ArrayList<ArrayList<nodeInfo>> resultList;public ArrayList<nodeInfo> record;//Gn算法中上一次访问过节点public double[] disArray;//Gn算法中一次的各个边的距离public double[] weightArray;//Gn算法中一次的各边的权重public double[][] disMatrix;//用于记录源节点与其他节点的距离public double[][] sumDisMatix;//记录边介数private int MAX_NUM;//最大的数目private int coperationNum;//统计社团的数目private int[] belong;//用于区别节点所述社团

以及节点对象和边对象

public class nodeInfo {public List<Integer> parentNodes;//父节点public List<Integer> childrenNodes; //子节点public int name;//public double weightOfNode;//点权,public nodeInfo(int n) {parentNodes=new ArrayList<Integer>();childrenNodes=new ArrayList<Integer>();name=n;//weightOfNode=1;}}//边对象private class edgeInfo{public int start;//开始的节点public int end;//结束的节点public double weightOfEdge;//边权public void setInfo(int a,int b,double c) {this.start=a;this.end=b;this.weightOfEdge=c;}}

初始化变量,申请内存空间。

private void init(){MAX_NUM=100;linkMatrix=new double[MAX_NUM][MAX_NUM];originMatrix=new double[MAX_NUM][MAX_NUM];Qlist=new ArrayList<Double>();deleteEgdes=new ArrayList<edgeInfo>();resultList=new ArrayList<ArrayList<nodeInfo>>();}

现在简单说明算法的实现,主要实现如下,不断对每一个在图中,不孤立的点使用GN算法。去除边介数最大的点,直到所有边都删除为止。结束后求出最大的Q值,依次按照删除边的顺序对originMartrix矩阵进行删除,得出最后的划分图。

public void calGn(){ while (true) {sumDisMatix=new double[MAX_NUM][MAX_NUM];coperationNum=0;belong=new int[MAX_NUM];//使用GN算法计算每一个点,从而得出边介数for(int i=0;i<MAX_NUM;i++)if(isNodeOut(i)==false){calOneNodeGn(i);}double max=0;int x=0,y=0;//删除边权比最高的边for(int i=0;i<MAX_NUM;i++)for(int j=0;j<MAX_NUM;j++){if(linkMatrix[i][j]>0)sumDisMatix[i][j]=sumDisMatix[i][j]/linkMatrix[i][j];else {sumDisMatix[i][j]=0;}}for(int i=0;i<MAX_NUM;i++)for(int j=0;j<MAX_NUM;j++)if(max<sumDisMatix[i][j]){max=sumDisMatix[i][j];x=i;y=j;}if(max==0)break;calQ();deleEdge(x,y);}//查找最大的Q值,此时为最佳划分double maxq=0;int index=0;for(int i=0;i<Qlist.size();i++){if(maxq<Qlist.get(i)){maxq=Qlist.get(i);index=i;}}System.out.print("maxQ:"+maxq+" "+"index:"+index);}

对单独节点使用GN算法,这里先忽略掉边的权值,使用无权GN算法。首先需要对源节点使用一次广度优先遍历,得出访问过的节点列表,之后对这一列表中各个节点依次使用广度优先遍历,直到没有其他相互连接的节点为止。在广度优先遍历的过程中,建立了以源节点为根节点的树状网络。在遍历的过程中,对每一个节点建立了父节点列表和子节点列表,用于确定该节点的父节点(可能有多个)和子节点(可能有多个)。其次,对节点的社团进行标记;最后,对该树状网络进行权值的计算,计算过程请看简介,计算出边介数之后一次算法的目的达到。

public void calOneNodeGn(int n){if(isNodeOut(n)==true)return ;disMatrix=new double[MAX_NUM][MAX_NUM];previousNodes=new ArrayList<dataPreprocessing.nodeInfo>();disArray=new double[MAX_NUM];weightArray=new double[MAX_NUM];Boolean isStop=false; int deep1=2;currentNodes=new ArrayList<dataPreprocessing.nodeInfo>();singleNodeGNFirst(new nodeInfo(n), 1);//不断往下寻找,建立以节点n为源节点的树while(isStop==false){isStop=true;           record=currentNodes;currentNodes=new ArrayList<dataPreprocessing.nodeInfo>();for(int i=0;i<record.size();i++){boolean ldl=singleNodeGN(record.get(i),deep1);//如果还有子节点,继续循环if(ldl==true)isStop=false;          }       deep1++;// System.out.print(previousNodes.size()+"\n");}for(int i=0;i<previousNodes.size();i++){nodeInfo ne=previousNodes.get(i);if(ne.childrenNodes.size()==0)  for(int j=0;j<ne.parentNodes.size();j++){int x=ne.parentNodes.get(j);disMatrix[i][x]=weightArray[x]/weightArray[i];disMatrix[x][i]=disMatrix[i][x];}}//对叶子节点进行赋初值double max=0;int num=0;for(int i=0;i<MAX_NUM;i++)if(max<disArray[i]){max=disArray[i];num=i;}//此时把previousNodes中与最后一个相同的节点归为同一社团,并且标记int first=previousNodes.size()-1;if(belong[first]==0){coperationNum++;belong[first]=coperationNum;}for(int i=previousNodes.size()-1;i>=0;i--){int x=previousNodes.get(i).name;if(belong[x]==0)belong[x]=coperationNum;}//进行第二步,计算各边的权重for(int i=previousNodes.size()-1;i>=0;i--)singleSencondStep(previousNodes.get(i).name,n);//计算边介数for(int i=0;i<MAX_NUM;i++)for(int j=0;j<MAX_NUM;j++){sumDisMatix[i][j]+=disMatrix[i][j];}}
public Boolean singleNodeGNFirst(nodeInfo nn,int deep){      //System.out.println(deep+"\n");boolean res=true;int n=nn.name;previousNodes.add(nn);          for(int i=0;i<MAX_NUM;i++){if(linkMatrix[n][i]>0){   nodeInfo ne=new nodeInfo(i);         nodeInfo parentInfo=findNodeInfoById(n, previousNodes);                parentInfo.childrenNodes.add(i);//为父子关系ne.parentNodes.add(n);           currentNodes.add(ne);disArray[i]=deep;weightArray[i]=1;}}for(int j=0;j<MAX_NUM;j++){if(linkMatrix[n][j]>0){if(disArray[j]==0)res=false;}}return res;}
//广度优先遍历节点public Boolean singleNodeGN(nodeInfo nn,int deep){     //System.out.println(deep+"\n");boolean res=false;int n=nn.name;if(findNodeInfoById(n, previousNodes)==null)previousNodes.add(nn);       for(int i=0;i<MAX_NUM;i++){if(linkMatrix[n][i]>0){   nodeInfo ne=new nodeInfo(i);         if(findNodeInfoById(n, record)!=null&&(findNodeInfoById(i, record)!=null))break;if((findNodeInfoById(i, previousNodes)==null)){nodeInfo parentInfo=findNodeInfoById(n, previousNodes);if(findNodeInfoById(i, currentNodes)==null){parentInfo.childrenNodes.add(i);//为父子关系ne.parentNodes.add(n);//currentNodes.add(ne);//如果在当前访问节点中为空并且从未被访问过res=true;}else {{parentInfo.childrenNodes.add(i);//为父子关系findNodeInfoById(i, currentNodes).parentNodes.add(n);res=true;}}if(disArray[i]==0){disArray[i]=deep;weightArray[i]=weightArray[parentInfo.name];}else if(disArray[i]==deep){weightArray[i]=weightArray[n]+weightArray[i];}else if(disArray[i]<deep);else {;}}}}/* for(int j=0;j<MAX_NUM;j++){if(linkMatrix[n][j]>0){if(disArray[j]==0)res=false;}}*/return res;}
//计算各边的权重public void singleSencondStep(int n,int source){nodeInfo neInfo=findNodeInfoById(n, previousNodes);for(int j=0;j<neInfo.parentNodes.size();j++){nodeInfo pa=findNodeInfoById(neInfo.parentNodes.get(j), previousNodes);double q=1;for(int k=0;k<neInfo.childrenNodes.size();k++)q+=disMatrix[n][neInfo.childrenNodes.get(k)];int x=neInfo.parentNodes.get(j);if(pa.name!=source){if(weightArray[n]!=0){disMatrix[n][x]=weightArray[x]*q/weightArray[n];disMatrix[x][n]=disMatrix[n][x];}}else {disMatrix[n][x]=q;disMatrix[x][n]=disMatrix[n][x];   }}}

对边的删除,主要是对linkMatrix矩阵进行删除操作,并将删除的边记录在列表中,也把当时计算的Q值记录,便于查找。对Q值的计算公式详见简介

public void deleEdge(int start,int end){edgeInfo deInfo=new edgeInfo();deInfo.setInfo(start, end, linkMatrix[start][end]);deleteEgdes.add(deInfo);linkMatrix[start][end]=0;linkMatrix[end][start]=0;}
<span style="font-family: Arial, Helvetica, sans-serif;">public double calQ()</span><span style="font-family: Arial, Helvetica, sans-serif;">{</span>
     double Q=0;double M=0;double sum=0;double []k=new double[MAX_NUM];for(int i=0;i<MAX_NUM;i++)for(int j=0;j<MAX_NUM;j++){M+=linkMatrix[i][j];               }M=M/2;for(int i=0;i<MAX_NUM;i++)for(int j=0;j<MAX_NUM;j++)if(linkMatrix[i][j]>0){k[i]+=linkMatrix[i][j];}for(int i=0;i<MAX_NUM;i++)for(int j=0;j<MAX_NUM;j++){if(belong[i]==belong[j])sum+=(linkMatrix[i][j]-k[i]*k[j]/(2*M));}Q=sum/(2*M);Qlist.add(Q);// System.out.print(Q+"\n");return Q;}

计算出结果后,可以选择将结果进行打印,调用函数printResult即可,此时打印的矩阵为GN分裂后的社团结构,以二维数组的形式呈现,打印横纵坐标和权值。

public void printResult(){double max=0;int index=0;for(int i=0;i<Qlist.size();i++){if(max<Qlist.get(i)){max=Qlist.get(i);index=i;}}for(int i=0;i<index;i++){edgeInfo eInfo=deleteEgdes.get(i);int ks=eInfo.start;int ke=eInfo.end;originMatrix[ks][ke]=0;originMatrix[ke][ks]=0;}File file = new File("d:/temp", "res.txt"); try {  file.createNewFile(); // 创建文件  } catch (IOException e) {  // TODO Auto-generated catch block  e.printStackTrace();  }  try {FileOutputStream in = new FileOutputStream(file);  for(int i=0;i<MAX_NUM;i++)for(int j=0;j<MAX_NUM;j++){String str =""+i+" "+j+" "+originMatrix[i][j]+"\n";  byte bt[] = new byte[1024];  bt = str.getBytes();  try {  in.write(bt, 0, bt.length);  //in.close();  // boolean success=true;  // System.out.println("写入文件成功");  } catch (IOException e) {  // TODO Auto-generated catch block  e.printStackTrace();  }  }} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}

加权GN算法的Java实现相关推荐

  1. 负载均衡算法及其Java代码实现

    负载均衡算法及其Java代码实现 什么是负载均衡 负载均衡,英文 名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须 ...

  2. java负载均衡原理_多种负载均衡算法及其 Java 代码实现

    首先给我们介绍下什么是负载均衡 负载均衡 树立在现有网络结构之上,它供给了一种廉价有用通明的办法扩展 网络设备和 效劳器的带宽.添加 吞吐量.加强网络数据处理才能.进步网络的灵敏性和可用性. 负载均衡 ...

  3. 【LeetCode-面试算法经典-Java实现】【015-3 Sum(三个数的和)】

    [015-3 Sum(三个数的和)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given an array S of n integers, are there ...

  4. java实现 k nn算法_数据挖掘(二)——Knn算法的java实现

    本文接数据挖掘-基于Kmeans算法.MBSAS算法及DBSCAN算法的newsgroup18828文本聚类器的JAVA实现(上). (update 2012.12.28 关于本项目下载及运行的常见问 ...

  5. 【LeetCode-面试算法经典-Java实现】【109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)】...

    [109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 ...

  6. 八大排序算法的java实现

    八大排序算法的java实现 有时间再贴算法分析图 JDK7的Collections.sort()的算法是TimSort, 适应性的归并排序, 比较晦涩难懂, 这里没有实现 public class m ...

  7. 对一致性Hash算法,Java代码实现的深入研究

    一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性 ...

  8. DES和RSA算法的java实现

    2019独角兽企业重金招聘Python工程师标准>>> 一.对称加密算法 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过 ...

  9. 【建议收藏】MD5 算法的Java Bean

    MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输 ...

最新文章

  1. QT的QMutableMapIterator类的使用
  2. DVWA File Inclusion——Writeup
  3. C++ 重载左移和右移运算符
  4. 人群与网络:博弈论基本概念
  5. 【渝粤教育】国家开放大学2019年春季 2106宪法学 参考试题
  6. 求职 IT 少年李文星之死:请务必学会保护自己!
  7. ATL之深入浅出书评(转)
  8. 单片机0 99c语言程序,单片机C语言程序设计实训99例.doc
  9. 交互式电子杂志_快速的创建交互式演示和翻转电子书工具-XFlip Enterprise(电子杂志相册制作器) V2.0.5.0 中文版 - 未来软件园...
  10. 2022最新第四方聚合支付系统源码+详细搭建教程
  11. 粒子群算法(PSO) C
  12. linux系统svn安装教程,Linux下SVN安装配置
  13. HealthKit框架简介
  14. Wilcoxon秩和检验MATLAB实现
  15. git获取所有branch_获取Git仓库的所有分支名字
  16. 迪文串口屏(DMG10600C101-03WTC)的使用测试
  17. 还在搞公众号互推涨粉?这个小工具助你粉丝躺增!
  18. Hadoop常用命令参数介绍
  19. 【刷题篇】避免洪水泛滥
  20. 根据地址智能识别省市县/区

热门文章

  1. curl https -k
  2. 搭配Online:斥资$500000美元!沙特为何抄底疫情重灾股?
  3. 告诉你怎样选择虚拟主机!
  4. 软件测试怎么保证数据的准确性,在MT4软件EA测试过程中,如何获得99.9%的数据质量,提高EA测试的准确性 -...
  5. mysql伪列的使用,mysql伪列的妙用,mysql获取近几天的日期用来连表查询
  6. 将来是多久,看一看大佬的故事--《绝非偶然》
  7. 西北乱跑娃 --- python xml转dict
  8. 中国中药保健品行业发展现状与未来拓展模式分析报告2022-2027年版
  9. 理解torch.einsum(‘ijk,ilk->ijl‘, a,b)
  10. Spring Cloud云架构 - SSO单点登录之OAuth2.0登录认证(1)