如何在加权多数投票游戏中快速找到所有最小获胜联盟?
Posted
技术标签:
【中文标题】如何在加权多数投票游戏中快速找到所有最小获胜联盟?【英文标题】:How to find all minimal winning coalitions in a weighted-majority voting game in a fast way? 【发布时间】:2022-01-06 13:25:02 【问题描述】:编辑:感谢论文A survey of algorithms for calculating power indices of weighted majority games,我找到了解决方案
我想解决以下问题:
给定一个集合 N=1,..,n,权重向量 W=w_1,..,w_n,按降序排序,总和为 1, 找到 N 的所有子集 C(也称为“联盟”),使得
-
C 是“获胜”,即子集 C 内元素的权重之和超过某个阈值(例如 0.5)
C 是“最小的”,这意味着从 C 中删除任何元素都将使子集不再“获胜”。
为了澄清,一个例子可以是:N=1,2,3 W=0.45,0.35,0.2
-
这里的“获胜”子集是 1,2、2,3、1,3 和 1,2,3,因为它们的总权重都超过 0.5
只有 1,2、2,3 和 1,3 是最小的,因为在 1,2,3 中您可以删除一个元素并获取上面的元素。
从上面引用的论文中,我现在实现了这个代码,它递归地生成所有最小获胜联盟的列表
MWC = function(w,threshold=0.5)
n = length(w)
l = list()
enumerate = function(S1,n1,b1)
if(n1==n)
return(list(c(S1,n1)))
else
if(sum(w[(n1+1):n]) >= b1)
l = c(l,enumerate(S1,n1+1,b1))
if(w[n1] >= b1)
l=c(l,list(c(S1,n1)))
else
l = c(l,enumerate(c(S1,n1),n1+1,b1-w[n1]))
return(l)
return(enumerate(c(),1,threshold))
w = c(0.46,0.3,0.19,0.05)
MWC(w)
在指数复杂度使一切都不可行之后,代码运行到 n = 20 左右。
【问题讨论】:
为什么 2,3 在您的第一个样本中不是一个获胜的子集? 你说得对,我编辑了这个问题。对不起这个错误 【参考方案1】:您的问题的一个解决方案是使用while loop
并在循环中应用上述约束。
下面是工作代码:
N = 1:10
W <- c(0.60, 0.40, 0.33, 0.30, 0.25, 0.20, 0.15, 0.10, 0.05, 0.03);
Winning_Sets <- c()
i <- 1
while (i != (length(N) - 1))
if (i == 1)
Subsets <- combn(N, i)
else
Keep_Combs <- Subsets[,which(Intermediate_Sets == 'No_Match')]
Subsets <- combn(N, i)
if (i == 2)
Subsets <- apply(Subsets, 2, function(x)
x <- x[x[i - 1] %in% Keep_Combs]
)
else
Subsets <- apply(Subsets, 2, function(x)
unlist(apply(Keep_Combs, 2, function(y)
if (identical(y, x[1:(i - 1)]) == TRUE)
x
))
)
Subsets <- do.call('cbind', Subsets)
Intermediate_Sets <- apply(Subsets, 2, function(x)
if (sum(W[x]) > 0.5)
paste('', paste(x, collapse = ','), '', sep = '')
else
'No_Match'
)
Winning_Sets <- append(Winning_Sets, unlist(Intermediate_Sets[Intermediate_Sets != 'No_Match']))
if (length(which(Intermediate_Sets == 'No_Match')) > 0)
i <- i + 1
else
i <- length(N) - 1
输出:
Winning_Sets
[1] "1" "2,3" "2,4" "2,5" "2,6" "2,7"
[7] "3,4" "3,5" "3,6" "4,5" "2,8,9" "2,8,10"
[13] "3,7,8" "3,7,9" "3,7,10" "4,6,7" "4,6,8" "4,6,9"
[19] "4,6,10" "4,7,8" "5,6,7" "5,6,8" "3,8,9,10" "4,7,9,10"
[25] "5,6,9,10" "5,7,8,9" "5,7,8,10" "6,7,8,9,10"
【讨论】:
嗨,这段代码似乎并不总是有效(例如它不适用于 N = 1:3 W 但我认为可以通过传递组合一个不包括已删除元素的不同 N 来修复它......我会试试的! 我错过了检查这些条件,但通过添加一些约束可以解决它。你也能说出 N 有多大吗? 理想情况下约为 50,但我不知道这是否可行,因为子集的可能数量为 ( 2^57 - 1) ...但是越大越好,我的代码在 20 左右严重减速,我希望至少能达到 30...以上是关于如何在加权多数投票游戏中快速找到所有最小获胜联盟?的主要内容,如果未能解决你的问题,请参考以下文章