めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

Jupyterノートブック上でJavaScriptからカーネルのコードを実行する方法

qiita.com

これは、jupyter notebook Advent Calendar 2016の10日目の記事です。

何の話かというと

IPython.displayモジュールのHTML関数を使うと、次のように、Jupyterノートブック上でJavaScriptを実行することができます。

from IPython.display import HTML

javascript = '''
<script type="text/javascript">
    alert("HOGE")
</script>
'''

HTML(javascript) # ポップアップウィンドウを表示

この時さらに、JavaScriptからノートブックを実行中のカーネルを呼び出して、任意のコードを実行することが可能です。また、JavaScript側でコードの実行結果を受け取ることもできます。具体的には、次のようになります。

import numpy as np
from IPython.display import HTML

javascript = '''
<script type="text/javascript">
var kernel = IPython.notebook.kernel;

var callback = function(output) {
  var res = output.content.data['text/plain'];
  alert(res);
};

var x = 2.0;
var command = 'np.sin(' + x + ')';
kernel.execute(command, {'iopub': {"output": callback}}, {silent:false});
</script>
'''

HTML(javascript)

この例では、Pythonカーネル側で np.sin(2.0) を計算して、その結果をJavaScriptに返しています。カーネルの呼び出しは非同期に行われるので、カーネル側の計算が終わったタイミングでコールバック関数(この例では callback)が呼び出されます。JavaScriptからAjaxでREST APIを呼ぶ感覚で、カーネル側のコードを実行すると思えばよいでしょう。

やってみた

というわけで、これを応用して、Jupyterノートブックで遊べるオセロゲームを作りました。オセロの盤面の処理(コマを置いてひっくり返すとか)とコンピュータ側の思考ルーチンをPythonで実装して、JavaScriptのUIから呼び出すようにしています。UIの実装は、enchant.jsを使っています。

github.com

実行画面はこんな感じ。囲碁のパーツで作ったので超違和感がありますがwww。あと、ゲームの終了判定や「パス」ボタンの実装は、面倒だったので省略しています。

うまくいかない点

ゲーム画面が描画された後、画面を上下にスクロールするとクリック位置の判定がおかしくなります。(クリック位置が固定されたままで、一緒にスクロールしていない。)

enchant.jsの実行ループを開始すると、カーソルキーが無効になります。

むむぅ。誰が解決策がわかったら教えてください。

おまけ

コンピュータ側の思考ルーチンはMini-Max法を使っています。具体的には、次のクラスのget_values()メソッドで盤面の評価値(人間側がどの程度優勢か)を計算して、これをなるべく小さくするように打ってきます。

class SimpleMiniMax:
    def get_values(self, boards):
        result = []
        for board in boards:
            score = 0.0
            # The value is defined from the player=1's point of view.
            for c in sum(board, []):
                if c == 1: score += 1
                if c == -1: score -= 1
            result.append([score])
        return np.array(result)

この実装では、「人間側のコマの数-コンピュータ側のコマの数」を評価値にしているので、人間側のコマをなるべく減らす(コンピュータ側のコマをなるべく増やす)という単純なアルゴリズムになっています。最近はやりのディープなんとかで、評価値の計算をなんとかすると、なんとかなあれができるかも知れません。がんばってください。