rgamer とは、学習・教育・研究目的でゲーム理論を使用する人たちのために作られた R のパッケージである。 rgamer を使えば、ゲームを自動的に解析・可視化することが可能になる。 このサイトでは、rgamer の機能と使い方について簡単に紹介する。 詳細については、我々が執筆した「R で学ぶゲーム理論」(朝倉書店)か、あるいはパッケージのヘルプページから確認してほしい。
R および RStudio のインストールに関しては、有益な情報がネットで見つかるのでそれらを参考にしてほしい。
もし、今までまったく R や RStudio に触れた経験もなく、かつ、インストールなどの作業にあまり自身がない方は、クラウド上で RStudio を使用できるサービス(Posit Clould / 旧 RStudio Clould)が無料で提供されているんで、そちらを利用すると良いだろう。
R や RStudio の基本的な使い方(画面の見方)などについても、多くの情報がネットで公開されているので、必要であればそれらを参照して欲しい。
rgamer
を github
からインストールするために、まずパッケージ remotes
をインストールする。
install.packages("remotes")
続けて、以下のコードを実行すれば rgamer
がインストールできる。
::install_github("yukiyanai/rgamer") remotes
rgamer
を利用するためには、まず rgamer
を読み込む必要がある。
library(rgamer)
これで rgamer
を使用可能である。
試しに、囚人のジレンマゲームを分析してみる。
まずはゲーム(囚人のジレンマゲーム)を定義する。
<- normal_form(
g1 players = c("player 1", "player 2"),
s1 = c("C", "D"),
s2 = c("C", "D"),
payoffs1 = c(4, 5, 1, 2),
payoffs2 = c(4, 1, 5, 2),
)
<- solve_nfg(g1) g1_sol
player 2
|
|||
---|---|---|---|
strategy | C | D | |
player 1 | C | 4, 4 | 1, 5^ |
D | 5^, 1 | 2^, 2^ |
$psNE g1_sol
## [1] "[D, D]"
$br_plot g1_sol
展開形ゲームを定義する方法はいくつか用意されている。 まずは簡単な方法を紹介する。 標準形ゲームで使用した囚人のジレンマゲームを、player 1 (P1) が先手、player 2 (P2) が後手として、プレイされる状況を考える。
<- seq_form(
g2 players = c("P1", "P2"),
s1 = c("C", "D"),
s2 = c("C", "D"),
payoffs1 = c(4, 5, 1, 2),
payoffs2 = c(4, 1, 5, 2),
)
<- seq_extensive(g2) g3
ゲームの木の向きを右向きに変える。
<- seq_extensive(g2, direction = "right") g3
バックワードインダクションで戦略の組を求める。
<- solve_efg(g3)
g3_sol $sols g3_sol
## [[1]]
## [1] "[(D), (D, D)]"
ゲームの木に表示!
$trees g3_sol
## [[1]]
mini 最後通牒ゲームを展開形ゲームとして定義する。
最初に先手(P)が資源(4)の分配案を
から選択し、後手(R)が受け入れる(Y)か拒否する(N)かを選択する。
<- extensive_form(
g4 players = list("P", # n1
rep("R", 3), # n2 - n4
rep(NA, 6) # n5 - n10
),actions = list(c("(4, 0)", "(2, 2)","(0, 4)"), # n1: P
c("Y", "N"), ## n2: R
c("Y", "N"), ## n3: R
c("Y", "N") ## n4: R
),payoffs = list(P = c(4, 0, 2, 0, 0, 0),
R = c(0, 0, 2, 0, 4, 0)),
direction = "right",
show_tree = TRUE,
)
バックワードインダクションを実行する。
<- solve_efg(g4)
g4_sol $sols g4_sol
## [[1]]
## [1] "[((4, 0)), (Y, Y, Y)]"
##
## [[2]]
## [1] "[((2, 2)), (N, Y, Y)]"
ゲームの木に表示!
library(patchwork)
plot(g4_sol$trees[[1]] / g4_sol$trees[[2]])
これより、先手が利己的(自分に全部)な提案する場合も、先手が平等な提案をする場合も、どちらもあり得ることがわかる。
先ほどの展開形ゲームを標準形に変換する。
<- to_matrix(g4)
g4_m <- solve_nfg(g4_m) g4_m_sol
R
|
|||||||||
---|---|---|---|---|---|---|---|---|---|
strategy | (Y, Y, Y) | (Y, Y, N) | (Y, N, Y) | (Y, N, N) | (N, Y, Y) | (N, Y, N) | (N, N, Y) | (N, N, N) | |
P | ((4, 0)) | 4^, 0^ | 4^, 0^ | 4^, 0^ | 4^, 0^ | 0, 0^ | 0, 0^ | 0^, 0^ | 0^, 0^ |
((2, 2)) | 2, 2^ | 2, 2^ | 0, 0 | 0, 0 | 2^, 2^ | 2^, 2^ | 0^, 0 | 0^, 0 | |
((0, 4)) | 0, 4^ | 0, 0 | 0, 4^ | 0, 0 | 0, 4^ | 0, 0 | 0^, 4^ | 0^, 0 |
当然、NE を求めることができる。
$psNE g4_m_sol
## [1] "[((4, 0)), (Y, Y, Y)]" "[((4, 0)), (Y, Y, N)]" "[((4, 0)), (Y, N, Y)]"
## [4] "[((4, 0)), (Y, N, N)]" "[((2, 2)), (N, Y, Y)]" "[((2, 2)), (N, Y, N)]"
## [7] "[((4, 0)), (N, N, Y)]" "[((0, 4)), (N, N, Y)]" "[((4, 0)), (N, N, N)]"
定義済みの標準形ゲームに対して、シミュレーションを実行することが可能である。 例えば、仮想のプレイヤーたちに、囚人のジレンマをプレイさせてみよう。
以下のコードで、50 ペアに 10 期間囚人のジレンマをプレイさせることができる。
set.seed(20230303)
<- sim_game(g1, # 「標準形ゲーム」で定義した g1 である
g1_sim n_samples = 50,
n_periods = 10)
当たり前だが、両者ともにすぐに D を選択し続けるようになる。
$plot_mean g1_sim
男性 \(M1, M2\) と女性 \(W1, W2, W3\) との間での、2部門1対1のマッチング問題について考えよう。
それぞれの選好は以下の通りとする。
男性
女性
では、ボストン方式の結果を求める。
<- matching(
m_boston g1_names = c("M1", "M2"),
g1_prefs = list(c("W1", "W2", "W3"),
c("W2", "W1", "W3")),
g2_names = c("W1", "W2", "W3"),
g2_prefs = list(c("M2", "M1"),
c("M2", "M1"),
c("M1", "M2")),
algorithm = "Boston",
switch = TRUE,
verbose = TRUE
)
## Step 1
## W3 proposes M1
## M1 accepts W3
##
## W1, W2 propose M2
## M2 accepts W2
print(m_boston)
## Results
## W3 : M1
## W2 : M2
## W1 : NA
次に、DA 方式の結果を求める。
<- matching(
m_da g1_names = c("M1", "M2"),
g1_prefs = list(c("W1", "W2", "W3"),
c("W2", "W1", "W3")),
g2_names = c("W1", "W2", "W3"),
g2_prefs = list(c("M2", "M1"),
c("M2", "M1"),
c("M1", "M2")),
algorithm = "DA",
switch = TRUE,
verbose = TRUE
)
## Step 1
## W1 proposes M2
## W1 and M2 temporarily match
##
## W2 proposes M2
## M2 rejects W1
## W2 and M2 temporarily match
##
## W3 proposes M1
## W3 and M1 temporarily match
##
## Step 2
## W1 proposes M1
## M1 rejects W3
## W1 and M1 temporarily match
##
## W3 proposes M2
## M2 rejects W3
##
print(m_da)
## Results
## W1 : M1
## W2 : M2
## W3 : NA
それぞれの結果(マッチング)の安定性をチェックする。
is_stable(m_boston)
## $stable
## [1] FALSE
##
## $blocking_pairs
## proposer proposed proposer_current proposer_better proposed_current
## 1 W1 M1 NA 2 3
## proposed_better
## 1 1
is_stable(m_da)
## $stable
## [1] TRUE
##
## $blocking_pairs
## NULL
つまり、今回の選好リストにおいては、DA 方式は安定な結果を返しているが、 ボストン方式の結果は安定ではない。 (W1, M1) がブロッキングペアである。
Enjoy with rgamer!!!