「高校生のためのゲーム理論入門」の動画公開です

昨年(2021年)の10月に東京都立大学のオープンユニバーシティで講義した「高校生のためのゲーム理論入門」(高校生のための大学授業体験シリーズ)の動画が、東京都立大学のホームページ内でOCWとして公開されることになりました!

2021年度東京都立大学オープンユニバーシティ・高校生のための大学授業体験シリーズ 高校生のためのゲーム理論入門

他のゲーム理論講義動画とともにどうぞ

高校生のゲーム理論研究:八王子東高校「探究学習」の成果発表会に行ってきました!

2021年度は筑波大附属高校の他に、八王子東高校でも「探究学習」のゲーム理論プロジェクトのお手伝いをしました。3月12日(2022年)には、その成果発表会があり、参加させて頂きました。

当日はゲーム理論だけではなく、物理化学、生物、哲学、心理学、スポーツ、ジェンダーなど、さまざまなプロジェクトのすべての成果が発表されていました。多くの会場で同時並行的に発表会が行われ、さながら学園祭のようでした。

成果発表会のプログラム

生徒たちの間に実行委員があり、発表会が行われるようです。すごい!(委員長と副委員長の開会と閉会の挨拶も素晴らしかったです)。

教室での発表の様子

ゲーム理論プロジェクト発表は、主に体育館のポスターセッションでした。発表数も多く、ゲーム理論プロジェクトだけでも、全部を聞けなくて残念でした。

体育館での発表

以下は研究テーマの例です。

  • 親子のお手伝いから考える努力に対する報酬のインセンティブ
  • ブラフはどのような場面で成功するのか
  • Eカードにおける最良の選択は何か
  • チキンゲームで考える恋愛必勝法
ポスターセッション!
ブラフの有効性

今回のゲーム理論プロジェクトは高校1年生の発表でした。ゲーム理論は高校1年生には少し難しいかなとも思たのですが、皆さん、私の「ビジュアルゲーム理論」を参考書にし、よく勉強して、素晴らしい成果を発表していました。⇒アマゾン

ビジュアルゲーム理論

今回の探究学習のお手伝いを通じて、混合戦略などを、どのように高校生に教えればよいか、考えさせられました。高校生を主にターゲットにしながら、ゲーム理論を面白く教えるような教材を作っていきたいと思うようになりました。

筑波大附属高校で「総合的な探究の時間」のお手伝い

筑波大学附属高校で「総合的な探究の時間」のお手伝いをしてきました。高校1年生の「数学的モデリング」をテーマにしたグループで、ゲーム理論の講演をしたり、彼らの研究に助言を与えたりしました。

講演の様子

生徒たちは、ゲーム理論を中心に、自分の興味がある研究テーマに取り組みます。微分も確率もほとんど習っていない高校1年生とは思えないほどの高度な研究に取り組んでいました。テーマの例を挙げると

  • 特殊ルール(手札のシャッフル)がある3人ババ抜きの戦略
  • 3人人狼の戦略とシミュレーション
  • ゲーム理論の観点からの交通渋滞の回避
  • LINEによる異性とのやり取りの戦略

です。また、特に高校生にとってはゲーム理論によるスポーツの戦略に興味があるようで

  • バスケットボールの戦略(3Pシュートと2Pシュートのどちらを打つべきか)
  • 野球の戦略(高校野球における初級ストライクを打つべきかどうか)
  • バレーボールの戦略(アタックはストレートかクロスか)
  • サッカーの戦略(ドリブルか、パスか)

などのテーマが多く見受けられました。

野球の戦略

スポーツの戦略と混合戦略については、いくつかの研究はあるものの、それを詳しく解説したものはありません。改めて、そのような解説を書いてみようかと思いました。

多くの学生のテーマに向き合い、短い時間でアドバイスを与える担当の山田先生は、本当に凄いなと思いました。学生たちの探求は、まだまだ続くようです。

東京都立大学 ゲーム理論 過去の試験問題

東京都立大学「ゲーム理論1」「ゲーム理論2」の過去の試験問題と解答です。一部欠落しているものもあります。2021年度以降の問題は公開していません。講義資料(スライド)や宿題などはこちらにあります。

