大连海事大学智能科学与技术专业课程设计福利

写法说明

该实验通过调整:生成地图的类型(1.随机边权抽象图。2.满足三角形不等式规则的实际二维平面地图),种群数量,迭代代数,变异概率等相关影响结果的因素,分别对随机生成的地图进行求解。并通过dfs暴力搜索对点数比较少的地图暴力求解最优解。经过比较发现,种群数量以及迭代次数都和求解所得路径的长度成负相关关系。

附代码:

#include<bits/stdc++.h>
using namespace std;
#define maxn 150
#define UNIT 2052
#define inf 0x3f3f3f3f
const double Pacs=0.8;//杂交概率
const double Pvan=0.05;//变异概率
struct way
{
    int q[maxn];
    double val;
}ans;
vector<way>a;
bool operator < (way a,way b)
{
    return a.val>b.val;
}
int n,m,T_T;///n为点数,m为个体数
double dis[maxn][maxn];
int make_data(int n,int kind)//生成n个点的无向边权完全图
{
    memset(dis,0,sizeof(dis));
    if(kind==1)//生成平面n点,满足三角形不等式
    {
        double x[maxn],y[maxn];
        for(int i=1;i<=n;i++)
        {
            x[i]=rand();
            y[i]=rand();
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                double sx=x[i]-x[j],sy=y[i]-y[j];
                dis[j][i]=dis[i][j]=sqrt(sx*sx+sy*sy);
            }
        }
    }
    if(kind==2)//随机生成完全图
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                double sx=rand(),sy=rand();
                dis[j][i]=dis[i][j]=sqrt(sx*sx+sy*sy);
            }
        }
    }
    return n;
}
void outmap()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            printf("%.5lf ",dis[i][j]);
        }
        printf("\n");
    }
}
void outway(way x)
{
    printf("%lf : ",x.val);
    for(int i=0;i<n;i++)
    {
        printf("%d -> ",x.q[i]);
    }
    printf("%d\n",x.q[0]);
}
double Get_val(way x)
{
    double ret=0;
    for(int i=0;i<n-1;i++)
    {
        ret+=dis[x.q[i]][x.q[i+1]];
    }
    ret+=dis[x.q[n-1]][x.q[0]];
    return ret;
}
int creat_way(int x)//随机生成x个路径
{
    a.clear();
    way now;
    int m=0;
    x--;
    for(int i=0;i<n;i++) now.q[i]=i+1;
    now.val=Get_val(now);
    a.push_back(now);
    ans=now;
    outway(ans);
    while(x--)
    {
        for(int i=0;i<n;i++)
        {
            now.q[i]=a[m].q[i];
        }
        m++;
        random_shuffle(now.q,now.q+n);
        now.val=Get_val(now);
        a.push_back(now);
        //outway(now);
        if(ans<now)ans=now;
    }
    return a.size();
}
void variation(way &x)
{
    int p1=rand()%n,p2=rand()%n;
    int temp=x.q[p1]; x.q[p1]=x.q[p2]; x.q[p2]=temp;
    x.val=Get_val(x);
}
way across(way a,way b)
{
    bool vis[maxn]={0};
    way ret;
    int p1=rand()%n,p2=rand()%n;
    int l=min(p1,p2),r=max(p1,p2),cnt=0;
    for(int i=l;i<=r;i++)
    {
        ret.q[cnt++]=a.q[i];
        vis[a.q[i]]=1;
    }
    for(int i=0;i<n;i++)
    {
        if(!vis[b.q[i]])
        {
            ret.q[cnt++]= b.q[i];
        }
    }
    //outway(ret);
    ret.val=Get_val(ret);
    return ret;
}
vector<way> work_Ga()//一次迭代
{
    double s[UNIT]={0};
    vector<way>ret;
    int e=a.size(),i,j;
    for(i=0;i<e;i++)
    {
        s[i+1]=s[i]+a[i].val;
    }
    for(i=0,j=e;i+1<e;i +=2)//杂交生成子代
    {
        if((rand()%1000) > Pacs*1000)continue;
        way temp=across(a[i],a[i+1]);
        if((rand()%1000) < Pvan*1000 )variation(temp);
        s[j+1]=s[j]+temp.val;
        j++;
        a.push_back(temp);
        if(ans<temp)
        {
            ans=temp;
            //outway(ans);
        }
    }
    double limit=s[a.size()-1];
    int aim_num=m;//下一代个数
    while(aim_num--)
    {
        double pos=limit+1;
        while(pos>limit)
        {
            pos=0.0001*(rand()%10000)+((long long int)rand()*rand())%((int)floor(limit)+1);
        }
        int l=0,r=a.size()-1;
        //printf("pos=%lf %d limit=%lf %d\n",pos,r,limit,(int)floor(limit));
        //for(int i=0;i<r;i++)printf("%lf ",s[i]);printf("\n\n\n");
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(s[mid]>=pos)r=mid-1;
            else l=mid+1;
        }
        if(ans<a[r+1])
        {
            ans=a[r+1];
            //outway(ans);
        }
        ret.push_back(a[r+1]);
    }
    return ret;
}
bool test_vis[maxn];
way test_best;
void dfs(int x,way now)
{
    if(x==n)
    {
        now.val=Get_val(now);
        if(test_best<now)test_best=now;
        return;
    }
    for(int i=1;i<=n;i++)
    {
        if(!test_vis[i])
        {
            test_vis[i]=1;
            now.q[x]=i;
            dfs(x+1,now);
            test_vis[i]=0;
        }
    }
}
way BM_test()
{
    memset(test_vis,0,sizeof(test_vis));
    test_best.val=inf;
    way now;
    dfs(0,now);
    return test_best;
}
void OutInformation()
{
    printf("交叉概率:%.2lf\n变异概率: %.2lf\n完全图点数:%d\n种群个数: %d\n迭代次数: %d\n",
           Pacs,Pvan,n,m,T_T);
}
int main()
{
    srand(19980720);
    n=make_data(50,1);
    //outmap();
    printf("按顺序遍历结果:");
    m=creat_way(1000);
    //printf("暴力搜索最优结果:");outway( BM_test() );///暴力测试n个点的最优解
    T_T = 100;//迭代次数
    OutInformation();
    while(T_T--)
    {
        //printf("s");
        a=work_Ga();
        //if(T_T%10)outway(ans);
    }
    printf("遗传算法得到结果:");
    outway(ans);
    while(1)getchar();
    return 0;
}