多模块划分的基本算法是依据任务间的通信代价进行聚类,两个任务通信代价越高或越频繁,越应该把这两个任务划分到一个模块(簇,类),依据划分结果,计算块间的通信代价,而模块内的通信代价量认为为零。这个过程 可以多次进行,最终选一个模块间通信代价之和最小者,算法终止。实现了 智能系统的多模块优化划分。
聚类特点
• 聚类是将数据进行分组。
• 聚类中的组称为簇,
• 聚类中的簇不是预先定义的,而是根据实际数据的特征按照数据间的相似性来定义的。
• 簇一般具有特征:
(1)簇是一些相似成员的集合,
(2)不同簇中的成员是不相似的,
(3)簇中的任两点间距离要小于簇中的点与簇外任一点之间的距离
基于聚类的划分方法有三种,分别为单连接技术(Single Link) , 全连接技术(Complete Link) ,平均连接技术(Average Link)
对于单连接技术,所采用的合并策略为簇间的距离为元素间的最短距离,即当某元素与簇间的元素之间的最小距离小于或等于当前的阈值d时,即将该元素加入簇中。若两元素之间的距离小于或等于当前阈值d且两元素均未加入簇中时,可将该两元素合并成新簇。

对于全连接技术,对于全连接技术,所采用的合并策略为簇间的距离为元素间的最长距离,即当某元素与簇间的元素之间的最大距离小于或等于当前的阈值d时,即将该元素加入簇中。若两元素之间的距离小于或等于当前阈值d且两元素均未加入簇中时,可将该两元素合并成新簇。

对于均连接技术,对于均连接技术,所采用的合并策略为簇间的距离为元素间的平均距离,即当某元素与簇间的元素之间的平均距离小于或等于当前的阈值d时,即将该元素加入簇中。若两元素之间的距离小于或等于当前阈值d且两元素均未加入簇中时,可将该两元素合并成新簇。

以下为对一个例子的全连接,单连接,均链接的java实现

