0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【実装編】公共財供給メカニズム〜リンダールメカニズム〜

0
Last updated at Posted at 2026-06-01

前回は公共財自発的供給メカニズム(VCM)を紹介しました。VCMではただ乗り行動が支配戦略になることを確認し、また、VCMは予算均衡条件のみ満たされており、それ以外(ボーエン=サミュエルソン条件、個人合理性、耐戦略性)は満たされていないことを確認しました。今回はリンダールメカニズムというメカニズムを紹介します。

【概要】

本記事で紹介するリンダールメカニズムでは、全プレイヤーの公共財供給量(表明)が一致するまで公共財の負担割合$q_i$を繰り返し調整します。最終的に全員が合意する供給水準 $G^{\ast}$ と負担割合の組 $(G^{\ast}, q^{\ast})$ を「リンダール均衡」と呼びます。つまり、$G_1=G_2=\cdots=G_n=G^{\ast}$ となる$G^{\ast}$を決定するために公共財の負担割合の組$q=(q_1,q_2,\cdots,q_n)$を調整します。

満たす性質

性質 結果 理由
ボーエン=サミュエルソン条件 リンダール均衡では $\sum v'_i(G^{\ast}) = c'(G^{\ast})$ が成立します
予算均衡条件 $\sum x_i = c(G^{\ast})$ が成立します
個人合理性 均衡では各プレイヤーが自分の望む水準で同意するため参加制約を満たします
耐戦略性 × 便益関数を偽ることで個人の利得を改善できます(数値例参照)

ここで、負担割合 $q_i$ の具体的な更新手順が定められていません。そのため、実装には追加的な手続きが必要となり、$q_i$ の更新ルールはデザイナーの裁量に任されています。

【アルゴリズム】

  • ステップ1:政府は各プレイヤー $i$ に対して個別の費用負担割合 $q_i$ を提示します。ただし $\sum_{i=1}^{n} q_i = 1$ を満たします。
  • ステップ2:各プレイヤー $i$ は $q_i$ を所与として、自分の利得 $u_i = v_i(G_i) - q_i c(G_i)$ を最大化する供給水準 $G_i$ を政府に伝えます。
  • ステップ3(反復):$G_1 = G_2 = \cdots = G_n$ が成立していない場合、低い $G_i$ を申告したプレイヤーの $q_i$ を下げ、高い $G_i$ を申告したプレイヤーの $q_i$ を上げ、ステップ1に戻ります。
  • ステップ4:全員が同一の $G^{\ast}$ に合意した時点で供給を確定し、各プレイヤーから $x_i = q_i^{\ast} c(G^{\ast})$ を徴収して終了します。

性質の確認

\begin{align*}
【\text{予算均衡条件}】\quad \sum_{i=1}^{n} x_i &= c(G^*) \sum_{i=1}^{n} q_i^* = c(G^*)\cdot 1=c(G^*)\\[4mm]
【\text{ボーエン=サミュエルソン条件}】\quad
v'_i(G_i) &= q_i c'(G_i) \quad \therefore\quad \sum_{i=1}^{n} v'_i(G^*) = c'(G^*) \quad
\end{align*}

【プログラム】Python

以下の便益関数を前提として実装します。

$$
v_i(G) = G - \frac{1}{2} a_i G^2 \quad (a_i > 0), \quad c(G) = G
$$

解析解

リンダール均衡(最終的に合意された供給水準)を$G\rightarrow G^{\ast}、q_i\rightarrow q_i^{\ast}$とすると、$G^{\ast}$と$q^{\ast}$は以下のように導出されます。

$$
【\boldsymbol{供給水準}】G^* = \frac{n-1}{\sum_{i=1}^{n} a_i}, \qquad 【\boldsymbol{負担割合}】q_i^* = 1 - a_i G^*
$$

上式を用いて、最終的な利得$u_i$は下式のようになります。

$$
【\boldsymbol{利得}】u_i= G-\frac{1}{2}a_iG^2-x_i
$$

"""
リンダールメカニズム(Lindahl Mechanism)
"""

# ===== 定数 =====
SEPARATOR = "=" * 50


# ===== 入力設定 =====
def input_data() -> tuple:
    """パラメータを設定する"""
    N = 3                          # プレイヤー数
    a = [1, 2, 3]                  # 便益パラメータ a_i(値が大きいほど限界便益が急減)
    return N, a


# ===== 供給水準の決定 =====
def determine_supply(N: int, a: list) -> float:
    """リンダール均衡における公共財の供給水準 G* = (N-1) / Σa_i を計算する"""
    return (N - 1) / sum(a)


# ===== 費用負担の計算 =====
def calculate_burden(N: int, a: list, G: float) -> tuple:
    """各プレイヤーの費用負担額 x_i = q_i * c(G) = q_i * G を計算する
    リンダール均衡の費用負担割合: q_i* = 1 - a_i * G*
    """
    q = [1 - a[i] * G for i in range(N)]
    x = [q[i] * G for i in range(N)]
    return x, q