ゲーム理論1

ゲーム理論2

プログラム更新履歴

更新履歴:ナッシュ均衡を計算するアプリ

(comp_nash1.html, input_bimatrix.py, comp_nash1.py)

  • ver.1 2022/01/03 公開
  • ver.1.1 2022/01/04 例外処理を追加:戦略数が2以上でないとエラーになる。利得行列に空欄があるとエラーになる(htmlのinputタグのrequired属性を設定)。途中で方程式が解けないとエラーになる(正則でないとか、退化しているとかのメッセージを出す。)。利得行列の初期値に0を入れておく(htmlのinputタグのvalueに0を設定)。
  • ver.1.2. 2022/01/06 絶対値が極端に大きい(1e10以上)数値や無限大(inf)の利得は受け付けない。利得行列にNaNがあるときに受け付けない例外処理。
  • ver.1.3. 2022/01/06 正則ではない利得行列への対応
  • ver.1.4. 2022/01/07 戦略数が10以上の場合のバグへの対応:行列Aのi行j列をaijという文字列でデータを受け取っていたが、a23だと2行3列となるが、a111だと1行11列なのか、11行1列なのk分からない、という問題が発生。aizjとzで区切ることにした。
  • ver.1.5 2022/01/13 2X2は受け付けないことにしました(試験や宿題で使われるのを防ぐため)。また、入口となるページをhtmlで書いていましたが、すべてpyファイルにし、pythonで出力することにしました。最初に入り口としてリンクされたページhttp://nabenavi.net/ap/comp_nash1はなくなりましたが、twitter等で拡散していましたので、.htaccessにてリダイレクトするようにしました。
  • ver.1.6 2022/06/09 要請があり、宿題だと受け付けない処理をつけました。

NABENAVI.net 計算プロジェクト

戦略10以下の2人戦略形ゲームのナッシュ均衡を(混合戦略まで含めて)すべて計算するプログラムなど、趣味で作ったweb上の計算アプリケーションを提供しています。

ゲーム理論 オンライン講義 一覧

東京都立大学 ゲーム理論 オンライン講義

2020年コロナ対応でオンデマンドにした大学の講義動画をyoutubeに公開しています。以下は、そのタイトルの一覧です。

GoogleアナリティクスGA4ではGTMを使わない?

  • Googleアナリティクスが、今までの「ユニバーサルアナリティクス(UA)」というもの(プロパティ)から「アナリティクス4(GA4)」というものに変わったみたい。
  • ユニバーサル アナリティクスでは、収集されたデータの基本単位は「ヒット」と呼ばれた。そして、ページビューとイベントという 2 つのヒットタイプがよく使用された。
  • このアナリティクスで「あるページから外部リンクが何回クリックされたか」など、いろいろなデータを計測するために「イベント」を自分で作成する必要があった
  • そして、イベントを作成するためには、これまで(UAで)はページに「タグ」と呼ばれるものを埋め込まなければならなかった。そのために、直接ページにタグを埋め込む方法と「Googleタグマネージャー(GTM)」と呼ばれるもので管理する方法と2つあった。
  • 多くのタグを管理するためにはGTMが便利であり、それを解説しているページが多い。
  • 一方、GA4ではイベントの概念が変わった。GA4ではデータの収集単位がイベントになった。ページビューもイベントの1つだ。
  • そしてイベントはタグを埋め込まなくても、アナリティクスで直接管理できるようなしくみが多く導入された。
  • したがってUA4から解析しているときは、GTMは必要ない?GTMで管理しているような記事は参照にしないほうが良い?
  • まだまだ、わからないことが多く勉強が必要?

numpyをimportしたcgiをさくらのレンタルサーバーで動かす。

前の記事「さくらのレンタルサーバーにPython3とNumpyをインストールする」で、見事にPython3とNumpyのインストールに成功したと思った自分だったが、pythonで書かれたcgiプログラムを動かすと、再びnumpyがimportできず「ctypeがない問題」が発生した。試行錯誤の結果、numpyのバージョンを更に下げて、動かすことに成功した。