package zdghgd;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class SingleLinkage {
public static void main(String[] args) {
int[][] matrix=
{
{0, 1, 0, 0, 0, 0, 4, 0, 2, 0},
{0, 0, 3, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 2, 0, 1},
{0, 0, 0, 0, 0, 2, 0, 5, 6, 0},
{0, 0, 0, 0, 0, 0, 0, 3, 7, 8},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};//导入通信代价矩阵
int[][] tempMatrix=new int[10][10];
for (int m=0;m<tempMatrix.length;m++) {
for (int n=0; n <tempMatrix.length;n++) {
matrix[m][n] =matrix[m][n];//将通信代价矩阵导入到一个新的矩阵中
}
}
SingleLinkage linkage=new SingleLinkage();
List list=linkage.singleLink(matrix,3,4);//得到经过单连接划分后的list,其中簇中元素最多为3,最多有4个簇
System.out.println("单连接划分后得到");
for (int i=0;i<list.size();i++)
{
List temp = (List) list.get(i);
System.out.println("簇的元素个数为:"+temp.size());
for (int j=0;j<temp.size();j++)
{
System.out.print(((int) temp.get(j)+1)+",");//将划分后的簇输出
}
System.out.println();
}
System.out.println();
int max=-1;
int length=matrix.length;
for (int i = 0; i < length; i++) {
for (int j = i; j < length; j++) {
if (matrix[i][j] >= max) {
max = matrix[i][j];
}
}
}//得到通信代价矩阵中的最大值
int maxDistance=max;
int totalDistance=linkage.calculateDistance(tempMatrix,list,maxDistance);//计算划分后各簇之间的总通信距离
System.out.println("通信距离:"+totalDistance);
}
private List singleLink(int[][] data,int num,int direction)//确定单连接划分的簇个数以及簇内最多元素个数
{
int length=data.length;//矩阵大小
int count=0;//计算已经放到簇中的数据个数
List<List> list=new ArrayList<>();//生成一个新的list
boolean[][] border = new boolean[length][length];//确定该边是否已划分
boolean[] used = new boolean[length];//确定该元素是否已放入簇中
data=getDistance(data);//将通信代价矩阵转换为通信距离矩阵
int maxLength=getMaxDistance(data);//计算通信距离的最大值
for(int distance=0;distance<=maxLength;distance++)//阈值从零开始逐渐递增
{
if(count>=length){//若元素全部放到簇中
break;
}
//遍历通信距离矩阵
for (int i=0;i<length;i++)
{
for (int j=i+1;j<length;j++)
{
if (data[i][j]==distance&&!border[i][j])//若通信代价等于阈值且未加入过簇
{
if (list.size()==0)//如果结果list为空,则直接将数据加入到一个list中
{
List tempList = new ArrayList();
tempList.add(i);//加入这两个元素
tempList.add(j);
used[i]=true;//将这两个元素标记为已划分
used[j]=true;
border[i][j]=true;//标记该元素已加入簇中
count+=2;//簇中的元素个数加二
list.add(tempList);
}
else
{
boolean flag=false;
int m=0;
//如果不为空的话,就遍历结果list,找出这个数字是否出现过
for (m=0;m<list.size();m++)
{
List tempList=list.get(m);
for (int n=0; n<tempList.size();n++)
{
if (tempList.contains(i)&&!rol[j])
{
flag=true;
if (tempList.size()<num)//数字出现在某个list中,且list中元素的个数小于最多元素个数
{
tempList.add(j);//将该元素加入簇中
used[j]=true;//将这个元素标记为已划分
border[i][j]=true;//标记该元素已加入簇中
count++;//簇中的元素个数加一
break;
}
}
if (tempList.contains(j)&&!rol[i])
{
flag=true;
if (tempList.size()<num)//数字出现在某个list中,且list中元素的个数小于最多任务数
{
tempList.add(i);//将该元素加入簇中
used[i]=true;//将这个元素标记为已划分
border[i][j]=true;//标记该元素已加入簇中
count++;//簇中的元素个数加一
break;
}
}
}
}
if (m==list.size()&&!hasUsed[i][j]&&!flag&&!rol[i]&&!rol[j])//遍历所有簇,并不能将现有的数据加入进去,则新建一个list
{
List tempList = new ArrayList();
tempList.add(i);
tempList.add(j);
used[i]=true;//将这个元素标记为已划分
used[j]=true;
border[i][j]=true;//标记该元素已加入簇中
count+=2;//簇中的元素个数加二
list.add(tempList);
}
}
}
}
}
}
return list;
}
private int[][] communicateDistance(int[][] data)
{
int length = data.length;
//找到通信代价最大值
int max = getMaxDistance(data);
//计算通信距离
for (int i = 0; i < length; i++) {
for (int j = i; j < length; j++) {
data[i][j] = max - data[i][j] + 1;
}
data[i][i] = 0;
}
return data;
}
private int getMaxDistance(int[][] data)//计算最大距离
{
int max=-1;
int length=data.length;
for (int i = 0; i < length; i++)
{
for (int j = i; j < length; j++)
{
if (data[i][j] >= max)
{
max = data[i][j];
}
}
}
return max;
}
private int calculateDistance(int[][] data, List list, int maxDistance)
{
int totalDistance=0;
//先找到两个相邻的簇,然后匹配簇中的元素
System.out.println("相连接的元素为:");
for (int i = 0; i < list.size()-1; i++)
{
List last= (List) list.get(i);//得到相邻的簇
for (int j=i+1;j<list.size();j++)
{
List next=(List)list.get(j);//得到相邻的簇
for (int m=0;m<last.size();m++)//进行元素的两两匹配
{
for (int n=0;n<next.size();n++)
{
if(data[(int) last.get(m)][(int) next.get(n)]<maxDistance&&data[(int) last.get(m)][(int) next.get(n)]>0)
{//若两元素间有链路相链接
System.out.println((int) last.get(m)+" "+(int) next.get(n));//输出相联的两个元素
totalDistance+=data[(int) last.get(m)][(int) next.get(n)];
}
if(data[(int)next.get(n)][(int)last.get(m)]<maxDistance&&data[(int)next.get(n)][(int)last.get(m)]>0)
{//若两元素间有链路相链接
System.out.println((int) next.get(n)+" "+(int) last.get(m));//输出相联的两个元素
totalDistance+=data[(int) next.get(n)][(int) last.get(m)];
}
}
}
}
}
return totalDistance;
}
}package zdghgd;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class CompleteLinkage {
public static void main(String[] args) {
int[][] data=
{
{0, 1, 0, 0, 0, 0, 4, 0, 2, 0},
{0, 0, 3, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 2, 0, 1},
{0, 0, 0, 0, 0, 2, 0, 5, 6, 0},
{0, 0, 0, 0, 0, 0, 0, 3, 7, 8},
{0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
int[][] tempData=new int[10][10];
for (int m=0;m<tempData.length;m++) {
for (int n=0; n <tempData.length;n++) {
tempData[m][n] =data[m][n];//将通信代价矩阵导入到一个新的矩阵中
}
}
CompleteLinkage linkage=new CompleteLinkage();
List list=linkage.CompleteLink(data,3,4);//得到经过单连接划分后的list,其中簇中元素最多为4,最多有3个簇
System.out.println("全连接划分后得到");
for (int i=0;i<list.size();i++)
{
List temp = (List) list.get(i);
System.out.println("簇的元素个数为:"+temp.size());
for (int j=0;j<temp.size();j++)
{
System.out.print(((int) temp.get(j)+1)+",");//将划分后的簇输出
}
System.out.println();
}
System.out.println();
int max=-1;
int length=data.length;
for (int i = 0; i < length; i++) {
for (int j = i; j < length; j++) {
if (data[i][j] >= max) {
max = data[i][j];
}
}
}//得到通信代价矩阵中的最大值
int maxDistance=max;
/*int maxDistance=linkage.getMaxDistance(tempData);*/
int totalDistance=linkage.calculateDistance(tempData,list,maxDistance);//计算通信距离
System.out.println("通信距离:"+totalDistance);
}
private List CompleteLink(int[][] data,int num,int direction)
{
int length=data.length;//矩阵大小
int number=0;//记录簇的个数
int count=0;//计算已经放到簇中的数据个数
List<List> list=new ArrayList<>();
boolean[][] border = new boolean[length][length];
boolean[] used = new boolean[length];
data=getDistance(data);//将通信代价矩阵转换为通信距离矩阵
int maxLength=getMaxDistance(data);//计算通信距离的最大值
for(int distance=0;distance<=maxLength;distance++)//阈值从零开始逐渐递增
{
if(count>=length)
{//若元素全部放到簇中
break;
}
//遍历通信距离矩阵
for (int i=0;i<length;i++)
{
for (int j=i+1;j<length;j++)
{
if (data[i][j]<=distance&&!border[i][j])//若通信代价等于阈值且未加入过簇
{
if (list.size()==0)//如果结果list为空,则直接将数据加入到一个簇中
{
List tempList = new ArrayList();
number++;//簇的个数加一
tempList.add(i);
tempList.add(j);
used[i]=true;
used[j]=true;
border[i][j]=true;//标记该元素已加入簇中
border[j][i]=true;
count+=2;//簇中的元素个数加二
list.add(tempList);
}
else
{
boolean flag=false;
int m=0;
for (m=0;m<list.size();m++) //如果不为空的话,就遍历结果list,找出这个数字是否出现过
{
List tempList=list.get(m);
for (int n=0; n<tempList.size();n++)
{
if (tempList.contains(i)&&!rol[j]) //若j元素未出现在簇中
{
flag=true;
if (tempList.size()<num)//数字出现在某个list中,且list中元素的个数小于最多元素个数
{
int flag1=0;
for(int k=0;k<tempList.size();k++)
{
if(data[(int)tempList.get(k)][j]>distance||data[j][(int)tempList.get(k)]>distance)
{
flag1=1;//判断该元素与簇中元素的通信距离是否大于阈值
}
}
if(flag1==0)
{
tempList.add(j);//将该元素加入簇中
used[j]=true;
border[i][j]=true;
border[j][i]=true;
count++;
break;
}
}
}
if (tempList.contains(j)&&!rol[i])
{
flag=true;
if (tempList.size()<num)//数字出现在某个list中,且list中元素的个数小于最多元素个数
{
int flag2=0;
for(int k1=0;k1<tempList.size();k1++)
{
if(data[(int)tempList.get(k1)][i]>distance||data[i][(int)tempList.get(k1)]>distance)
{//若新加入的元素通信距离大于阙值
flag2=1;//判断该元素与簇中元素的通信距离是否大于阈值
}
}
if(flag2==0)
{
tempList.add(i);//将该元素加入簇中
used[i]=true;
border[i][j]=true;
border[j][i]=true;
count++;
break;
}
}
}
}
}
if (m==list.size()&&!border[i][j]&&!flag&&!used[i]&&!used[j])//遍历所有簇,并不能将现有的数据加入进去,则新建一个list
{
if(number<direction)//若簇的数目小于约束条件
{
List tempList = new ArrayList();
number++;
tempList.add(i);
tempList.add(j);
used[i]=true;
used[j]=true;
border[i][j]=true;
count+=2;
list.add(tempList);
}
}
}
}
}
}
}
return list;
}
private int[][] getDistance(int[][] data)
{
int length = data.length;
//找到通信代价最大值
int max = getMaxDistance(data);
//计算通信距离
for (int i = 0; i < length; i++) {
for (int j = i; j < length; j++) {
data[i][j] = max - data[i][j] + 1;
}
data[i][i] = 0;
}
return data;
}
private int getMaxDistance(int[][] data)//计算最大距离
{
int max=-1;
int length=data.length;
for (int i = 0; i < length; i++)
{
for (int j = i; j < length; j++)
{
if (data[i][j] >= max)
{
max = data[i][j];
}
}
}
return max;
}
private int calculateDistance(int[][] data, List list, int maxDistance)
{
int totalDistance=0;
//先找到两个相邻的簇,然后匹配簇中的元素
System.out.println("相连接的元素为:");
for (int i = 0; i < list.size()-1; i++)
{
List preList= (List) list.get(i);
for (int j=i+1;j<list.size();j++)
{
List nextList=(List)list.get(j);
for (int m=0;m<preList.size();m++)//进行元素的两两匹配
{
for (int n=0;n<nextList.size();n++)
{
if(data[(int) preList.get(m)][(int) nextList.get(n)]<maxDistance&&data[(int) preList.get(m)][(int) nextList.get(n)]>0)
{//若两元素间有链路相链接
System.out.println((int) preList.get(m)+" "+(int) nextList.get(n));
totalDistance+=data[(int) preList.get(m)][(int) nextList.get(n)];
}
if(data[(int)nextList.get(n)][(int)preList.get(m)]<maxDistance&&data[(int)nextList.get(n)][(int)preList.get(m)]>0)
{//若两元素间有链路相链接
System.out.println((int) nextList.get(n)+" "+(int) preList.get(m));
totalDistance+=data[(int) nextList.get(n)][(int) preList.get(m)];
}
}
}
}
}
return totalDistance;
}
}
















