前回はリンダールメカニズムを紹介しました。これまでのVCM、リンダールメカニズムともに「耐戦略性を満たさない」という性質を確認しました。本記事では「耐戦略性を満たすメカニズム」としてボーエンメカニズムを紹介します。
【概要】
ボーエンメカニズムは、費用負担を全プレイヤーで均等に分担($q_i = \frac{1}{n}$)したうえで、各プレイヤーが望む公共財供給水準を表明させ、コンドルセ方式(多数決投票) によって供給量を決定するメカニズムです。
各プレイヤーの選好が単峰的であれば、中位投票者定理によってちょうど中央値の $G^*$ がコンドルセ勝者となります。また、限界便益が正規分布に従う場合に限り、中央値と平均値が一致するためボーエン=サミュエルソン条件を満たします。この2つの制約条件は非常に厳しく、一般には成立しません。
満たす性質
| 性質 | 結果 | 条件 |
|---|---|---|
| ボーエン=サミュエルソン条件 | ×(条件付き⚫) | 限界便益が正規分布に従う場合のみ成立しますが、一般的に満たすのは非常に困難。 |
| 予算均衡条件 | ⚫ | $\sum q_i = 1$ より常に成立します |
| 個人合理性 | × | 均等負担が強制されるため参加が不利なプレイヤーが生じます |
| 耐戦略性 | ⚫ | 選好が単峰的であれば成立します(制約あり) |
「選好の単峰性」の簡単な説明
プレイヤー $i$ の選好が単峰的であるとは、ある「理想点(最も好ましい水準)」$G_i^{\ast}$ が存在し、そこから離れるほど選好が単調に下がる性質のことです。グラフにしたときに一番順位が高い結果(峰)が1つしかなく、そこから右の結果も左の結果も単調に下がっていくようなグラフの形状を指します。
下図はそれぞれ左が単峰性の図、右が双峰性(多峰性)の図になります。
単峰性が重要な理由は、コンドルセのパラドックス(多数決の循環)を防げるからです。全員の選好が単峰的であれば、どの2案を比較しても多数決で必ず勝者が決まり、次節で登場する「中位投票者定理」によって中央値が唯一のコンドルセ勝者となります。
【アルゴリズム】
- ステップ1:政府は全 $n$ 人のプレイヤーに対して均等な費用負担割合 $q_i = \frac{1}{n}$ を提示します。
- ステップ2:各プレイヤー $i$ は $q_i = \frac{1}{n}$ を所与として、自分の利得 $u_i = v_i(G_i) - \frac{c(G_i)}{n}$ を最大化する供給水準 $G_i$ を表明します。
- ステップ3:政府は表明された ${G_1, G_2, \ldots, G_n}$ を候補とし、コンドルセ方式(任意の2候補を多数決で比較し続ける方式)で最終的な供給量を決定します。全員の選好が単峰的であれば、中位投票者定理より中央値 $G_m$ がコンドルセ勝者となります。
- 確定:$G^* = G_m$ の公共財を供給し、各プレイヤーから $x_i = \frac{c(G^*)}{n}$ を徴収して終了します。
補題:中位投票者定理
投票者全員が単峰的な選好を持っている場合、中位投票者(中央値の順位を持つ投票者)が望む候補が多数決投票によって選択されます。
ボーエン=サミュエルソン条件が満たされるための2つの制約
\begin{align*}
【\text{条件(1)}】&\quad v'_m(G_m) = \frac{c'(G_m)}{n} \quad \cdots\text{中位投票者の最適化条件}\\[2mm]
【\text{条件(2)}】&\quad v'_m(G_m) = \frac{\displaystyle\sum_{i=1}^{n} v'_i(G_i)}{n} \quad \cdots v_i\text{が正規分布に従う場合}
\end{align*}
条件(1)(2)を合わせると $\sum_{i=1}^{n} v_i'(G^{\ast}) = c'(G^{\ast})$ が成立し、ボーエン=サミュエルソン条件を満たします。ただし条件(2)は $v_i$ が正規分布に従うと仮定しています。これにより$中央値v_m'(G_m)=平均値\frac{1}{n}\sum_{i=1}^{n} v'_i(G_i)$を導出していますが、実用上制約が厳しく、一般には成立しません。
【プログラム】Python
以下の設定で実装します。
$$
v_i(G) = G - 0.5, a_i G^2, \quad c(G) = G, \quad a = [a_1, a_2, a_3] = [1,, 2,, 10]
$$
パラメータの設計意図:$a_3 = 10$ と大きく設定することで、プレイヤー3が望む供給水準 $G_3 = \frac{2}{3 \times 10} \approx 0.067$ が、多数決で決定される $G^* = \frac{1}{3}$ と大きく乖離します。均等負担の強制により $x_3 = \frac{G^{\ast}}{3}$ を支払う一方、$G^{\ast}$ での便益 $v_3(G^*)$ が負となるため、個人合理性の違反が確認できます。
解析解
プレイヤーの数を$n$とすると、各プレイヤーの最適な供給水準$G_i^{\ast}$ は以下のように導出されます。
\begin{align*}
【\boldsymbol{供給水準}】&G_i^* = \frac{n-1}{na_i}
\end{align*}
今回の例の場合、プレイヤー数は3人であり $G_2^{\ast}$ が中央値になるため、公共財の供給水準は$\frac{1}{3}$になります。上記を踏まえ、最終的な利得$u_i$は下式のようになります。
\begin{align*}
【\boldsymbol{利得}】&u_i = G-\frac{1}{2}a_iG^2-x_i
\end{align*}
"""
ボーエンメカニズム(Bowen Mechanism)
"""
import statistics
# ===== 定数 =====
SEPARATOR = "=" * 50
# ===== 入力設定 =====
def input_data() -> tuple:
"""パラメータを設定する"""
N = 3 # プレイヤー数
a = [1, 2, 10] # 便益パラメータ a_i(a_3が大きく,強制負担でIR違反が生じる)
return N, a
# ===== 供給水準の決定 =====
def determine_supply(N: int, a: list) -> tuple:
"""コンドルセ方式(中位投票者定理)により公共財の供給水準を決定する
各プレイヤーの最適化条件 v'_i(G_i) = q_i より G_i = (1 - q_i) / a_i
中位投票者定理: 供給水準の中央値がコンドルセ勝者となる
"""
q = [1 / N] * N # 均等割の費用負担割合
g_reported = [(1 - q[i]) / a[i] for i in range(N)] # 各プレイヤーの表明水準
G = statistics.median(g_reported) # 多数決(中央値)で決定
return G, q, g_reported
# ===== 費用負担の計算 =====
def calculate_burden(N: int, q: list, G: float) -> list:
"""各プレイヤーの費用負担額 x_i = q_i * c(G) = q_i * G を計算する"""
return [q[i] * G for i in range(N)]
# ===== 利得の計算 =====
def calculate_payoff(N: int, a: list, G: float, x: list) -> list:
"""各プレイヤーの利得 u_i = v_i(G) - x_i を計算する
v_i(G) = G - 0.5 * a_i * G^2
"""
return [G - 0.5 * a[i] * G**2 - x[i] for i in range(N)]
# ===== 条件の確認 =====
def check_conditions(N: int, G: float, burden: list, payoff: list,
endowment: list, c_G: float) -> None:
"""予算均衡条件と個人合理性を数値的に確認する"""
budget_ok = abs(sum(burden) - c_G) < 1e-9
ir_flags = [payoff[i] >= endowment[i] for i in range(N)]
ir_ok = all(ir_flags)
print("【条件の確認】")
print(f" 予算均衡条件 : {'⚫ 成立' if budget_ok else '× 不成立'}"
f" (Σx_i = {sum(burden):.4f}, c(G) = {c_G:.4f})")
print(f" 個人合理性 : {'⚫ 成立' if ir_ok else '× 不成立'}"
f" ※パラメータによっては不成立になる場合があります")
for i in range(N):
sign = "≥" if ir_flags[i] else "<"
mark = "⚫" if ir_flags[i] else "×"
print(f" プレイヤー {i+1}: u_{i+1} = {payoff[i]:.4f} "
f"{sign} 参加前 = {endowment[i]:.4f} {mark}")
# ===== メイン =====
def main() -> None:
print(SEPARATOR)
print(" ボーエンメカニズム(Bowen Mechanism)")
print(SEPARATOR + "\n")
# 1. 入力情報
N, a = input_data()
print("【入力情報】")
print(f" プレイヤー数 N : {N}")
print(f" 便益パラメータ a_i : {a}")
print(f" 費用負担割合 q_i : 1/N = {1/N:.4f}(全員均等割)")
print(f" 便益関数 v_i(G) : G - 0.5 * a_i * G^2")
print(f" 供給費用 c(G) : G\n")
# 2. 公共財供給水準の決定(コンドルセ方式)
G, q, g_reported = determine_supply(N, a)
print("【公共財供給水準】 G_i = (1 - q_i) / a_i → G* = 中央値")
for i in range(N):
print(f" プレイヤー {i+1} の表明水準 G_{i+1} = {g_reported[i]:.4f}")
print(f" G* = 中央値(コンドルセ勝者) = {G:.4f}\n")
# 3. 費用負担の計算
burden = calculate_burden(N, q, G)
print("【費用負担】 x_i = q_i × G* = (1/N) × G*")
for i in range(N):
print(f" プレイヤー {i+1}: x_{i+1} = {burden[i]:.4f}")
print()
# 4. 利得の計算
payoff = calculate_payoff(N, a, G, burden)
print("【利得】 u_i = v_i(G*) - x_i")
for i in range(N):
vi = G - 0.5 * a[i] * G**2
print(f" プレイヤー {i+1}: v_{i+1}(G*) = {vi:.4f}, u_{i+1} = {payoff[i]:.4f}")
print()
# 5. 条件の確認(参加前の利得 = G=0 時の便益 = 0)
check_conditions(N, G, burden, payoff, endowment=[0.0]*N, c_G=G)
if __name__ == "__main__":
main()
コード解説
-
determine_supply(N, a):均等割 $q_i = 1/N$ を固定したうえで、各プレイヤーの最適化条件 $G_i = \frac{1-q_i}{a_i}$ から表明水準を計算し、statistics.median()でコンドルセ方式(中位投票者定理)を実装します。タプル(G, q, g_reported)を返します。 -
calculate_burden(N, q, G):均等割の費用負担額 $x_i = \frac{1}{N} \cdot G^*$ を計算します。全プレイヤーで同額となります。 -
calculate_payoff(N, a, G, x):利得 $u_i = v_i(G^{\ast}) - x_i$ を計算します。$a_i$ が大きいプレイヤーは $v_i(G^*)$ が負になる場合があります。 -
check_conditions(...):4メカニズム共通の条件確認関数です。今回は× 不成立が数値的に確認でき、ボーエンメカニズムが一般に個人合理性を満たさないことが示されます。
実行結果(N=3、$a = [1, 2, 10]$)
==================================================
ボーエンメカニズム(Bowen Mechanism)
==================================================
【入力情報】
プレイヤー数 N : 3
便益パラメータ a_i : [1, 2, 10]
費用負担割合 q_i : 1/N = 0.3333(全員均等割)
便益関数 v_i(G) : G - 0.5 * a_i * G^2
供給費用 c(G) : G
【公共財供給水準】 G_i = (1 - q_i) / a_i → G* = 中央値
プレイヤー 1 の表明水準 G_1 = 0.6667
プレイヤー 2 の表明水準 G_2 = 0.3333
プレイヤー 3 の表明水準 G_3 = 0.0667
G* = 中央値(コンドルセ勝者) = 0.3333
【費用負担】 x_i = q_i × G* = (1/N) × G*
プレイヤー 1: x_1 = 0.1111
プレイヤー 2: x_2 = 0.1111
プレイヤー 3: x_3 = 0.1111
【利得】 u_i = v_i(G*) - x_i
プレイヤー 1: v_1(G*) = 0.2778, u_1 = 0.1667
プレイヤー 2: v_2(G*) = 0.2222, u_2 = 0.1111
プレイヤー 3: v_3(G*) = -0.2222, u_3 = -0.3333
【条件の確認】
予算均衡条件 : ⚫ 成立 (Σx_i = 0.3333, c(G) = 0.3333)
個人合理性 : × 不成立 ※パラメータによっては不成立になる場合があります
プレイヤー 1: u_1 = 0.1667 ≥ 参加前 = 0.0000 ⚫
プレイヤー 2: u_2 = 0.1111 ≥ 参加前 = 0.0000 ⚫
プレイヤー 3: u_3 = -0.3333 < 参加前 = 0.0000 ×
実行結果の読み方
プレイヤー3の便益パラメータ $a_3 = 10$ は他のプレイヤーに比べて非常に大きく、限界便益が急減することを意味します。そのため、プレイヤー3が望む供給水準は $G_3 = 0.067$ と非常に小さいです。しかし多数決によって $G^* = 0.333$ が選ばれ、この水準での便益は $v_3(G^*) = -0.222 < 0$ となります。さらに均等負担 $x_3 = 0.111$ を強制されるため、利得は $u_3 = -0.333 < 0$ となり、参加しない場合(利得 = 0)より悪化します。これが個人合理性の違反です。
| プレイヤー | 望む $G_i$ | 強制される $G^*$ | $v_i(G^*)$ | $x_i$(均等負担) | 利得 $u_i$ | 個人合理性 |
|---|---|---|---|---|---|---|
| 1 | 0.667 | 0.333 | +0.278 | 0.111 | +0.167 | 成立 |
| 2 | 0.333 | 0.333 | +0.222 | 0.111 | +0.111 | 成立 |
| 3 | 0.067 | 0.333 | −0.222 | 0.111 | −0.333 | 不成立 |