アダムズ方式

新型コロナワクチンを各都道府県の人口に比例して配分するにはどういう計算をすればいいか。ドント方式で配分すると,人口の非常に少ない県は割当がなくなってしまうかもしれない。そんなときはアダムズ(Adams)方式を使う。Rでの計算法はすでに書いたので,ここではPythonで200箱を配分する。

import numpy as np

都道府県 = ["北海道", "青森", "岩手", "宮城", "秋田", "山形", "福島",
            "茨城", "栃木", "群馬", "埼玉", "千葉", "東京", "神奈川",
            "新潟", "富山", "石川", "福井", "山梨", "長野", "岐阜",
            "静岡", "愛知", "三重", "滋賀", "京都", "大阪", "兵庫",
            "奈良", "和歌山", "鳥取", "島根", "岡山", "広島", "山口",
            "徳島", "香川", "愛媛", "高知", "福岡", "佐賀", "長崎",
            "熊本", "大分", "宮崎", "鹿児島", "沖縄"]

# 2019-10-01推計人口(単位1000人)
人口 = np.array([5250, 1246, 1227, 2306, 966, 1078, 1846, 2860, 1934,
                 1942, 7350, 6259, 13921, 9198, 2223, 1044, 1138, 768,
                 811, 2049, 1987, 3644, 7552, 1781, 1414, 2583, 8809,
                 5466, 1330, 925, 556, 674, 1890, 2804, 1358, 728, 956,
                 1339, 698, 5104, 815, 1327, 1748, 1135, 1073, 1602, 1453])

x = sum(人口) # 総人口

総数 = 250

while (np.sum(np.ceil(総数 * 人口 / x)) > 総数):
    x += 1

割当 = np.ceil(総数 * 人口 / x).astype(int)

for k, v in zip(都道府県, 割当):
    print(k, v)

上の方法では x += 1 が問題になることがある。人口が非常に多いと非効率になり,逆に非常に少ないと 1 ずつ動かしたのでは通り過ぎてしまうことがある。そこで,ドント方式の別解と同様な別解が便利である:

割当 = np.ones_like(人口)
for _ in range(総数 - len(人口)):
    a = 人口 / 割当
    割当[np.argmax(a)] += 1

上のコードでは,人口ゼロの都道府県はなく,総数は都道府県数以上であり,タイはないと仮定した。タイのチェックはドント方式の別解と同様に行うことができる。

都道府県ごとのアダムズ方式とドント方式の割当を並べて示す。大きいところはドント方式が,小さいところはアダムズ方式が有利なことがわかる。

北海道 10 11
青森 3 2
岩手 3 2
宮城 5 4
秋田 2 2
山形 2 2
福島 4 3
茨城 6 6
栃木 4 4
群馬 4 4
埼玉 14 15
千葉 12 13
東京 25 30
神奈川 17 19
新潟 4 4
富山 2 2
石川 3 2
福井 2 1
山梨 2 1
長野 4 4
岐阜 4 4
静岡 7 7
愛知 14 16
三重 4 3
滋賀 3 3
京都 5 5
大阪 16 19
兵庫 10 11
奈良 3 2
和歌山 2 2
鳥取 1 1
島根 2 1
岡山 4 4
広島 5 6
山口 3 2
徳島 2 1
香川 2 2
愛媛 3 2
高知 2 1
福岡 10 11
佐賀 2 1
長崎 3 2
熊本 4 3
大分 3 2
宮崎 2 2
鹿児島 3 3
沖縄 3 3

Last modified: