<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Oddwit &#187; Things I Made</title>
	<atom:link href="http://oddwit.com/blog/category/things-i-made/feed" rel="self" type="application/rss+xml" />
	<link>http://oddwit.com/blog</link>
	<description>Web, Dev, Etc</description>
	<lastBuildDate>Thu, 15 Dec 2011 02:02:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Wikipedia専用の短縮URLサービスを作った</title>
		<link>http://oddwit.com/blog/2011/wikipediashort</link>
		<comments>http://oddwit.com/blog/2011/wikipediashort#comments</comments>
		<pubDate>Thu, 15 Dec 2011 01:32:47 +0000</pubDate>
		<dc:creator>merikonjatta</dc:creator>
				<category><![CDATA[Things I Made]]></category>
		<category><![CDATA[wikipedia]]></category>

		<guid isPermaLink="false">http://oddwit.com/blog/?p=741</guid>
		<description><![CDATA[作りました。 http://wikipediashort.org/ WikipediaのURLの後ろにshortを入れるだけで短縮URLになります。 http://ja.wikipedia.org/wiki/草間彌生 ↓ [...]]]></description>
			<content:encoded><![CDATA[<p>作りました。<br />
<a href="http://wikipediashort.org/">http://wikipediashort.org/</a><br />
WikipediaのURLの後ろにshortを入れるだけで短縮URLになります。</p>
<pre class="brush:plain">http://ja.wikipedia.org/wiki/草間彌生
↓

http://ja.wikipediashort.org/wiki/草間彌生

に書き換えてアクセス
↓

http://wkpdia.org/tmiuzn

短縮された！</pre>
<p>特に日本語が含まれるURLはSkypeなどに貼り付けるとエンコードされて大変見た目が悪くなるので、そういう時には便利かと。ツイートボタンもつけてあるので、Wikipediaの記事をTwitterに投げたい時にもどうぞ。</p>
<p>ちなみに中身はPHPでできています。めっちゃ久しぶりにPHP書いた。これくらいの小物ならPHPのほうがどこでも動くし楽。でもよく考えたらSinatraとかでもよかったかもしれない。URLを短縮するところはbit.ly任せ。</p>
<p><strong>追記</strong><br />
生成される短縮URLは全部<code>wkpdia.org/******</code>だしwikipedia.org以外のURLは短縮できない仕様になってるので、短縮されていても一発でWikipediaだと分かるっちゅーメリットもあります。</p>

]]></content:encoded>
			<wfw:commentRss>http://oddwit.com/blog/2011/wikipediashort/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redmine用プラグイン「autohier」を公開しました</title>
		<link>http://oddwit.com/blog/2011/redmine-autohier</link>
		<comments>http://oddwit.com/blog/2011/redmine-autohier#comments</comments>
		<pubDate>Thu, 17 Mar 2011 19:23:08 +0000</pubDate>
		<dc:creator>merikonjatta</dc:creator>
				<category><![CDATA[Things I Made]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[redmine]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://oddwit.com/blog/?p=720</guid>
		<description><![CDATA[Redmine用プラグインredmine_autohierを公開しました。 ページタイトルを使って自動的にWikiページの階層構造を管理してくれるプラグインです。例えばJuice>Orangeというページを作ると、Jui [...]]]></description>
			<content:encoded><![CDATA[<p>Redmine用プラグイン<a href="http://www.redmine.org/plugins/autohier">redmine_autohier</a>を公開しました。</p>
<p>ページタイトルを使って自動的にWikiページの階層構造を管理してくれるプラグインです。例えば<strong>Juice>Orange</strong>というページを作ると、<strong>Juice</strong>が親ページに設定されます。ただそれだけの事ですがすごく便利になります。</p>
<ul>
<li>長いドロップダウンから親ページを選ばなくていい</li>
<li>ページの親パスがURLに現れる</li>
<li>今のURLに<strong>>AnotherPage</strong>とするだけで子ページを作れる</li>
<li>Renameに行けば親ページを変えられることが分かりやすくなる</li>
</ul>
<p>redmine 1.1およびtrunkの先っぽで動作確認しています。</p>
<p>インストールは</p>
<pre class="brush:shell">
$ script/plugin install git://github.com/merikonjatta/redmine_autohier.git
</pre>
<p>もう少し詳しい動作などについては<a href="https://github.com/merikonjatta/redmine_autohier">githubにて確認</a>してください。ライセンスはMIT Licenseです。</p>

]]></content:encoded>
			<wfw:commentRss>http://oddwit.com/blog/2011/redmine-autohier/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascriptで手っ取り早く関数をモックする</title>
		<link>http://oddwit.com/blog/2010/quick-j-mocking</link>
		<comments>http://oddwit.com/blog/2010/quick-j-mocking#comments</comments>
		<pubDate>Wed, 02 Jun 2010 12:11:55 +0000</pubDate>
		<dc:creator>merikonjatta</dc:creator>
				<category><![CDATA[Things I Made]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://oddwit.com/blog/?p=393</guid>
		<description><![CDATA[JsMockitoとかJSMockとか色々あるようですが、変にDSLのようなものを覚えるのも面倒だったのでスパッとモックできるようにしてみました。 機能は任意の関数を、別の関数で一時的に置き換えるだけです。Ajaxを使う [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jsmockito.org/">JsMockito</a>とか<a href="http://jsmock.sourceforge.net/examples/">JSMock</a>とか色々あるようですが、変にDSLのようなものを覚えるのも面倒だったのでスパッとモックできるようにしてみました。</p>
<p>機能は<strong>任意の関数を、別の関数で一時的に置き換える</strong>だけです。Ajaxを使うような関数のユニットテストなどがやりやすくなります。</p>
<pre class="brush:js">
// Mock.makeで関数を置き換え。
// 最初の引数は関数名で、次は関数オブジェクト。
Mock.make(&quot;some_func&quot;, new_func);

// some_funcを呼ぶとnew_funcが実行される
some_func();

// Mock.revertで元に戻る
Mock.revert(&quot;some_func&quot;);

// Mock.revert_allで全てのモックが元に戻る
Mock.revert_all();
</pre>
<h2>使い方の例（１）</h2>
<pre class="brush:js">
// prompt()をモックしてみる
Mock.make(&quot;prompt&quot;, function(title, text){
  return &quot;あばびぶべー！&quot;;
});

var name = prompt(&quot;What's your name?&quot;)
console.log(name); //=&gt; &quot;あばびぶべー！&quot;

Mock.revert(&quot;prompt&quot;); // これでもとに戻った
</pre>
<h2>使い方の例（２）</h2>
<pre class="brush:js">
test(&quot;#save saves the text&quot;, function(){
    var ajax_called = false;

    // $.ajaxをモックする。
    Mock.make(&quot;$.ajax&quot;, function(opts){
        ajax_called = true;
        // $.ajaxが呼ばれたときにオプションが適切かどうかをassertする
        equals(opts.url,        &quot;/jsapi/pages/set_title&quot;);
        equals(opts.type,       &quot;post&quot;);
        equals(opts.data.id,    page_id);
        equals(opts.data.title, new_title);
        // successコールバックを呼ぶ。
        opts.success({success:true}, null, null);
    });

    // MyLibrary.saveは$.ajaxを呼ぶはず。
    MyLibrary.save(25, &quot;This is the new text.&quot;);
    ok(ajax_called, &quot;Ajax was called.&quot;);
});
</pre>
<h2>本体</h2>
<pre class="brush:js">
var Mock = {
  store: {},

  make: function(funcname, newfunc){
    if (this.store[funcname]==undefined){
      this.store[funcname] = (function(){
        return eval(funcname);
      }).apply(arguments.caller);
    }
    (function(){
      eval(funcname+&quot;=newfunc;&quot;);
    }).apply(arguments.caller);
  },

  revert: function(funcname){
    if(this.store[funcname]!=undefined){
      var self = this;
      (function(){
        eval(funcname+&quot;=self.store[funcname];&quot;);
      }).apply(arguments.caller);
      this.store[funcname] = undefined;
    }
  },

  revert_all: function(){
    for(var funcname in this.store){
      this.revert(funcname);
    }
  },
};
</pre>

]]></content:encoded>
			<wfw:commentRss>http://oddwit.com/blog/2010/quick-j-mocking/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Readerで背面にタブを開くChrome拡張の開発をやめました</title>
		<link>http://oddwit.com/blog/2009/chrome-extension-greader-open-in-background-quit</link>
		<comments>http://oddwit.com/blog/2009/chrome-extension-greader-open-in-background-quit#comments</comments>
		<pubDate>Thu, 24 Dec 2009 08:29:53 +0000</pubDate>
		<dc:creator>merikonjatta</dc:creator>
				<category><![CDATA[Things I Made]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://oddwit.com/blog/?p=343</guid>
		<description><![CDATA[Google Readerの「v」で背面にタブを開くChrome拡張機能の開発をやめました。 理由は タブが二枚開くなどのバグがあったが原因究明に時間を費やしすぎる Chromeのバージョンが同じなのにこのPCと隣のPC [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://oddwit.com/blog/2009/chrome-extension-greader-open-in-background">Google Readerの「v」で背面にタブを開くChrome拡張機能</a>の開発をやめました。</p>
<p>理由は</p>
<ul>
<li>タブが二枚開くなどのバグがあったが原因究明に時間を費やしすぎる</li>
<li>Chromeのバージョンが同じなのにこのPCと隣のPCで動作が違ったりして萎えた</li>
<li>よく考えたらGoogle ReaderだけFirefoxで見ればいい。Firefox全然嫌いじゃなかった</li>
</ul>
<p>ということで、申し訳ありませんがこれ以上新しいバージョンは出ません。</p>
<p>CRXをダウンロードしてunzipするのが面倒な方のためにPage actionのソースを貼っておきますので、どなたか気が向いたらご利用ください。</p>
<pre class="brush:js">
/*
 * taken from http://userscripts.org/scripts/show/24955
 */
function simulateClick(node) {
  var event = node.ownerDocument.createEvent("MouseEvents");
  event.initMouseEvent("click",
                      true, true, window, 1, 0, 0, 0, 0,
                      false, false, false, false, 0, null);
  node.dispatchEvent(event);
}

/*
 * original
 * thx to http://sites.google.com/site/ggchromium/ for fixes
 */
document.addEventListener("keypress", function(e){

  var name = e.target.tagName;
  // Do nothing if the target of this event is an edit box
  if (name == "TEXTAREA" || name == "INPUT"){ return; }

  var keycode = (e.keyCode) ? e.keyCode : e.which;
  var k = String.fromCharCode(keycode);
  if (k=="v" &#038;&#038; !e.altKey &#038;&#038; !e.ctrlKey &#038;&#038; !e.metaKey &#038;&#038; !e.shiftKey){ // just 'v' and no modifiers
    // Get the current entry node
    var current_entry = document.getElementById('current-entry');

    // Get the url. In Expanded view or List view?
    var card_content = current_entry.getElementsByClassName('card-content')[0]
    if (card_content){
      var url = current_entry.getElementsByClassName('entry-title-link')[0].href;
    } else {
      var url = current_entry.getElementsByClassName('entry-original')[0].href;
    }

    if(!url){ return true; }

    // open the link in background
    chrome.extension.sendRequest({"func":"open_in_background", "url":url});

    // mark the entry as read
    simulateClick(current_entry.childNodes[0]);
    simulateClick(current_entry.childNodes[0]);

    // make sure the event doesn't propate
    e.stopPropagation();
    e.preventDefault();

    return false;
  }
}, true);
</pre>

]]></content:encoded>
			<wfw:commentRss>http://oddwit.com/blog/2009/chrome-extension-greader-open-in-background-quit/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Readerの「v」で背面にタブを開くChrome拡張機能</title>
		<link>http://oddwit.com/blog/2009/chrome-extension-greader-open-in-background</link>
		<comments>http://oddwit.com/blog/2009/chrome-extension-greader-open-in-background#comments</comments>
		<pubDate>Mon, 23 Nov 2009 06:50:07 +0000</pubDate>
		<dc:creator>merikonjatta</dc:creator>
				<category><![CDATA[Things I Made]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[greasemonkey]]></category>

		<guid isPermaLink="false">http://www.oddwit.com/blog/?p=304</guid>
		<description><![CDATA[Google Chromeの拡張機能です。Google Readerでvを押したときに元記事が背面のタブで開くようになります。これを入れておけば、タイトルを見ながらいくつも連続で開いておいて、あとでそれぞれを見ていくとい [...]]]></description>
			<content:encoded><![CDATA[<p>Google Chromeの拡張機能です。Google Readerでvを押したときに元記事が背面のタブで開くようになります。これを入れておけば、タイトルを見ながらいくつも連続で開いておいて、あとでそれぞれを見ていくという読み方ができます。</p>
<p>ダウンロード：<br />
<a href="http://www.chromeextensions.org/appearance-functioning/google-reader-open-in-background-tab/">Google Reader: Open in background tab «  Google Chrome Extensions</a></p>
<p>Firefox用には同じことをする<a href="http://sunnywu.net/2007/08/02/google-reader-tweak-open-links-in-background/">Greasemonkeyスクリプト</a>があったんですが、Chromeでは動作しなかったので作りました。</p>
<p>「ここはこうしとけよ！」みたいなのがあったらコメントでお願いします。</p>

]]></content:encoded>
			<wfw:commentRss>http://oddwit.com/blog/2009/chrome-extension-greader-open-in-background/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Flashで物理法則の習作</title>
		<link>http://oddwit.com/blog/2007/flash-physics-study</link>
		<comments>http://oddwit.com/blog/2007/flash-physics-study#comments</comments>
		<pubDate>Sun, 03 Jun 2007 19:09:20 +0000</pubDate>
		<dc:creator>merikonjatta</dc:creator>
				<category><![CDATA[Things I Made]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[physics]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.oddwit.com/blog/2007/flash-physics-study</guid>
		<description><![CDATA[http://www.oddwit.com/lab/flashminis/20070603solids/ ボールが飛び跳ねるだけの習作。本当はこの二つをつなぐ剛体が作りたかったのだが、それは次回に持ち越し。 最初はボール [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.oddwit.com/lab/flashminis/20070603solids/">http://www.oddwit.com/lab/flashminis/20070603solids/</a></p>
<p>ボールが飛び跳ねるだけの習作。本当はこの二つをつなぐ剛体が作りたかったのだが、それは次回に持ち越し。</p>
<p>最初はボールをドラッグしている間は座標を直接いじってマウスに吸着させていたが、このやり方はボールを投げたくなったときにダメだった。重力と同じく、マウスがボールを引くのも一つの力とみなす必要があった。</p>
<p>そこで、基本的には常に重力を受け続け、ドラッグしている間はマウスからの引力も受けることにした。簡単のためX軸だけで説明すると、</p>
<pre class="brush:as3">
var dx = _root._xmouse - posx;	// マウスから自分（ボール）までの距離
var fxm = dx * fdamp;		// マウスの引力は距離に比例。fdampはその比例定数
</pre>
<p>比例定数fdampのfはforce、dampはdampen（鈍らせる）だ。</p>
<p>さて、この力を元に加速度を計算し、加速度を速度に足し合わせて新しい速度を得るが、このそれぞれの段階でも動きを調整する定数をかける。</p>
<pre class="brush:as3">
var accelxm = (fxm/mass)*adamp;	// 加速度＝(力/質量)×加速度比例定数
velocx = (velocx+accelx)*vdamp;	// 速度＝(以前の速度＋加速度）×速度比例定数
</pre>
<p>あとは座標に足し込めば移動したことになる。</p>
<p>ここで三つの比例定数fdamp, adamp そしてvdamp が登場したが、この設定の仕方によって力に対する物体の挙動が変わってくる。今回の習作では二つのボールで速度比例定数の設定が異なっている。</p>
<p>左のボールは力：7、加速度：0.3、速度：0.9。<br />
右のボールは力：7、加速度：0.3、速度：0.7。</p>
<p>この場合、左のボールのほうがボヨボヨと活発にはねまわる。</p>
<p><strong>力比例定数</strong>が大きいと、単純に力が強くなる。これは今は特に問題ない。</p>
<p><strong>加速度比例定数</strong>が大きいと、どうやら早送りしているように見えるようだ。逆に小さければスローモーションに見える。</p>
<p><strong>速度比例定数</strong>が大きいと、弱い力でもよく動く。小さいければ動きが鈍る。</p>
<p>考慮する力がマウスの引力だけのとき、加速度と速度の定数はそれぞれ0.3、0.7、くらいがいいのだが、重力に対しては1、1がいいことが経験的にわかっている。そこで二種類の力に対して二セットの係数を使い分ける必要がある。</p>
<p>力と加速度は互いに独立した値だから、それぞれの定数を問題なくかけることができる。しかし速度の場合、全ての力を受けた結果としての一つの値しかない。つまり、<strong>何か一つの定数</strong>をかけなければいけない。</p>
<p>ではその「一つの定数」はどう求めるか。</p>
<p>特に根拠は無かったのだが、二種類の定数を混ぜる方法として加重平均のような正規化のような操作をしてみたところ、びっくりするくらい上手く行った。</p>
<p>重量と引っ張る力がたとえば1:4で、重力的には1がよくて、引っ張り的には0.7がいい場合、最終的な比例定数は<br />
(1/5 * 1) + (4/5 * 0.7)<br />
というわけ。</p>
<p>たぶんこのやり方には名前があるのだろうが、無知無教養な僕には分からない。</p>
<p>このやり方なら、力の源がいくつあっても、それぞれに対する挙動を独立した比例定数のセットとして定義できる。ということは色々なところから力を受ける剛体や紐のようなものもシミュレートできる…はず。それはまた今度。</p>

]]></content:encoded>
			<wfw:commentRss>http://oddwit.com/blog/2007/flash-physics-study/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flashで遺伝的アルゴリズムを実装してみた</title>
		<link>http://oddwit.com/blog/2007/flash-ga-salesman</link>
		<comments>http://oddwit.com/blog/2007/flash-ga-salesman#comments</comments>
		<pubDate>Sun, 20 May 2007 18:39:29 +0000</pubDate>
		<dc:creator>merikonjatta</dc:creator>
				<category><![CDATA[Things I Made]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[ai]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.oddwit.com/blog/2007/flash-ga-salesman</guid>
		<description><![CDATA[あらすじ： Flashで、遺伝的アルゴリズム（GA)で巡回セールスマン問題を解くアプリを実装してみた。GAではパラメータのチューニングがかなり重要な要素だということが理解できた。 実行はこちら。ソースもあるよ 巡回セール [...]]]></description>
			<content:encoded><![CDATA[<p>あらすじ：<br />
Flashで、遺伝的アルゴリズム（GA)で巡回セールスマン問題を解くアプリを実装してみた。GAではパラメータのチューニングがかなり重要な要素だということが理解できた。</p>
<p><a href="http://www.oddwit.com/lab/flashga/GA.html"><img src="http://farm1.static.flickr.com/191/506092127_268323a4cb_m.jpg" alt="FlashでGAのスクリーンショット" /></a><br />
<a href="http://www.oddwit.com/lab/flashga/GA.html">実行はこちら。ソースもあるよ</a></p>
<h2>巡回セールスマン問題</h2>
<p>今回扱ったのは、いくつかの都市を全て一回ずつ巡回するとき、最短となるルートを発見しようという、いわゆる「巡回セールスマン問題」。</p>
<p>ごり押しで解こうとなると、12の都市で12!（じゅうにバン！と読む）≒4億7千万通りのルートを試さなければならない。できるだけ少ない試行でそれなりに短いルートを得るために、今回は遺伝的アルゴリズム（Genetic Algorithm, GA）を使う。この実装では、12箇所の場合、調べる回数が数万回にまで減らせることが分かった。</p>
<h2>遺伝的アルゴリズム</h2>
<p>GAは、生物の進化にヒントを得たおもしろいアルゴリズムだ。定義や一般的なやり方については<a href="http://ja.wikipedia.org/wiki/%E9%81%BA%E4%BC%9D%E7%9A%84%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0">Wikipedia</a>あたりを見てもらうとして、ごく簡単に説明すると、生物の進化を模倣したアルゴリズムだ。問題に対するさまざまな解を生き物に見立て、解どうしで交配させて子どもを作ったり、環境に適さないものを淘汰したりすることで、確率的に最適解を見つける。</p>
<h2>構成</h2>
<p>主なクラスは5つ。</p>
<ul>
<li>Agent &#8211; 一人のセールスマンをあらわすエージェント。DNAを保持</li>
<li>Population &#8211; セールスマンの集まり。世代を経るなどの動作をする</li>
<li>World &#8211; 都市がばらまかれたマップ。エージェントのDNAを評価する</li>
<li>Node &#8211; 都市。</li>
<li>GA &#8211; アルゴリズムを実行する。</li>
</ul>
<p>まずはPopulationオブジェクトとWorldオブジェクトを作成・初期化し、それをGAオブジェクトに渡して、myGA.run() で実行するという流れだ。</p>
<h2>DNAの表現</h2>
<p>エージェントのDNAは、単純に都市を廻る順番を配列にしたもので表した。たとえば<br />
<code>[0, 2, 9, 12, 10, 4, 11, 6, 8, 1, 3, 7]</code><br />
のような感じだ。</p>
<h2>自然選択の方法</h2>
<p>最適解に近づくため、各世代で一部のエージェントたちが死ぬ必要がある。今回は移動距離の長さでセールスマンを1～nまでランク付けし、そのうちの半分が淘汰され、半分が残る仕組みにした。</p>
<p>他にも選択の手法がいくつかある事をさっきWikipediaで調べて知ったのだが、この方法はどうも「<a href="http://ja.wikipedia.org/wiki/%E9%81%BA%E4%BC%9D%E7%9A%84%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0#.E3.81.9D.E3.81.AE.E4.BB.96">エリート選択</a>」にあたるらしい。名前は知らなかったが「ルーレット選択」というのもあり、これに似たことをしようかなとも思ったが、あまり結果に影響しなさそうだったので手を抜いた。実際、恐らく他のパラメータと比べると影響力は弱いと思う。</p>
<h2>交配の方法</h2>
<p>上の自然選択で死んだ分を、新しい子供で埋める。ここで親の選び方は、まさしくルーレット選択によるものだった。全てのセールスマンの成績を合計し、そのうち自分の成績が占める割合が、get laidできる確率となる。つまりできる男ほどモテるということだ。ただし問題は、男にモテるということだ。アッー！まぁ話がややこしくなるので父親･母親と呼ぶことにする。</p>
<p>さてどのように子供を生むかというのが考えどころだが、結局次のようにした。DNAの長さを12だとすると、そこから2つの連続した値を3つ取り出し、空の子供DNAに同じ位置で引き継がせる。たとえば</p>
<p>父：[<strong>0, 2</strong>, 9, <strong>5, 10</strong>, 4, 11, 6, <strong>8, 1</strong>, 3, 7]<br />
↓<br />
子：[<strong>0, 2</strong>, -, <strong>5, 10</strong>, -, -, -, <strong>8, 1</strong>, -, -]</p>
<p>のような具合だ。</p>
<p>次に、まだ埋まっていない場所へ、母親のDNAの同じ位置から値を引き継ぐ。ただし各都市を一回ずつ巡回する必要があるので、既にある値と重複してしまう場合はスキップする。</p>
<p>母：[1, 9, 0, 3, 2, 10, <strong>7</strong>, <strong>6</strong>, 3, 11, 8, <strong>4</strong>]<br />
↓<br />
子：[0, 2, -, 5, 10, -, <strong>7</strong>, <strong>6</strong>, 8, 1, -, <strong>4</strong>]</p>
<p>最後に、まだ埋まっていない場所をランダムな値で埋めれば子供のDＮＡが完成する。</p>
<p>子：[0, 2, <strong>9</strong>, 5, 10, <strong>3</strong>, 7, 6, 8, 1, <strong>11</strong>, 4]</p>
<p>今回は重複してはいけないという制約があるため少し特殊だが、方法としては<a href="http://ja.wikipedia.org/wiki/%E9%81%BA%E4%BC%9D%E7%9A%84%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0#.E4.B8.80.E6.A7.98.E4.BA.A4.E5.8F.89">一様交差</a>に似ていると思う。</p>
<p>最初は、父親のDNAから5つの値の連続を1つ取り出して同じ位置で子に渡していた。しかしこれだと世代間に多様性がなくなり、ほとんどを変異に頼ることになってしまう。そこで、もう少しバラエティに富んだ子が生まれることを期待しつつも、親の流れをそれなりに継いで欲しいとの願いから、2の連続x3を取る方法を選んだ。</p>
<p>他の可能性としては3の連続x2などもうまく行きそうな気がするし、同じ位置じゃなくずらして引き継がせるのもいいだろう。</p>
<h2>突然変異</h2>
<p>さて子を産んで再び人口が上限まで埋まったら、それぞれのエージェントを突然変異させる。DNAのうち二つの値を選んでそれを入れ替えるという作業を何回か、一定の確率で行う。</p>
<p>ただし、一番成績の良かったエージェントは変異しないように守ることにした。これは変異による状況の悪化を防ぐという意味で、エリート選択と少し似ている。</p>
<h2>いろいろなパラメータ</h2>
<p>実行時のパラメータがいろいろあって、いじり具合によってはすぐに良い結果が出たり一向に距離が縮まらなかったりするのが面白かった。</p>
<ul>
<li>巡回先の都市数</li>
<li>人口の上限</li>
<li>エージェントが変異する確率（今回は1）</li>
<li>変異したときにいくつのビットを入れ替えるか（今回は1）</li>
<li>世代ごとに淘汰される割合（今回は50%）</li>
<li>変異しないよう守られるエリートの数（今回は1）</li>
</ul>
<p>たぶん、人口の上限はある程度大きいほうが効率が良いと思う。ただ、今回は世代カウンタがカタカタ上がっていくビジュアルが欲しかったので、一世代ごとの計算量を抑えるために人口は小さめにしてある。</p>
<p>変異する確率と入れ替えビット数は、大きすぎるとせっかく良い親を選んでもそれを生かせなくなるだろうから、そこそこにとどめておかなくてはいけない。でも逆に小さすぎると、最適さの極大値のようなところで動きが止まってしまう。</p>
<p>これら全てが動作結果を左右する。良い結果を得るためには試行錯誤で良いパラメータを選ばなくてはならない。</p>
<h2>他に考慮すべきところ</h2>
<p>今回は実装しなかったが他に考慮すべき点として、1つのマップで同じ設定のGAを数回から数十回走らせることなどが有効じゃないだろうかと思う。単純に人口を数倍にするのに比べて、ローカルマキシマムで踏みとどまってしまうことが少なくなるはずだ。</p>
<p>あと、せっかくコンピュータを使っているのだから、不器用な生物界をそのまま模倣する必要もない。何が言いたいかというと、生物の進化はランダムな変異が環境によってある方向へ絞られるだけだが、コンピュータでは何かの意図を持って変異させることができる。たとえば巡回セールスマン問題なら、線が交差したり往復したりしていると明らかに距離が長そうだ。そういうった状況を察知して避けるように作為的な変異をさせられれば、効率は大幅に上がるだろう。</p>
<p>もう1つは、そもそもこれをやろうと思った理由ながら実現していないのだが、有性生殖と無性生殖だ。子孫を残す際、二つのDNAを交叉させる必要はあるのだろうか？ひとつのDNAをさまざまな度合いで変異させる、つまり無性生殖では、有性生殖と比べて性能に差が出るのだろうか？友人のA木くんによると「愛があったほうがいい」とのことだが、また時間があれば試してみたいと思う。</p>
<h2>おまけ：環境</h2>
<p>とりあえずパッと実装したかったので比較的馴染みのあるFlash/ActionScript 2.0。以前にFlashでアプリを作ったときよりかなり勝手が分かるようになっていて自分でも驚いた。言語仕様は特殊じゃないから、他の言語での経験が生きたんだろうと思う。次はApolloかな。</p>

]]></content:encoded>
			<wfw:commentRss>http://oddwit.com/blog/2007/flash-ga-salesman/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