ITやや素人の私が、ナッシュ均衡を計算するwebアプリを作るための記録。前回は「さくらのレンタルサーバーにPython3とNumpyをインストールする」で、苦労の末、遂にPython3とNumpyのインストールに成功した…と思ったのだが…。

ターミナルでは問題なく動く

webアプリを作るためにいろいろ試行錯誤。これについては、また改めて記事にしようと思う。とりあえず、現時点の目標「htmlからフォームでデータを送り、python3で(numpyをインポートして書かれた)cgiプログラムを動かして出力する」こと。

まず自分のPCのwindows上でやってみて、うまく行った。そこで次に、さくらのレンタルサーバー上で、動かすことに挑戦。ところがうまく動かない。Internal Server Errorになるのである。

そこでまず、以下の簡単なプログラムをファイル名 investigation2.cgi として作った。

#!$HOME/local/python/bin/python3

import cgi
import cgitb
import numpy as np

cgitb.enable() 
print("Content-type: text/html <br>")
print()
print("Hello World!<br>")
print(np.zeros(5))

($HOMEは実際には正しいパス名が入る)。windowsではうまく動いたし、シェルから動かすと、以下のようにちゃんと動く

% python3 investigation2.cgi
Content-type: text/html <br>

Hello World!<br>
[0. 0. 0. 0. 0.]

そこでブラウザから http://正しいURL/investigation2.cgiとしても、うまく行かない。パーミションはきちんとしているし、だいいちここから、import numpy as npと print(np.zeros(6)) を削除し http://正しいURL/investigation2.cgiとすると

とちゃんと出てくるじゃないか。どう見ても import numpy as np が悪さをしている。しかしcgiでエラーが出るとエラーをブラウザに吐いてくれるcgitbというモジュールも、エラーを吐いてくれない。これはどうしたことだろうか?

いろいろネットでべると「import numpy を直接ではなく、関数に入れるとできる」のようなっ記事を目にしたので(ごめんなさい、どの記事か忘れてしまいました)、以下のように変更してみた。essential_mainという関数を定義し、そこでnumpyをインポートする、というものだ。

#!/home/nabepremium/local/python/bin/python3

import cgi
import cgitb

def essential_main():
    import numpy as np
    print("in the main function")
    print(np.zeros(5))

cgitb.enable() 
print("Content-type: text/html <br>")
print()
print("Hello World!<br>")
essential_main()

うーん、これでもダメだった。しかし、これだと Internal Server Errorにならず、アクセスはできていた、しかも幸いなことに、cgitbがエラーをブラウザに吐き出してくれたのである。エラーの内容は多いので、ここには記さないが、エラーを読むと

numpyのモジュールは探し出せているが、numpyをインポートするときにnumpy自身がいろんなライブラリを呼び出していて、その際に

import _ctypes_ctypes undefined

とか

ImportError: Shared object “libffi.so.6” not found, required by “_ctypes.cpython-38.so”

とかいうエラーが出ているようだ。…ん?ctypeがないって…

まだゾンビのように生き残っていたのか!ctypes問題!(詳しくは 「さくらのレンタルサーバーにPython3とNumpyをインストールする」 を参照せよ)

環境変数やsys.path.insertなど試してみるもダメ

Shared object “libffi.so.6” not found, required by “_ctypes.cpython-38.so とあるが、この libffi.so.6 というファイルは、前回のlibffiをインストールしたときに入っている。なので、これを見つけることができないということは、環境変数かパスを通してやれば、いいんじゃないか?と考えたのだが、ここからはpythonやnumpyに通じてない、やや素人の私には無理な話。とりあえずpathとか、いろいろな環境変数にlibffi.so.6があるパスを入れたりしたのだがダメである。

自分がターミナルから動かしたときには動くのに、cgiからは動かない、というのはlibffi.so.6のある位置が、外部のnobodyだったかotherがcgiを動かすときに、これが見えなくなっていることだから、 プログラムの内部にこれを教えてやればいいんじゃないか?と推測する。でもも、ここからはpythonやnumpyに通じてない、やや素人の私にはやっぱり無理な話。