# ===== 利得の計算 =====
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 '× 不成立'}")
    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("  リンダールメカニズム(Lindahl Mechanism)")
    print(SEPARATOR + "\n")

    # 1. 入力情報
    N, a = input_data()
    print("【入力情報】")
    print(f"  プレイヤー数 N      : {N}")
    print(f"  便益パラメータ a_i  : {a}")
    print(f"  便益関数 v_i(G)     : G - 0.5 * a_i * G^2")
    print(f"  供給費用 c(G)       : G\n")

    # 2. 公共財供給水準の決定(リンダール均衡)
    G = determine_supply(N, a)
    print("【公共財供給水準】")
    print(f"  G* = (N-1) / Σa_i = {N-1} / {sum(a)} = {G:.4f}\n")

    # 3. 費用負担の計算
    burden, q = calculate_burden(N, a, G)
    print("【費用負担】  x_i = q_i* × G*  (q_i* = 1 - a_i × G*)")
    for i in range(N):
        print(f"  プレイヤー {i+1}: q_{i+1}* = {q[i]:.4f},  x_{i+1} = {burden[i]:.4f}")
    print(f"  費用負担割合の合計 Σq_i = {sum(q):.4f}  (≒ 1 を確認)\n")

    # 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):ボーエン=サミュエルソン条件 $\sum v'_i(G) = c'(G)$ を解いた解析解 $G^* = \frac{N-1}{\sum a_i}$ を計算します。
  • calculate_burden(N, a, G):リンダール均衡の負担割合 $q_i^* = 1 - a_i G^$ と費用負担額 $x_i = q_i^ G^*$ を計算し、タプル (x, q) として返します。
  • calculate_payoff(N, a, G, x):各プレイヤーの利得 $u_i = v_i(G^*) - x_i$ を計算します。
  • check_conditions(...):4メカニズム共通の条件確認関数です。リンダールは「参加前」($G=0$ 時の便益 = 0)と比較します。

実行結果(N=3、$a = [1, 2, 3]$)

==================================================
  リンダールメカニズム(Lindahl Mechanism)
==================================================

【入力情報】
  プレイヤー数 N      : 3
  便益パラメータ a_i  : [1, 2, 3]
  便益関数 v_i(G)     : G - 0.5 * a_i * G^2
  供給費用 c(G)       : G

【公共財供給水準】
  G* = (N-1) / Σa_i = 2 / 6 = 0.3333

【費用負担】  x_i = q_i* × G*  (q_i* = 1 - a_i × G*)
  プレイヤー 1: q_1* = 0.6667,  x_1 = 0.2222
  プレイヤー 2: q_2* = 0.3333,  x_2 = 0.1111
  プレイヤー 3: q_3* = 0.0000,  x_3 = 0.0000
  費用負担割合の合計 Σq_i = 1.0000  (≒ 1 を確認)

【利得】  u_i = v_i(G*) - x_i
  プレイヤー 1: v_1(G*) = 0.2778,  u_1 = 0.0556
  プレイヤー 2: v_2(G*) = 0.2222,  u_2 = 0.1111
  プレイヤー 3: v_3(G*) = 0.1667,  u_3 = 0.1667

【条件の確認】
  予算均衡条件 : ⚫ 成立  (Σx_i = 0.3333, c(G) = 0.3333)
  個人合理性   : ⚫ 成立
    プレイヤー 1: u_1 = 0.0556 ≥ 参加前 = 0.0000  ⚫
    プレイヤー 2: u_2 = 0.1111 ≥ 参加前 = 0.0000  ⚫
    プレイヤー 3: u_3 = 0.1667 ≥ 参加前 = 0.0000  ⚫

実行結果の読み方

$G^{\ast} = \frac{2}{6} = \frac{1}{3}$ がリンダール均衡の供給量であり、$a_i$ が大きいほど$v_i$や$q_i$が低下します。例えば、プレイヤー3は $q_3^{\ast} = 0$、つまり費用負担なしでリンダール均衡に合意します。全員の利得 $u_i > 0$ であるため個人合理性が成立し、$\sum x_i = G^{\ast}$ により予算均衡条件も成立しています。

耐戦略性が満たされない理由(数値例)

$n=2$、$a_1=a_2=1$、$\theta=1.5$(プレイヤー1が $a_1$ を $\theta$ に偽った場合)として確認します。

\begin{align*}
【\text{真実申告}】&\quad v_1(G^*) - q_1^* c(G^*) = \frac{0.5 \cdot 1}{(1+1)^2} = \frac{1}{8} = 0.125 \\[2mm]
【\text{虚偽申告}】&\quad v_1(G^{**}) - q_1^{**} c(G^{**}) = \frac{1.5 - 0.5}{(1.5+1)^2} = \frac{4}{25} = 0.16
\end{align*}

$0.16 > 0.125$ より、プレイヤー1は虚偽申告することで利得を増やせます。リンダールメカニズムは耐戦略的ではありません

参考資料

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?