遺伝的アルゴリズム??
一応遺伝的アルゴリズム(GA)のつもり
* 赤字の答えにたどり着くために世代交代(交配)を繰り返します
* スクロールバーをつけてないので、テキストエリアをスクロールできないのですが
* マウスで選択してグアーっと下に選択していくとスクロール?して確認できます。
* 遺伝子のモデルは2進数なのでbit演算したほうが絶対良いのですが、やり方が分かりません・・・
/**
* Copyright fumix ( http://wonderfl.net/user/fumix )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/lFLo
*/
/*
* 一応遺伝的アルゴリズム(GA)のつもり
* 赤字の答えにたどり着くために世代交代(交配)を繰り返します
* スクロールバーをつけてないので、テキストエリアをスクロールできないのですが
* マウスで選択してグアーっと下に選択していくとスクロール?して確認できます。
* 遺伝子のモデルは2進数なのでbit演算したほうが絶対良いのですが、やり方が分かりません・・・
*/
package {
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.display.MovieClip;
[SWF(width = 465, height = 465, backgroundColor = 0xFFFFFF, frameRate = 60)]
/**
* @author fumix
*/
public class GeneticAlogrithm extends MovieClip {
private var tx : TextField;
private var answer : String;
private var genicArray : Array;
private var generationCount : Number;
private var upButton : Sprite;
private var downButton : Sprite;
/*
* コンストラクタ
*/
public function GeneticAlogrithm() {
tx = new TextField();
tx.multiline = true;
tx.width = 450;
tx.height = 450;
addChild(tx);
generationCount = 0;
//スクロールボタン
upButton = new Sprite();
upButton.graphics.beginFill(0x333333);
upButton.graphics.drawRect(0, 0, 15, 15);
upButton.graphics.endFill();
upButton.buttonMode = true;
upButton.x = 450;
upButton.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
addChild(upButton);
downButton = new Sprite();
downButton.graphics.beginFill(0x333333);
downButton.graphics.drawRect(0, 0, 15, 15);
downButton.graphics.endFill();
downButton.buttonMode = true;
downButton.x = 450;
downButton.y = 450;
downButton.addEventListener(MouseEvent.MOUSE_UP, onMouseDownHandler);
addChild(downButton);
//求める答え(8bit)
answer = generateGene(8);
addTextField(answer, '#ff0000');
addTextField('----------');
//遺伝子を10個ためておく配列
genicArray = new Array();
for (var i : int = 0;i < 10;i++) {
var gene : Gene = new Gene(generateGene(8));
genicArray.push(gene);
}
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
private function onMouseDownHandler(event : MouseEvent) : void {
tx.scrollV++;
}
private function onMouseUpHandler(event : MouseEvent) : void {
tx.scrollV--;
}
private function onEnterFrameHandler(event : Event) : void {
//遺伝子の評価
genicArray = evaluateGene(answer, genicArray);
//交配
var newGene1 : Gene = crossbreeding(genicArray[0], genicArray[1]);
var newGene2 : Gene = crossbreeding(genicArray[0], genicArray[1]);
genicArray.pop();
genicArray.pop();
genicArray.push(newGene1);
genicArray.push(newGene2);
generationCount++;
addTextField(generationCount + '世代目');
for (var i: String in genicArray) {
//評価点が最大の場合、ループ終わり
if(genicArray[i].score == genicArray[i].gene.length) {
addTextField(genicArray[i].gene + ' ' + genicArray[i].score, '#0000ff');
removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
} else {
addTextField(genicArray[i].gene + ' ' + genicArray[i].score);
}
}
addTextField('----------');
}
/*
* 交配
*/
private function crossbreeding(gene1 : Gene, gene2 : Gene) : Gene {
var gene1Str : String = gene1.gene;
var gene2Str : String = gene2.gene;
var bitLenght : int = gene1Str.length;
var returnGene : Gene = new Gene('00000000');
var crossPoint : Number = Math.floor(Math.random() * bitLenght + 1);
returnGene.gene = gene1Str.substr(0, crossPoint) + gene2Str.substr(crossPoint, bitLenght - crossPoint);
//突然変異
var mutateCrossPoint : Number = Math.floor(Math.random() * bitLenght);
var p : String = returnGene.gene.substr(mutateCrossPoint, 1);
if(p == '0') {
returnGene.gene = returnGene.gene.substr(0, mutateCrossPoint) + '1' + returnGene.gene.substr(mutateCrossPoint + 1, bitLenght - mutateCrossPoint - 1);
} else {
returnGene.gene = returnGene.gene.substr(0, mutateCrossPoint) + '0' + returnGene.gene.substr(mutateCrossPoint + 1, bitLenght - mutateCrossPoint - 1);
}
return returnGene;
}
private function evaluateGene(ans : String, arr : Array) : Array {
var retunArray : Array = new Array();
for (var i : String in arr) {
var gen : Gene = arr[i];
var score : Number = 0;
for (var j : int = 0;j < gen.gene.length;j++) {
if(ans.substr(j, 1) == gen.gene.substr(j, 1)) score++;
}
gen.score = score;
retunArray.push(gen);
}
//評価点でソート
retunArray.sort(sortOnScore);
return retunArray;
}
function sortOnScore(a : Gene, b : Gene) : Number {
var aScore : Number = a.score;
var bScore : Number = b.score;
if(aScore > bScore) {
return -1;
} else if(aScore < bScore) {
return 1;
} else {
return 0;
}
}
/*
* ランダムな2進数の文字列を返す
* 引数のbit数に満たない場合は左桁に0を足す
*/
private function generateGene(bit : int = 1) : String {
var rnd : String = Math.floor(Math.random() * Math.pow(2, bit)).toString(2);
var rtn : String = '';
if(rnd.length < bit) {
for (var i : int = 0;i < bit - rnd.length;i++) {
rtn += '0';
}
rtn += rnd;
return rtn;
} else {
return rnd;
}
}
/*
* テキストフィールドに文字列を表示させる
*/
private function addTextField(txt : String,color : String = '#000000') : void {
tx.htmlText += '<font color="' + color + '">' + txt + '</font>';
//trace(txt);
}
}
}
class Gene {
private var _gene : String;
private var _score : Number;
public function Gene(gene:String,score:Number = 0) {
_gene = gene;
_score = score;
}
public function get gene() : String {
return _gene;
}
public function set gene(gene : String) : void {
_gene = gene;
}
public function get score() : Number {
return _score;
}
public function set score(score : Number) : void {
_score = score;
}
}