政治資金収支報告書のプログラム
先日のアルゴリズムを実装してみました。
といっても、実際のデータは諸般の事情により利用できないので、サンプルデータを使っての実装です。
-
-
- -
-
テストデータは、4つの団体が含まれます。
- Poli_A - 政党A
- Poli_B - 政治家B
- Poli_C - 政治家C
- Poli_D - ロビー団体D
寄付の内訳
直接の寄付 | Poli_Aから | Poli_Bから | Poli_Cから | Poli_Dから | |
---|---|---|---|---|---|
Poli_Aへ | 50 | 20 | 20 | 50 | |
Poli_Bへ | 30 | 70 | 50 | ||
Poli_Cへ | 30 | 70 | |||
Poli_Dへ | 100 |
表の見方は、たとえば、Poli_Dはロビー団体なので、会員からの寄付のみが収入で、そのお金を他の政治団体に配っています。また、Poli_Aは政党なので、党員の政治家に活動費を配っています。
お金の流れをよく見ると、閉路も含まれています。これは、政治家が政党へ会費を納める一方、政党が政治家に活動費を配るという現象を説明しています。
-
-
- -
-
結果は次のようになりました。
収入の内訳
Poli_A | Poli_B | Poli_C | Poli_D | |
---|---|---|---|---|
直接の寄付 | 50.0 | 30.0 | 30.0 | 100.0 |
Poli_Aから | 10.0 | 30.0 | 30.0 | 0.0 |
Poli_Bから | 4.8 | 2.4 | 2.4 | 0.0 |
Poli_Cから | 7.2 | 3.6 | 3.6 | 0.0 |
Poli_Dから | 68.0 | 84.0 | 34.0 | 0.0 |
合計 | 140 | 150 | 100 | 100 |
これを見ると、政治家B(Poli_B)が半分以上の収入をロビー団体D(Poli_D)から得ているほか、政治家C(Poli_C)も直接は受け取っていませんが、政党を経由して収入の1/3をロビー団体Dに依存していることがわかります。
なお、自分自身からも寄付を受け取ったことになっていますが、これは他の団体に寄付したお金が、めぐりめぐってまた自分のところに戻ってきたことを示しているので、バグではありません。
プログラム
module polimoney import String, StdFile, Misc, List, Real ::Group = { name :: String, expense :: [(String, Real)], income_total :: Real, income1 :: Real, // income from people's donation income2 :: [(String, Real)] // [result] income from other political groups } Start w = loop (calc InitialData) where loop (diff, data) | diff < 0.01 = show data w = loop (calc data) calc data = let data2 = newdata data in (diff data2 data, data2) where newdata [] = [] newdata [group: rest] = [{group & income2 = newincome2 group.name}: newdata rest] newincome2 target = sortsum [] unsorted where unsorted = foldr (++) [] [foldr (++) [] [income_of name income_total v income1 income2 \\ (n, v) <- expense | n == target] \\ {name, expense, income_total, income1, income2} <- data] income_of name total expense income1 income2 = [(name, income1 * prop): [(n, v * prop) \\ (n, v) <- income2]] where prop = expense / total sortsum re [] = re sortsum re [(name, value): rest] = sortsum (update re name value) rest update [] name value = [(name, value)] update [(n0, v0):rest] name value | n0 == name = [(name, v0 + value): rest] | n0 < name = [(n0, v0): update rest name value] = [(name, value), (n0, v0): rest] diff [] [] = 0.0 diff [g0: d0] [g1: d1] = diffincome2 g0.income2 g1.income2 + diff d0 d1 diffincome2 [] income2 = sum $ map (\(_,v) = v) income2 diffincome2 income2 [] = sum $ map (\(_,v) = v) income2 diffincome2 g0`=:[(n0,v0):g0] g1`=:[(n1,v1):g1] | n0 == n1 = abs (v0 - v1) + diffincome2 g0 g1 | n0 < n1 = v0 + diffincome2 g0 g1` = v1 + diffincome2 g0` g1 show data w # (f, w) = stdio w f = foldl writedata f data (_, w) = fclose f w = w where writedata f {name, expense, income_total, income1, income2} = f |> fwrites name |> fwrites "\nTotal Income: " |> fwriter income_total |> fwrites "\n Direct = " |> fwriter income1 |> (\f = foldl writedetail f income2) |> fwrites "\n\n" writedetail f (name, value) = f |> fwrites "\n " |> fwrites name |> fwrites " = " |> fwriter value //==== DATA ====// InitialData = [ { name = "Poli_A", // party expense = [("Poli_B", 70.0), ("Poli_C", 70.0)], income_total = 140.0, income1 = 50.0, income2 = [("*Poli_A", 90.0)] }, { name = "Poli_B", // politician expense = [("Poli_A", 20.0)], income_total = 150.0, income1 = 30.0, income2 = [("*Poli_B", 120.0)] }, { name = "Poli_C", // politician expense = [("Poli_A", 20.0)], income_total = 100.0, income1 = 30.0, income2 = [("*Poli_C", 70.0)] }, { name = "Poli_D", // lobby expense = [("Poli_A", 50.0), ("Poli_B", 50.0)], income_total = 100.0, income1 = 100.0, income2 = [] } ]
実行結果
$ ./polimoney Poli_A Total Income: 140 Direct = 50 *Poli_A = 0.000321502057613169 Poli_A = 9.99996427754915 Poli_B = 4.79998285322359 Poli_C = 7.19997427983539 Poli_D = 67.9997570873342 Poli_B Total Income: 150 Direct = 30 *Poli_B = 0.000171467764060357 *Poli_C = 0.000150034293552812 Poli_A = 29.9998928326475 Poli_B = 2.3999914266118 Poli_C = 3.5999871399177 Poli_D = 83.9998070987654 Poli_C Total Income: 100 Direct = 30 *Poli_B = 0.000171467764060357 *Poli_C = 0.000150034293552812 Poli_A = 29.9998928326475 Poli_B = 2.3999914266118 Poli_C = 3.5999871399177 Poli_D = 33.9998070987654 Poli_D Total Income: 100 Direct = 100