• 締切済み

遺伝子アルゴリズムの2点交叉について教えてください

下記のプログラムを改良して2点交叉にしたいのですが、遺伝子アルゴリズムもC++も初心者なので、よくわかりません。どなたかお知恵を貸してください。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include "come.h" int kousa() { unsigned int max=100; unsigned int max2=17; int a,b,c,d; int i,v,w,y,n,o,k,p,f; char kari[1][17]; w=0;//カウンタ n=0; srand((unsigned)time(NULL)); for(v=0;v<100;v++) { for(i=0;i<17;i++) { get[v][i]=next[v][i]; //next[175][17]からget[100][17]へコピーする(親) } } for(o=0;o<100;o++) { for(k=0;k<17;k++) { take[o][k]=next[v][k]; //next[175][17]からtake[100][17]へコピーする(子) } } for(d=0;d<50;d++) { a=(rand()%max); //1つ目の交叉する列を見つける b=(rand()%max); //2つ目の交叉する列を見つける c=(rand()%max2); //交叉ポイント見つける for(;c<17;c++) //1点交叉 { kari[n][c]=get[a][c]; get[a][c]=get[b][c]; get[b][c]=get[n][c]; } for(y=0;y<17;y++) { take[w][y]=get[a][y]; //get[100][17]からtake[50][17]へコピー take[w+1][y]=get[b][y]; } w=w+2; } for(p=0;p<100;p++) { for(f=0;f<17;f++) { next[nextpop][f]=take[p][f]; } nextpop++; } return 0; }

みんなの回答

  • fonera
  • ベストアンサー率52% (38/72)
回答No.2

恐れ入ります。No.1で回答したものです。 >回答のプログラムを直接入力すると、kari[i] = get[father][i];の所で「左のオペランドが、左辺値になっていません」、というエラーが起きるので、変数iの部分がどう変えればいいか教えてもらえませんか? 参考にしていただいて、自身で作り直していただくのが一番なのですが、 追加で回答しておきます。 できるだけ元々のソースを残したまま、追加・修正しました。 (追加した部分は、ソース内にコメントを入れました。元ソースと比較して、何をしているか考えてみて下さい) なお、再度繰り返しますが掲載されたソースが「部分抜粋」で、「ソース全て」ではありません。全て載せていただけなければ、これ以上は判断が付きかねます。 (どんなプログラムの一部なのか推測するしかないので、弄りようがないです) 動かなかった場合は、全てのソースをおみせ願えないでしょうか。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include "come.h" int kousa() { unsigned int max=100; unsigned int max2=17; int a,b,c,d; int father, mother, point_1, point_2, temporary;/* 2点交叉で使う変数 */ int i,v,w,y,n,o,k,p,f; char kari[1][17]; w=0;//カウンタ n=0; father = mother = point_1 = point_2 = temporary = 0; /* 初期化 */ srand((unsigned)time(NULL)); for(v=0;v<100;v++) { for(i=0;i<17;i++) { get[v][i]=next[v][i]; //next[175][17]からget[100][17]へコピーする(親) } } for(o=0;o<100;o++) { for(k=0;k<17;k++) { take[o][k]=next[v][k]; //next[175][17]からtake[100][17]へコピーする(子) } } for(d=0;d<50;d++) { father = (rand() % max); /* 1つめの交叉する列を見つける */ mother = (rand() % max); /* 2つめの交叉する列を見つける */ point_1 = (rand() % max2); /* 交叉ポイントを見つける */ point_2 = (rand() % max2); /* 交叉ポイントを見つける */ /*↓から2点交叉*/ for(i = 0; i < 17; i++) { if (i < point_1) { temporary = get[father][i]; get[father][i] = get[mother][i]; get[mother][i] = temporary; } if (i < point_2) { temporary = get[father][i]; get[father][i] = get[mother][i]; get[mother][i] = temporary; } } /* ↑まで2点交叉 */ for(y=0;y<17;y++) { take[w][y]=get[a][y]; //get[100][17]からtake[50][17]へコピー take[w+1][y]=get[b][y]; } w=w+2; } for(p=0;p<100;p++) { for(f=0;f<17;f++) { next[nextpop][f]=take[p][f]; } nextpop++; } return 0; }

  • fonera
  • ベストアンサー率52% (38/72)
回答No.1

恐れ入ります。 ざっと読みましたが、質問に掲載されたプログラムが部分抜粋のようですので、不明点が多いです。推測して回答します。 遺伝的アルゴリズムの基礎はご存じですか? 質問に掲載されたプログラムは ・100の個体で、遺伝子数は17。(遺伝子の中身は不明) ・100の個体を、ランダムに50ペア選び交叉させる。 ・交叉後、親の個体は保持されない。子が親に取って代わる。 ・親集団は交叉中に変化する。親集団は全て破棄され、子が生まれる度に次集団にコピーされる。 # 1点交叉の get[b][c]=get[n][c];は、get[b][c]=kari[n][c];の間違いかと思いますがどうでしょうか? 通常遺伝的アルゴリズムと呼ばれているモノからすると、かなり変則的なアルゴリズムになっています。一度参考書などで確認された方がよろしいかと思います。 上記のプログラムのまま、2点交叉にしたいだけでしたら簡単です。 1点交叉は 親A 00000 親B 11111 の時に、 子C 11000 子D 00111 のようになります。 2点交叉は 親A 00000 親B 11111 の時に、 子C 11001 子D 00110 のように、交換場所が2カ所になるだけです。 つまり father = (rand() % max); mother = (rand() % max); point_1 = (rand() % max2); point_2 = (rand() % max2); for(i = 0; i < 17; i++) { if (i < point_1) { kari[i] = get[father][i]; get[father][i] = get[mother][i]; get[mother][i] = kari[i]; } if (i < point_2) { kari[i] = get[father][i]; get[father][i] = get[mother][i]; get[mother][i] = kari[i]; } } これで、point_1かつpoint_2の場合には2回交換して元に戻ることで、2点交叉が実現できます。(もっとエレガントな方法もありますが、理解しづらくなってしまいますので。ご自身でお考え下さい) 変数名の名前の付け方や、冗長部分のまとめ方などは、参考書を参考にしながらご自身でなされた方がよいかと思います。

iris0625
質問者

お礼

お礼が遅くなって申し訳ありません。とても参考になりました。

iris0625
質問者

補足

回答のプログラムを直接入力すると、kari[i] = get[father][i];の所で「左のオペランドが、左辺値になっていません」、というエラーが起きるので、変数iの部分がどう変えればいいか教えてもらえませんか?

関連するQ&A