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

forked from: 遺伝的アルゴリズム??

bit演算でやってみますた
一応遺伝的アルゴリズム(GA)のつもり
* 赤字の答えにたどり着くために世代交代(交配)を繰り返します
* スクロールバーをつけてないので、テキストエリアをスクロールできないのですが
* マウスで選択してグアーっと下に選択していくとスクロール?して確認できます。
* 遺伝子のモデルは2進数なのでbit演算したほうが絶対良いのですが、やり方が分かりません・・・
/**
 * Copyright uwi ( http://wonderfl.net/user/uwi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6p0j
 */

// forked from fumix's 遺伝的アルゴリズム??
// bit演算でやってみますた
/*
 * 一応遺伝的アルゴリズム(GA)のつもり
 * 赤字の答えにたどり着くために世代交代(交配)を繰り返します
 * スクロールバーをつけてないので、テキストエリアをスクロールできないのですが
 * マウスで選択してグアーっと下に選択していくとスクロール?して確認できます。
 * 遺伝子のモデルは2進数なのでbit演算したほうが絶対良いのですが、やり方が分かりません・・・
*/
package {
	import flash.events.MouseEvent;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;

	[SWF(width = 465, height = 465, backgroundColor = 0xFFFFFF, frameRate = 60)]

	/**
	 * @author fumix
	 */
	public class GeneticAlogrithm extends Sprite {
		private var tx : TextField;
		private var answer : uint;
		private var genicArray : Array;
		private var generationCount : int;
		private var upButton : Sprite;
		private var downButton : Sprite;
        private var N : int = 10;
        private var M : int = 10;
		
		/*
		 * コンストラクタ
		 */
		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);
			
			//求める答え(N bit)
			answer = generateGene(N);
			addTextField(toBinaryString(answer), '#ff0000');
			addTextField('----------');
			//遺伝子を10個ためておく配列
			genicArray = new Array(M);
			for (var i : int = 0;i < M;i++) {
			    genicArray[i] = {gene : generateGene(N), score : 0};
			}
			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 {
			//遺伝子の評価
			var genicArray : Array = evaluateGene(answer, genicArray);
			//交配
			var newGene1 : uint = crossbreeding(genicArray[0].gene, genicArray[1].gene);
			var newGene2 : uint = crossbreeding(genicArray[0].gene, genicArray[1].gene);
			genicArray.pop();
			genicArray.pop();
			genicArray.push({gene : newGene1, score : 0});
			genicArray.push({gene : newGene2, score : 0});

			generationCount++;
			addTextField(generationCount + '世代目');
			for each(var v : Object in genicArray) {
				//評価点が最大の場合、ループ終わり
				if(v.score == N) {
					addTextField(toBinaryString(v.gene) + ' ' + v.score, '#0000ff');
					removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
				} else {
					addTextField(toBinaryString(v.gene) + ' ' + v.score);
				}
			}
			addTextField('----------');
		}
		
		private function toBinaryString(a : uint) : String
		{
		    var ret : String = "000000000000000000000000000000000000" + a.toString(2);
		    return ret.substring(ret.length - N);
		}

		/*
		 * 交配
		 */
		private function crossbreeding(gene1 : uint, gene2 : uint) : uint {
		    // もっとえろえろに交配する
		    var mask : uint = Math.random() * (1 << N);
		    var ret : uint = (gene1 & mask) | (gene2 & (~mask));
		    
			//突然変異
			if(Math.random() < 0.9){
    			var mutatePoint : int = Math.random() * N;
    			ret ^= 1 << mutatePoint;
           }
			return ret;
		}

		private function evaluateGene(ans : uint, arr : Array) : Array {
		    for(var i : int = 0;i < arr.length;i++){
		        arr[i].score = N - bitcount(arr[i].gene ^ ans);
			} 
			//評価点でソート
			arr.sortOn("score", Array.DESCENDING | Array.NUMERIC);
			return arr;
		}
		
		private function bitcount(a : uint) : int
		{
		    a = (a & 0x55555555) + (a >> 1 & 0x55555555);
		    a = (a & 0x33333333) + (a >> 2 & 0x33333333);
		    a = (a & 0x0f0f0f0f) + (a >> 4 & 0x0f0f0f0f);
		    a = (a & 0x00ff00ff) + (a >> 8 & 0x00ff00ff);
		    a = (a & 0x0000ffff) + (a >> 16 & 0x0000ffff);
		    return a;
		}
		
		private function generateGene(bit : int = 1) : uint {
		    return Math.random() * (1 << bit);
		}

		/*
		 * テキストフィールドに文字列を表示させる
		 */
		private function addTextField(txt : String,color : String = '#000000') : void {
			tx.htmlText += '<font color="' + color + '">' + txt + '</font>'; 
			//trace(txt);
		}
	}
}