BGLL算法 C++实现

8 篇文章 0 订阅
3 篇文章 0 订阅

实际上,BGLL算法就是在CNM算法的基础之上,再进一步,通过将CNM算法的结果中处于同一个社团的节点看作一个节点,再使用CNM算法进行社团划分,照此步骤反复迭代,每一次迭代记作一个pass,直到无法继续划分为止(就是在节点合并后,Q也不再增加)。从而尽量减轻因CNM算法的贪心策略造成的社团划分效果不佳,CNM算法实现可参考前文《CNM算法C++实现》

下文示例数据下载链接:facebook_combined

#include<iostream>
#include<cstring>
#include<fstream>
#define N 10000
#define INF 100000000
using namespace std;

int flag,nn,n,M,row,col,A[N][N],B[N][N],book[N],root[N],term[N];
float delta_Q[N][N],a[N],Q,now_Q_change;
void readData();
void initialize();
float themax();
void update_Q_delta();
void printResult();
void solve(int nn);
void formB();

int main()
{
    cin>>nn;
    fstream readfile;
    readfile.open("C:\\Users\\lenovo\\Desktop\\网络科学导论cpp代码\\facebook_combined.txt",ios::in);
    if(!readfile.is_open ())
        cout << "Open file failure" << endl;
    flag=1;
    Q=0;
    int t=0;
    int v1,v2;
    while (!readfile.eof())            // 若未到文件结束一直循环
    {
        readfile >> v1 >> v2;
        //cout<<v1<<" "<<v2<<endl;
        B[v1][v2]=1;
        B[v2][v1]=1;
    }
    readfile.close();   //关闭文件
    while (flag==1)
    {
        flag=0;
        cout<<"第"<<++t<<"次pass"<<endl;
        solve(nn);
    }

    return 0;
}

void solve(int nn)
{
    M=0;
    n=nn;
    memset(book,0,sizeof(book));
    memset(a,0,sizeof(a));
    readData();
    initialize();
    now_Q_change=themax();
    //cout<<"now_Q_change是:"<<now_Q_change<<endl;
    while (now_Q_change>0.0000001)
    {
        flag=1;
        //cout<<"(row,col):("<<row<<","<<col<<")"<<endl;
        book[col]=1;
        root[col]=row;
        //cout<<"root["<<col<<"]:"<<row<<endl;
        cout<<"now_Q_change:"<<now_Q_change<<endl;
        Q+=now_Q_change;
        update_Q_delta();
        now_Q_change=themax();
        //cout<<"now_Q_change是:"<<now_Q_change<<endl;
    }
    printResult();
    return ;
}

void readData()
{
    for (int i=1;i<=n;i++)
        root[i]=-1;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            A[i][j]=B[i][j];
            if (A[i][j]&&i>j)
                M+=A[i][j];
        }
    }
    /*
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            cout<<A[i][j]<<" ";
        }
        cout<<endl;
    }
    */
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            if (A[i][j]!=0)
            {
                a[i]+=A[i][j];
            }
            delta_Q[i][j]=-INF;
        }
    }
    for (int i=1;i<=n;i++)
    {
        a[i]/=(2*M);
        //cout<<"a["<<i<<"]:"<<a[i]<<endl;
    }
    return;
}

void initialize()
{
    float temp=0.5;
    temp/=M;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            if (A[i][j]>0)
            {
                delta_Q[i][j]=temp-a[i]*a[j];
            }
            else
                delta_Q[i][j]=0;
        }
    }
    /*
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            cout<<A[i][j]<<" ";
        }
        cout<<endl;
    }*/
    return ;
}

float themax()
{
    float curmax=-INF;
    for (int i=1;i<=n;i++)
    {
        if (book[i]==1)
            continue;
        for (int j=1;j<=n;j++)
        {
            if (book[j]==1)
                continue;
            if (curmax<delta_Q[i][j])
            {
                curmax=delta_Q[i][j];
                row=i;
                col=j;
            }
        }
    }
    //cout<<"(row,col):("<<row<<","<<col<<")"<<endl;
    return curmax;
}

