如何让一个遗传算法程序自动运行多次后停止

shuiyrn 2014-05-01 12:22:12
因为初始化函数individual、选择函数select、交叉函数crossover、变异函数mutated,均包含有随机数rand函数,在重复运行过程中,得到的结果总是一致的,即便我在MAIN函数中加了srand((unsigned)(time(NULL)));【是在for循环外】也是重复结果,求救!万分感谢!!
...全文
515 36 打赏 收藏 转发到动态 举报
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
shuiyrn 2014-05-08
  • 打赏
  • 举报
回复
引用 34 楼 fire_agan 的回复:
数据越趋于稳定时,越靠近最优解,说明最优解已经产生。
手问题是动执行的结果并不如此,那么一定是其中有错误了
shuiyrn 2014-05-08
  • 打赏
  • 举报
回复
引用 33 楼 zhao4zhong1 的回复:
试试用 CoCreateGuid Creates a GUID, a unique 128-bit integer used for CLSIDs and interface identifiers. HRESULT CoCreateGuid( GUID *pguid //Pointer to the GUID on return ); Parameter pguid [out] Pointer to the requested GUID on return. Return Value S_OK The GUID was successfully created. Win32 errors are returned byUuidCreate but wrapped as an HRESULT. Remarks The CoCreateGuid function calls the RPC function UuidCreate, which creates a GUID, a globally unique 128-bit integer. Use the CoCreateGuid function when you need an absolutely unique number that you will use as a persistent identifier in a distributed environment.To a very high degree of certainty, this function returns a unique value – no other invocation, on the same or any other system (networked or not), should return the same value. QuickInfo Windows NT: Use version 3.1 or later. Windows: Use Windows 95 or later. Windows CE: Unsupported. Header: Declared in objbase.h. Import Library: Included as a resource in ole32.dll. See Also UuidCreate 获取随机数。
再次感谢。原谅愚蠢的我还是不懂
  • 打赏
  • 举报
回复
引用 30 楼 shuiyrn 的回复:
[quote=引用 28 楼 ilikehigame 的回复:] 跟随机函数rand()有关!
基本可以确定跟他有关 只是不会修改 洗牌算法有点难理解[/quote] 随机函数rand()放在循环里就会出现出来的随机数在"一定的小范围的现象"我以前也遇到过;
刘海东121111 2014-05-07
  • 打赏
  • 举报
回复
数据越趋于稳定时,越靠近最优解,说明最优解已经产生。
赵4老师 2014-05-07
  • 打赏
  • 举报
回复
试试用 CoCreateGuid Creates a GUID, a unique 128-bit integer used for CLSIDs and interface identifiers. HRESULT CoCreateGuid( GUID *pguid //Pointer to the GUID on return ); Parameter pguid [out] Pointer to the requested GUID on return. Return Value S_OK The GUID was successfully created. Win32 errors are returned byUuidCreate but wrapped as an HRESULT. Remarks The CoCreateGuid function calls the RPC function UuidCreate, which creates a GUID, a globally unique 128-bit integer. Use the CoCreateGuid function when you need an absolutely unique number that you will use as a persistent identifier in a distributed environment.To a very high degree of certainty, this function returns a unique value – no other invocation, on the same or any other system (networked or not), should return the same value. QuickInfo Windows NT: Use version 3.1 or later. Windows: Use Windows 95 or later. Windows CE: Unsupported. Header: Declared in objbase.h. Import Library: Included as a resource in ole32.dll. See Also UuidCreate 获取随机数。
shiter 2014-05-06
  • 打赏
  • 举报
回复
路过学习一下,是不会是精度的问题。。。我猜的
  • 打赏
  • 举报
回复
引用 8 楼 shuiyrn 的回复:
[quote=引用 5 楼 u012061345 的回复:] 把你自己的select函数换一个名字。C++应该不会出现这种问题吧。
我也不明白原因,我换了select函数名字,居然没有错误了。 执行的时候,出现以下问题: 当我循环次数为5时, 969.6706000000003800 981.4860000000004400 989.0981000000006100 991.8421000000007600 992.8316000000006600 969.3265000000001200 981.5705000000002700 986.8746000000004400 992.6205000000005600 993.2190000000006200 ……数值明显在5次以内递增。 当循环次数50时, 971.9180000000001200 984.1036000000001400 989.0679000000002400 989.8645000000004800 994.2145000000005000 995.0089000000004900 995.0089000000008400 995.2086000000010700 995.2086000000010700 995.8059000000007500 996.2051000000005800 997.0027000000006900 997.0027000000006900 997.2024000000005800 997.2024000000006900 997.2024000000009200 997.2024000000009200 997.2024000000011500 997.2024000000011500 997.2024000000014900 997.2024000000014900 997.4021000000013800 997.4021000000017200 997.4021000000017200 997.4021000000018400 997.4021000000020600 997.6018000000016200 997.6018000000018400 998.0010000000016800 998.0010000000019100 998.0010000000020200 998.0010000000022500 998.0010000000022500 998.0010000000022500 998.0010000000024800 998.0010000000024800 998.0010000000027000 998.0010000000028200 998.0010000000028200 998.0010000000028200 998.0010000000028200 998.0010000000028200 998.0010000000028200 998.0010000000029300 998.0010000000029300 998.0010000000029300 998.0010000000029300 998.0010000000029300 998.0010000000029300 998.0010000000031600 大量重复数据出现。 同时有一点,其他条件一样,但没有加自动循环时,原来手动执行的结果是在940~987之间随机波动的。 这是我最搞不懂得一点,只能猜测跟循环与随机数之间的问题,不知能否从致谢数据中看出应该问题出自哪里? 附上main函数内 我把循环加进去的方式 srand((unsigned)(time(NULL))); for(n=0;n<50;n++) { generation=0; initialize(); //初始化 evaluate(); //适应度计算 keep_the_best(); while(generation<MAXGENS) { generation++; selects(); //轮盘赌 crossover(); //交叉 mutate(); //变异 report(); evaluate(); //计算适应度 elitist(); } fprintf(galog,"\n\nSimulation completed\n"); fprintf(galog,"\nBest member:\n"); for(m=0;m<NVARS;m++) { fprintf(galog,"\n var(%d)=%f",m,population[POPSIZE].gene[m]); } fprintf(galog,"\n\nBest fitness=%f",population[POPSIZE].fitness); fprintf(bestlog,"%2.16f\n",population[POPSIZE].fitness); Sleep(1000); } fclose(galog); fclose(bestlog); [/quote] 跟随机函数rand()有关!
shuiyrn 2014-05-06
  • 打赏
  • 举报
回复
引用 26 楼 zhao4zhong1 的回复:
随机必然有重复,所谓“不重复的随机”实际上是洗牌。 洗牌算法参考下面:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int d[6];
int i,n,a,b,t;
int c,j;
void main() {
    srand(time(NULL));
    printf("shuffle 0..n-1 demo\n");
    for (n=1;n<=5;n++) {/* 测试1~5个元素 */
        printf("_____n=%d_____\n",n);
        j=1;
        for (c=1;c<=n;c++) j=j*c;/* j为n! */
        j*=n*2;
        for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
            for (i=0;i<n;i++) d[i]=i;/* 填写0~n-1 */
            for (i=n;i>0;i--) {/* 打乱0~n-1 */
                a=i-1;b=rand()%i;
                if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
            }
            printf("%04d:",c);
            for (i=0;i<n;i++) printf("%d",d[i]);
            printf("\n");
        }
    }
    printf("shuffle 1..n demo\n");
    for (n=1;n<=5;n++) {/* 测试1~5个元素 */
        printf("_____n=%d_____\n",n);
        j=1;
        for (c=1;c<=n;c++) j=j*c;/* j为n! */
        j*=n*2;
        for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
            for (i=1;i<=n;i++) d[i]=i;/* 填写1~n */
            for (i=n;i>1;i--) {/* 打乱1~n */
                a=i;b=rand()%i+1;
                if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
            }
            printf("%04d:",c);
            for (i=1;i<=n;i++) printf("%d",d[i]);
            printf("\n");
        }
    }
}
虽然没怎么搞懂,不过还是很感谢你,也许手动才是正统的做法
shuiyrn 2014-05-06
  • 打赏
  • 举报
回复
引用 29 楼 wangyaninglm 的回复:
路过学习一下,是不会是精度的问题。。。我猜的
关键是手动一次次执行 和 自动循环执行 之间差别太大 要么是循环程序问题 要么是随机数在一次次循环执行中有问题,感觉是后者。
shuiyrn 2014-05-06
  • 打赏
  • 举报
回复
引用 28 楼 ilikehigame 的回复:
跟随机函数rand()有关!
基本可以确定跟他有关 只是不会修改 洗牌算法有点难理解
shuiyrn 2014-05-05
  • 打赏
  • 举报
回复
数据结果好像明显是递增的
shuiyrn 2014-05-05
  • 打赏
  • 举报
回复
引用 23 楼 zhao4zhong1 的回复:
将srand(time(NULL));放在main函数的第一句,其它任何地方不要再srand了。 val=((double)(signed __int64)(ull%1000000000000ui64)/1000000000000.0)*(high-low)+low;
修改后可以成功运行,但是结果还是挺多重复: 980.4367344661411600 990.4176335097541800 992.7921210066214100 994.0778773056360900 995.6598700430269000 997.3516701830604900 997.3516701830606100 997.4988534782337400 997.6190424232729600 997.7517135579880700 997.7517135579883000 997.8367832461960900 997.9052287558395200 997.9667366158439600 997.9667366158439600 998.0031432849145900 998.1668652981054500 998.1668652981055600 998.1668652981055600 998.7089261291017700 998.7089261291017700 998.7089261291020000 999.1917357835192200 999.1917357835193300 999.1917357835194500 999.1917357835194500 999.1917357835194500 999.2280267756201500 999.2617773316638900 999.2617773316640100 999.2617773316640100 999.2617773316641200 999.4086046470774800 999.4086046470778200 999.4086046470779400 999.4086046470780500 999.4086046470781600 999.4086046470781600 999.7052144639229700 999.7052144639230800 999.7237156875780800 999.7237156875780800 999.7237156875780800 999.7237156875780800 999.7237156875783100 999.7237156875783100 999.7237156875785300 999.7237156875786500 999.7237156875787600 999.7326095504170100 可以看出数据重复度少了些,但数据依然很集中。 有一点,凡是循环的到的数据都出奇的好且稳定,甚至会让人误以为目前参数相当合理,以至于每次运行结果都非常接近最优解,这是为什么?为何加了循环会让数据都往好的解靠拢?我试了其它函数也是这样,不敢说肯定会好,但应该是能说明一些什么问题,我不懂。 至于程序,我目前的状况是, initialize函数调用randval (你修改的版本) ; selects函数【因为之前加了#include<windows.h>后,提示select函数定义出错,所以加了s】 循环调用的是 p=rand()%1000/1000.0; ; crossover函数循环调用的是x=rand()%1000/1000.0; 和按Xover算术杂交算子杂交 ; 其中Xover循环调用的是alpha=rand()%1000/1000.0; ; mutate函数循环调用的是x=rand()%1000/1000.0; ; srand函数放在main函数中【没有放第一局,第一句放的是int m,n;,否则会提示m,n未定义的错误】 ; Sleep(1000);放在main循环运行该程序的结尾;
赵4老师 2014-05-05
  • 打赏
  • 举报
回复
将srand(time(NULL));放在main函数的第一句,其它任何地方不要再srand了。 val=((double)(signed __int64)(ull%1000000000000ui64)/1000000000000.0)*(high-low)+low;
赵4老师 2014-05-05
  • 打赏
  • 举报
回复
随机必然有重复,所谓“不重复的随机”实际上是洗牌。 洗牌算法参考下面:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int d[6];
int i,n,a,b,t;
int c,j;
void main() {
    srand(time(NULL));
    printf("shuffle 0..n-1 demo\n");
    for (n=1;n<=5;n++) {/* 测试1~5个元素 */
        printf("_____n=%d_____\n",n);
        j=1;
        for (c=1;c<=n;c++) j=j*c;/* j为n! */
        j*=n*2;
        for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
            for (i=0;i<n;i++) d[i]=i;/* 填写0~n-1 */
            for (i=n;i>0;i--) {/* 打乱0~n-1 */
                a=i-1;b=rand()%i;
                if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
            }
            printf("%04d:",c);
            for (i=0;i<n;i++) printf("%d",d[i]);
            printf("\n");
        }
    }
    printf("shuffle 1..n demo\n");
    for (n=1;n<=5;n++) {/* 测试1~5个元素 */
        printf("_____n=%d_____\n",n);
        j=1;
        for (c=1;c<=n;c++) j=j*c;/* j为n! */
        j*=n*2;
        for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
            for (i=1;i<=n;i++) d[i]=i;/* 填写1~n */
            for (i=n;i>1;i--) {/* 打乱1~n */
                a=i;b=rand()%i+1;
                if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
            }
            printf("%04d:",c);
            for (i=1;i<=n;i++) printf("%d",d[i]);
            printf("\n");
        }
    }
}
罗博士 2014-05-04
  • 打赏
  • 举报
