C++实现KL算法 1-优化 2-式划分

Kl算法

KL 算法是 Kernighan 与 Lin 两个人在 1970 年设计一个图划分算法,是在寻找图 G 的一个极小成本的可许划分。KL 算法也是一种基于贪心算法的划分算法,通过交换两模块中的元素实现两模块间通信代价极小化。由于贪心算法会导致局部最优解,KL 算法在交换模块中元素时把所有可能交换后产生的代价增益都计算出来,从中选择一个最好的交换元素进行交换。这样在某种程度上降低了局部最优的风险,但会造成算法的时间复杂性。不过,KL 算法在很大程度上会给出全局最优解。实验表明 KL 算法给出的划分通信代价极小化是最好的。
【异构分布式嵌入式系统的优化设计方法,许巾一,陈仪香,李凯旋,2020 年 1 月】

λ-优化与 2 式划分

λ 优化:两个集合间的λ点互换是指交换这两个集合的λ元素。1-互换是将一个集合的单点与另一个集合的单点进行互换。一个配置称为 1-优化,若不再存在 1-互换导致划分成本的下降。
2 式划分:最简单划分问题是:给一个 2n 节点的图 G,其中每
个节点都拥有相同的尺寸,寻找一个极小成本划分将 2n 节点划分成都含有 n
个节点的两个集合。

题目

在这里插入图片描述

实现效果

在这里插入图片描述

Cpp实现

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;

const int task_num = 8;

vector<vector<double>> init(double data[][task_num]);                                                                 //初始化函数

//计算D
vector<double> countD(vector<vector<double>> &data, vector<int> tempA,vector<int> tempB);
//计算外代价
vector<double> countE(vector<vector<double>> data,vector<int> A,vector<int> B);
//计算内代价
vector<double> countI(vector<vector<double>> data,vector<int> A);
//计算总代价
double calculateDistance(vector<vector<double>> data, vector<int> tempA, vector<int> tempB);


template <typename T>
void res_print(vector<T> A,vector<T> B, int type);

// #define CountD
// #define CountE
#define CountI

int main()
{

    vector<int> A,B;
    double matrix[task_num][task_num] =
    {
    {0,     1,      0.5,    0,      0.5,    1,      0,      0.5},
    {1,     0,      0.5,    0,      0,      0,      0,      0},
    {0.5,   0.5,    0,      0.5,    1,      0.5,    0,      0},
    {0,     0,      0.5,    0,      0,      1,      0,      0.5},
    {0.5,   0,      1,      0,      0,      0.5,    1,      0},
    {1,     0,      0.5,    1,      0.5,    0,      0.5,    0.5},
    {0,     0,      0,      0,      1,      0.5,    0,      0.5},
    {0.5,   0,      0,      0.5,    0,      0.5,    0.5,    0},
    };//导入通信代价矩阵


// //      4
//     char charA[4] = {'a','d','g','h'};
//     char charB[4] = {'b','c','e','f'};

//     //4
//     char charA[4] = {'a','c','e','h'};
//    char charB[4] = {'b','d','g','f'};

//   //   4
//     char charA[4] = {'a','c','e','f'};
//    char charB[4] = {'b','d','g','h'};

//  4
    char charA[4] = {'a','b','c','d'};
    char charB[4] = {'e','f','g','h'};

 //4.5
//     char charA[4] = {'a','d','e','h'};
//    char charB[4] = {'b','c','g','f'};

//     char charA[4] = {'a','e','f','h'};
//    char charB[4] = {'b','c','d','g'};
	for(int i = 0; i < task_num / 2; i++)
	{
		A.push_back(charA[i]-'a');
		B.push_back(charB[i]-'a');
	}
    cout<<"初始划分集为:"<<endl;
    res_print(A,B,0);

    vector<vector<double>> data = init(matrix);

    vector<vector<double>> tempMatrix = data;
    
    for(int i = 0; i< tempMatrix.size(); i++)
    {
        for(int j = 0; j< tempMatrix.size(); j++)
    {
        cout<<tempMatrix[i][j]<<"\t";
    }
    cout<<endl;
    }

    vector<int> tempA, resA;                //resA 存放结果
    vector<int> tempB, resB;                //res
    vector<double> G;                       //G 存放每一次的g
    vector<double> D_A, D_B;
    int p = 0;                              
    double Gain=1;
    while(Gain > 0)
    {  
        G.clear();                          //清空之前G
        D_A.clear();
        D_B.clear();
        resA.clear();
        resB.clear();

        tempA = A;
        tempB = B;
       
        p = 0;
   
        while(p != 4)
        {   

            D_A = countD(data,tempA,tempB);
            D_B = countD(data,tempB,tempA);
            cout<<"p="<<p+1<<endl;
            cout<<"外部与内部成本之差"<<endl;

            for(int i = 0; i < D_A.size(); i++)
            {
            
                cout<<char(tempA[i]+'a')<<": "<<D_A[i];
                cout<<endl;
            }
            
            for(int i = 0; i < D_B.size(); i++)
            {
    
                cout<<char(tempB[i]+'a')<<": "<<D_B[i];
                cout<<endl;
            }
            int max_g = -100;
            int max_index_A, max_index_B;
            cout<<"交换对(x,y)"<<"\tDx\tDy\tCxy\t收益gp"<<endl;

            for(int i = 0; i < tempA.size(); i++)
            {
                for(int j = 0; j < tempB.size(); j++)
                {
                    int g_temp = D_A[i] + D_B[j] - 2*data[tempA[i]][tempB[j]];
                    cout<<"("<< char(tempA[i]+'a')<<","<<char(tempB[j]+'a')<<")\t\t"<<D_A[i]<<"\t"<<D_B[j]<<"\t"<<data[tempA[i]][tempB[j]]<<"\t"<<g_temp<<endl;
                    if(g_temp > max_g)
                    {
                        max_index_A = i;
                        max_index_B = j;
                        max_g = g_temp;
                    }
                }
            }
            // 已经选过的放到结果中
            resA.push_back(tempA[max_index_A]);
            resB.push_back(tempB[max_index_B]);

            tempA.erase(tempA.begin() + max_index_A);
            D_A.erase(D_A.begin() + max_index_A);

            tempB.erase(tempB.begin() + max_index_B);
            D_B.erase(D_B.begin() + max_index_B);
            G.push_back(max_g);
            p++;
        }
        int res = 0;
        int max_G = -10000;
        int res_max_index = 0;
        for(int i = 0; i < G.size(); i++)
        {
            
            res += G[i];
            
            if(res > max_G)
            {
                res_max_index = i;
                max_G = res;
            }
        }
        Gain = max_G;
            
        cout<<"k =" <<res_max_index<<endl;
        if(Gain != 0 || res_max_index != 0)
        {
       // if(Gain > 0)
       // {
        //  交换
        A.clear();
        B.clear();
        for(int i = 0; i < task_num/2; i++)
        {  
            if(i <= res_max_index)
            {
                A.push_back(resB[i]);
                B.push_back(resA[i]);
            }
            else
            {
                A.push_back(resA[i]);
                B.push_back(resB[i]);
            }
        }
        
        //res_print(A,B);
            sort(A.begin(), A.begin()+A.size());
          
            sort(B.begin(), B.begin()+B.size());
         
            cout<<"交换"<<endl;
            res_print(A,B,0);
    
        }
       cout<<"Gain = "<< Gain<<endl;
    }


    
    cout<<"划分结果:"<<endl<<endl;
    res_print(A, B, 0);
    double totalDistance =  calculateDistance(data, A, B);
    cout<<"通信代价="<<totalDistance<<endl;



	return 0;
}