また調べてみると、プログラムがモジュールを検索するときはsys.pathというものを使うということで、プログラム内でsys.path.insertというコマンドによって、モジュールを検索する場所を教えることができるようだ。そこでこのコマンドでいろいろパスを追加するもやっぱりダメ。

そもそもnumpyというモジュールの位置は探し出していて、それをインポートするときに、numpyが呼び出すライブラリのようなものが見つからないって言っているので、上記のやり方は違う気がする。

エラーは「_ctypes.cpython-38.soによって要求されるlibffi.so.6がない」と言っている。だからpythonに教えると言うよりは、この_ctypes.cpython-38.soにlibffi.so.6の位置を教えてやらないとダメだということだろう。しかし、どうやって教えればいいのかが分からない。_ctypes.cpython-38.soは$HOME/local/python/lib/python3.8/lib-dynloadにあるので、ここに libffi.so.6 をコピーしてみたのだが、やはり動かないようだ。やや素人の私には限界である。

Numpyのバージョンを下げる

_ctypes.cpython-38.soやlibffi.so.6はバイナリファイルだ。いろんな記事を読み、前回の記事で見たpyproject.toml-based projectの話も考慮して、素人の私の勝手な推測は、以下のようなことだ。

  • pythonのモジュールやNumpyは、初期の頃より複雑で巨大化している。だからモジュールで使われるライブラリなどは、最初はソースファイルで提供され、モジュールのインストール時にコンパイルされていたが、だんだんとバイナリで出来上がったものが提供されたり、利用されるようになってきたんじゃないだろうか。
  • ところがその「出来合いのバイナリファイル」が問題を起こしている。それは、ライブラリがモジュールのインストール時にコンパイルされたときには、持っている情報を使えるんだが、出来合いだとそれが使えないから、後で教えなければならない。
  • でも教え方は分からない。
  • じゃあ、モジュールのバージョンを下げて、ライブラリをモジュールのインストール時にコンパイルする時代まで戻れば、なんとかなるんじゃないか?だいたい、最初もNumpyのバージョンを下げればうまくいったじゃないか。

Numpyの最新のバージョンは1.21.5だが、先のインストール時に1.18.4に下げている(「さくらのレンタルサーバーにPython3とNumpyをインストールする」 を参照)。どこまで下げればいいんだろう?じゃあ、思いっきり下げてバージョン1.8.1くらいにしてみよう!

ということで、一応、Pythonを再インストールしてきれいにし、

%pip3 install numpy==1.8.1

としてみた。すると
Using legacy ‘setup.py install’ for numpy, since package ‘wheel’ is not installed.
として、かなり時間がかかっている。うーん、よくわからないが「(現在はwheelという完成品のパッケージを使うんだけど)、それがないから古いやりかた(古い遺産:legacy)である setup.py によってインストールしている」と言ってるのだろう、とやや素人の私は解釈。 かなり時間がかかって、エラーが出てないのはいい兆候だ、と思い、しばらく待つも、最後には大量のエラーが吐き出され失敗。

古すぎたのだろうか。それじゃあということで、適当にバージョン 1.14.6で挑戦してみた。すると、さっきと同じで
Using legacy ‘setup.py install’ for numpy, since package ‘wheel’ is not installed.
して、かなり時間がかかっている。

「こんな当てずっぽうなやり方じゃダメだな、これで同じエラーが出たら推測もだめだってことで、もう諦めよう」と思うが、とりあえず最後と思ってずっと待つ。「もうダメだ」と思った瞬間、なんとインストールに成功したじゃないか!

びっくりした。エラーが出るかと思ったが。

次に、先の http://正しいURL/investigation2.cgi にアクセスしてみると、ちゃんと動く。

さらに、import numpyを関数内の呼び出しからメインプログラムへ移したのだが、やはりちゃんと動いている。かくしてCGIでも正しく動作したのであった。

推測は正しくないかも知れないがまとめると、Python3.8.12とNumpy 1.14.6 の組み合わせで、cgiプログラムも正しく動作したのであった。

やっとここまで来た。しかし、まだwebアプリへの道のりは続くのであった。