回复
初始化代码是怎么写的?
罗博士 2014-05-04
  • 打赏
  • 举报
回复
引用 3 楼 shuiyrn 的回复:
[quote=引用 2 楼 FancyMouse 的回复:] 要么迭代太稳定,要么随机数没用对。一般后者可能性更大。
你好,可是我手动运行完全没问题啊[/quote] 手动运行是指......?
罗博士 2014-05-04
  • 打赏
  • 举报
回复
把你自己的select函数换一个名字。C++应该不会出现这种问题吧。
shuiyrn 2014-05-04
  • 打赏
  • 举报
回复
由于遗传算法的随机搜索的特性,在经过选择、杂交、变异的上千次迭代产生的最后种群,不可能每次都一样,所以最优解是需要经过多次重复执行源程序,得出最好的那个结果,并根据这些数据分析当前算法好坏。我不知道别人是怎么执行程序的,但是这样反复执行很耗神,所以我想请教的是怎么叫他自己执行,但是和我手动执行效果一样? 手动执行其实也不是不会重复,因为随机种子随时间变化,所以当我连续两次飞快地 按ctrl+F5执行,出来来的两次结果就会重复。
赵4老师 2014-05-04
  • 打赏
  • 举报
回复
请在程序初始化时调用一次srand(time(NULL));在其它地方就不要画蛇添足地调用了。
shuiyrn 2014-05-04
  • 打赏
  • 举报
