In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

遺伝的アルゴリズム??

一応遺伝的アルゴリズム(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;
		}
	}