天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 60|回复: 0

遗传算法解决最大割问题

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
//*****************************************************************

//https://mp.weixin.qq.com/s?__biz=MzU0NzgyMjgwNg==&mid=2247484679&idx=1&sn=79218705447398ad90ca661f482f0ab0&source=41#wechat_redirect
//遗传算法解决最大割问题(MaxCut_GA)

//*****************************************************************

//输出样例(dsjc001.txt)

//*****************************************************************

//Check_Max_Cut = 7

//Max_Cut = 7

//Distribution of each vertex :

//0 1 0 0 1 1 1

//*****************************************************************

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <fstream>

#include <cmath>

#include <time.h>

#define cin fin

#define cout fout

#define INF 1000000

#define Chromosome_Num 10//遗传过程中的群体大小

#define Max_Iter 100000//最大遗传迭代次数



using namespace std;

ifstream fin ( "C:\Users\jp\Desktop\新建文件夹\GA-master\data\dsjc001.txt" );

ofstream fout ( "C:\Users\jp\Desktop\Output.txt" );

int N, E;//算例规模(节点数,无向边数);

int **Chromosome;//群体中的所有染色体,每条染色体上的每个节点代表图中顶点,用0,1表示其分别位于哪个集合中;

int *Chromosome_CutValue;//群体每条染色体对应分配方案的被切割边数;



int *ParentA, *ParentB;//遗传过程中用于杂交的父代;

int *Offspring;//遗传过程所得到的子代;

int Offspring_CutValue;//遗传过程所得到子代对应分配方案的被切割边数;



int **Graph;//存储整个图结构

int MaxCutValue;//多代遗传过后的最大被切割边数;

int *MaxChromosome;//多代遗传过后最大被切割边数对应的分配方案;

//*****************************************************************

void Init() {

    char ch;

    cin >> ch >> N >> E;



    //所有动态数组的初始化

    ParentA = new int[N + 10];

    ParentB = new int[N + 10];

    Offspring = new int[N + 10];

    MaxChromosome = new int[N + 10];

    Chromosome_CutValue = new int[Chromosome_Num + 10];

    Chromosome = new int*[Chromosome_Num + 10];

    for ( int i = 1; i <= Chromosome_Num; ++i )

        Chromosome[i] = new int[N + 10];

    Graph = new int*[N + 10];

    for ( int i = 1; i <= N; ++i )

        Graph[i] = new int[N + 10];



    for ( int i = 1; i <= Chromosome_Num; ++i ) {

        Chromosome_CutValue[i] = 0;

        for ( int j = 1; j <= N; ++j )

            Chromosome[i][j] = 0;

    }

    for ( int i = 1; i <= N; ++i )

        for ( int j = 1; j <= N; ++j )

            Graph[i][j] = 0;



    //读入并存储图

    int A, B;

    for ( int i = 1; i <= E; ++i ) {

        cin >> ch >> A >> B;

        Graph[A][B] = 1;

        Graph[B][A] = 1;

    }

}

//*****************************************************************

void Genetic_Construction() {

    MaxCutValue = -INF;

    for ( int P = 1; P <= Chromosome_Num; ++P ) {

        //用随机方法构造第P条染色体

        for ( int i = 1; i <= N; ++i )

            Chromosome[P][i] = rand() % 2;



        //计算第P条染色体对应分配方案的被切割边数

        for ( int i = 1; i <= N; ++i )

            for ( int j = i + 1; j <= N; ++j )

                if ( Graph[i][j] == 1 && Chromosome[P][i] != Chromosome[P][j] )

                    Chromosome_CutValue[P]++;



        //更新最大被切割边数及其对应的节点分配方案

        if ( MaxCutValue < Chromosome_CutValue[P] ) {

            MaxCutValue = Chromosome_CutValue[P];

            for ( int i = 1; i <= N; ++i )

                MaxChromosome[i] = Chromosome[P][i];

        }

    }

}

//*****************************************************************