回复
引用 10 楼 u012061345 的回复:
[quote=引用 9 楼 shuiyrn 的回复:] 我本来以为是随机数种子的问题,所以叫他休眠1秒钟,但是没加休眠时 的问题也是以上状况。也就是说Sleep并没有解决该问题。
我觉得也不算大量重复吧,只是在那几代中没有出现更优的值而已。 手动50次难道一次重复的都没出现过?跟自动50次的结果模式完全不一样? 你把srand这句话去掉。然后比较一下自动50次和手动50次的结果。如果不一样,就说明你的代码确实有个奇怪的问题。[/quote] 至于说去掉srand,我试了下。 手动每次结果完全一样 976.2280000000000700 976.2280000000000700 976.2280000000000700 976.2280000000000700 976.2280000000000700 976.2280000000000700 自动循环时,每次循环内数据不一样,各次循环间一样。 比如循环1次 989.2558000000001400 989.2558000000001400 989.2558000000001400 989.2558000000001400 ……都一样; 循环5次 989.2558000000001400 994.4118000000003100 995.6070000000005400 995.8067000000007700 996.0062000000009400 989.2558000000001400 994.4118000000003100 995.6070000000005400 995.8067000000007700 996.0062000000009400 ……每5次循环往复; 当自动循环50次,就杂乱无章地大量重复 989.2558000000001400 994.4118000000003100 995.6070000000005400 995.8067000000007700 996.0062000000009400 996.2051000000009300 996.6035000000008500 996.8030000000006800 996.8030000000007900 996.8030000000007900 997.0025000000007400 997.0025000000008500 997.2022000000009700 997.2022000000009700 997.2022000000013100 997.2022000000014300 997.4019000000013200 997.6016000000013300 997.6016000000014400 997.6016000000017800 997.6016000000018900 997.6016000000022400 997.6016000000022400 997.6016000000023500 998.0010000000021400 998.0010000000024800 998.0010000000024800 998.0010000000027000 998.0010000000028200 998.0010000000028200 998.0010000000030500 998.0010000000030500 998.0010000000030500 998.0010000000031600 998.0010000000032700 998.0010000000032700 998.0010000000032700 998.0010000000032700 998.0010000000037300 998.0010000000038400 998.0010000000040700 998.0010000000040700 998.0010000000040700 998.0010000000040700 998.0010000000040700 998.0010000000040700 998.0010000000045200 998.0010000000045200 998.0010000000045200 998.0010000000047500 好崩溃牙
加载更多回复(16)

65,208

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