vector<double> countD(vector<vector<double>> &data, vector<int> tempA,vector<int> tempB)
{
    vector<double> res;
	vector<double> EA=countE(data, tempA, tempB);           // 计算外部代价
	vector<double> IA=countI(data, tempA);                  // 计算内部代价
    #ifdef CountD
    cout<<"countD"<<endl;
    res_print(tempA,tempB);
    res_print(EA, IA);
    #endif
	for(int i=0;i<tempA.size();i++)
	{
	    res.push_back(EA[i]-IA[i]);
	}
		

    return res;

}

template <typename T>
void res_print(vector<T> A,vector<T> B, int type)
{

    for(int i = 0; i < A.size(); i++)
	{
        if(!type)
            cout<<char(A[i]+'a')<<" ";
        else
             cout<<A[i]<<" ";
	}
    cout<<endl;
    for(int i = 0; i < B.size(); i++)
	{
        if(!type)
		    cout<<char(B[i]+'a')<<" ";
        else
            cout<<B[i]<<" ";
	}
    cout<<endl;
}




vector<double> countE(vector<vector<double>> data,vector<int> A,vector<int> B)//计算外代价
{
    vector<double> E;
    
    for(int i=0;i < A.size();i++)
    {   
        E.push_back(0);
        for(int j = 0; j < B.size(); j++)
        {
            E[i]+=data[A[i]][B[j]];
        }
    }
    #ifdef CountE

        cout<<"countE"<<endl;
        res_print(A,B);
        res_print(E, E);
    #endif
   
    return E;
}

vector<double> countI(vector<vector<double>> data,vector<int> A)//计算内代价
{
    vector<double> I;
    for(int i = 0; i < A.size(); i++)
    {   
        I.push_back(0);
        for(int j = 0;j < A.size();j++)
        {
            I[i] += data[A[i]][A[j]];
        }
    }
    return I;
}






vector<vector<double>> init(double data[][task_num])
{
    vector<vector<double>> res;
    for(int i = 0; i < task_num; i++)
    {
        vector<double> temp;
        for(int j = 0; j < task_num; j++)
        {
            temp.push_back(data[i][j]);
        }
        res.push_back(temp);
    }
    

    return res;
}


double calculateDistance(vector<vector<double>> data, vector<int> tempA, vector<int> tempB)
{
    double totalDistance=0;
    //先找到两个相邻的簇,然后匹配簇中的元素
    for (int i = 0; i < tempA.size(); i++) 
    {
        //vector<int> last= list[i];//得到相邻的簇
        
        for (int j=0; j < tempB.size();j++)
        {   
            double sum = 0;
            //vector<int> next=list[j];//得到相邻的簇

            if( data[tempA[i]][tempB[j]])
            {//若两元素间有链路相链接
                sum += data[tempA[i]][tempB[j]];
                totalDistance+=data[tempA[i]][tempB[j]];
            }
            
                
            
       // cout<< "模块"<< i + 1 <<"与模块"<< j + 1<<"通信代价:"<<sum<<endl;
        }
       
    }
    return totalDistance;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值