void Genetic_Crossover() {

    //用轮盘赌方法从群体中随机选择两个父代

    int Sum[100];

    int A, B, Random;



    Sum[0] = 0;

    for ( int i = 1; i <= Chromosome_Num; ++i )

        Sum[i] = Sum[i - 1] + Chromosome_CutValue[i];

    Random = rand() % Sum[Chromosome_Num] + 1;

    for ( int i = 1; i <= Chromosome_Num; ++i )

        if ( Random <= Sum[i] ) {

            A = i;

            break;

        }

    Sum[0] = 0;

    for ( int i = 1; i <= Chromosome_Num; ++i )

        if ( i != A )

            Sum[i] = Sum[i - 1] + Chromosome_CutValue[i];

        else

            Sum[i] = Sum[i - 1];

    Random = rand() % Sum[Chromosome_Num] + 1;

    for ( int i = 1; i <= Chromosome_Num; ++i )

        if ( Random <= Sum[i] ) {

            B = i;

            break;

        }



    for ( int i = 1; i <= N; ++i ) {

        ParentA[i] = Chromosome[A][i];

        ParentB[i] = Chromosome[B][i];

    }



    //对选取的父代进行杂交得到子代

    //其中杂交方法为若两个父代的同一节点在相同集合中,则保留;否则,对随机分配该节点至任意集合中;

    for ( int i = 1; i <= N; ++i )

        if ( ParentA[i] == ParentB[i] )

            Offspring[i] = ParentA[i];

        else

            Offspring[i] = rand() % 2;

}

//*****************************************************************

void Genetic_Mutation() {

    //在0.05的概率下,将子代的某个节点从一个集合移动到另一个集合中;

    for ( int i = 1; i <= N; ++i )

        if ( rand() % 20 == 1 )

            Offspring[i] = 1 - Offspring[i];



    //计算子代染色体对应分配方案的被切割边数;

    Offspring_CutValue = 0;

    for ( int i = 1; i <= N; ++i )

        for ( int j = i + 1; j <= N; ++j )

            if ( Graph[i][j] == 1 && Offspring[i] != Offspring[j] )

                Offspring_CutValue++;

}

//*****************************************************************

void Genetic_Update() {

    int MinCutValue = INF;

    int MinSign;



    //更新群体:若得到的子代的被切割边数大于群体中最小的被切割边数,则用该子代取代;

    for ( int i = 1; i <= Chromosome_Num; ++i )

        if ( Chromosome_CutValue[i] < MinCutValue ) {

            MinCutValue = Chromosome_CutValue[i];

            MinSign = i;

        }



    if ( MinCutValue < Offspring_CutValue ) {

        for ( int i = 1; i <= N; ++i )

            Chromosome[MinSign][i] = Offspring[i];

        Chromosome_CutValue[MinSign] = Offspring_CutValue;

        if ( MaxCutValue < Chromosome_CutValue[MinSign] ) {

            MaxCutValue = Chromosome_CutValue[MinSign];

            for ( int i = 1; i <= N; ++i )

                MaxChromosome[i] = Chromosome[MinSign][i];

        }

    }

}

//*****************************************************************

int Check() {

    //检验分配方案的实际被切割边数与存储的被切割边数是否一致;

    int CutValue = 0;

    for ( int i = 1; i <= N; ++i )

        for ( int j = i + 1; j <= N; ++j )

            if ( Graph[i][j] == 1 && MaxChromosome[i] != MaxChromosome[j] )

                CutValue++;

    return CutValue;

}

//*****************************************************************

void Output() {

    cout << "*****************************************************************" << endl;

    cout << "Check_Max_Cut = " << Check() << endl;

    cout << "Max_Cut = " << MaxCutValue << endl;

    cout << "Distribution of each vertex : " << endl;

    for ( int i = 1; i <= N; ++i )

        cout << MaxChromosome[i] << " ";

    cout << endl;

    cout << "*****************************************************************" << endl;

}

//*****************************************************************

int main() {

    srand ( ( unsigned ) time ( NULL ) );

    Init();//初始化数组,读入并存储图;

    Genetic_Construction();//生成初始群体;

    for ( int i = 1; i <= Max_Iter; ++i ) {

        Genetic_Crossover();//染色体交叉;

        Genetic_Mutation();//染色体变异;

        Genetic_Update();//生成下一代群体;



        /*

        for ( int j = 1; j <= Chromosome_Num; ++j )

            cout << Chromosome_CutValue[j] << " ";

        cout << endl;

        getchar();

        */

    }

    Output();//结果输出;

    return 0;

}

//*****************************************************************

 

 

 

 

遗传算法解决最大割问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 10:25 , Processed in 0.147903 second(s), 28 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表