多模块划分的基本算法是依据任务间的通信代价进行聚类,两个任务通信代价越高或越频繁,越应该把这两个任务划分到一个模块(簇,类),依据划分结果,计算块间的通信代价,而模块内的通信代价量认为为零。这个过程 可以多次进行,最终选一个模块间通信代价之和最小者,算法终止。实现了 智能系统的多模块优化划分。

聚类特点
• 聚类是将数据进行分组。
• 聚类中的组称为簇,
• 聚类中的簇不是预先定义的,而是根据实际数据的特征按照数据间的相似性来定义的。
• 簇一般具有特征:
(1)簇是一些相似成员的集合,
(2)不同簇中的成员是不相似的,
(3)簇中的任两点间距离要小于簇中的点与簇外任一点之间的距离

基于聚类的划分方法有三种,分别为单连接技术(Single Link) , 全连接技术(Complete Link) ,平均连接技术(Average Link)

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

微服务 maven 项目结构_微服务 maven 项目结构


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

微服务 maven 项目结构_List_02


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

微服务 maven 项目结构_sed_03


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

微服务 maven 项目结构_微服务 maven 项目结构_04

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;
    }
}