void update_Q_delta()
{
    //row行消失,只更新col行和col列,col列用col行对称过去即可
    for (int i=1;i<=n;i++)
    {
        if (book[i]==1||col==i)
            continue;
        if (A[col][i]!=0&&A[row][i]!=0)
        {
            delta_Q[col][i]=delta_Q[col][i]+delta_Q[row][i];
        }
        else if (A[col][i]!=0&&A[row][i]==0)
        {
            delta_Q[col][i]=delta_Q[col][i]-2*a[row]*a[i];
        }
        else if (A[col][i]==0&&A[row][i]!=0)
        {
            delta_Q[col][i]=delta_Q[row][i]-2*a[col]*a[i];
        }
    }
    for (int i=1;i<=n;i++)
    {
        if (book[i]==1)
            continue;
        delta_Q[i][col]=delta_Q[col][i];
    }
    a[col]+=a[row];
    return ;
}

void printResult()
{
    int seq=0;
    cout<<"Q值为:"<<Q<<endl;
    for (int i=1;i<=n;i++)
    {
        cout<<"节点"<<i<<"的根为:"<<root[i]<<endl;
        if (root[i]==-1)
        {
            term[i]=++seq;
        }
    }
    for (int i=1;i<=n;i++)
    {
        int now=i;
        while (root[now]!=-1)
        {
            now=root[now];
        }
        cout<<"节点"<<i<<"的根是节点:"<<now<<endl;
        term[i]=term[now];
    }
    //至此,seq变量表示新矩阵大小是seq*seq的
    nn=seq;
    formB();
    return ;
}

void formB()
{
    memset(B,0,sizeof(B));
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            if (term[i]!=term[j])//就是说i和j在同一个社团内,他们要形成同一个节点
            {
                B[term[i]][term[j]]+=A[i][j];
                //B[term[j]][term[i]]+=A[i][j];
            }
        }
    }
    /*
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            cout<<B[i][j]<<" ";
        }
        cout<<endl;
    }*/
    return ;
}

结果的话由于实在太长,所以只截取了部分关键结果(相邻两次迭代连接处),最终一共是迭代了五次。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
BGLL算法(Bipartite Graph Louvain Algorithm)是一种用于社区发现的算法,其特点是能够处理具有两个不同节点集的二分图。这种算法在MATLAB中有相应的实现。 使用MATLAB进行BGLL算法实现,首先需要构建二分图的邻接矩阵。对于一个有N1个节点的集合A和N2个节点的集合B的二分图,邻接矩阵的大小为N1 × N2。矩阵的每个元素表示A集合的某个节点与B集合的某个节点之间的边的权重。 接下来,可以使用MATLAB提供的函数来进行BGLL算法实现。例如,可以使用`biadjacency_matrix`函数将邻接矩阵转换为BGLL算法所需的输入格式。然后,可以使用`BGrlouvain`函数来执行BGLL算法,该函数会返回得到的社区划分结果。 下面是一个简单的MATLAB代码示例,用于实现BGLL算法: ```matlab % 构建二分图的邻接矩阵 adjacency_matrix = [1 0 1 1; 0 1 1 1; 1 1 0 0; 0 0 1 1; 1 0 1 0; 0 1 0 1]; % 将邻接矩阵转换为BGLL算法的输入格式 biadjacency_matrix = biadjacency_matrix(adjacency_matrix); % 执行BGLL算法 [communities, Q] = BGrlouvain(biadjacency_matrix); % 输出社区划分结果和模块度值 disp(communities); disp(Q); ``` 以上代码中,`adjacency_matrix`表示二分图的邻接矩阵,`biadjacency_matrix`是转换后的BGLL算法输入格式,`communities`表示得到的社区划分结果,`Q`表示模块度值。 这只是一个简单的示例,实际应用中,可能需要根据具体的问题进行相应的调整和扩展。希望以上回答对您有帮助!
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值