r - 从矩阵中提取总和最大的元素而不重复行或列的算法?
问题描述
我有一个数字矩阵,我需要提取具有最大可能总和的元素集,但必须遵守不能有 2 个元素来自同一行或同一列的约束。是否有任何有效的算法,并且是否有该算法的 R 实现?
例如,如果矩阵是(使用 R 的矩阵表示法):
[,1] [,2] [,3]
[1,] 7 1 9
[2,] 8 4 2
[3,] 3 6 5
那么唯一解是[1,3], [2,1], [3,2]
,它提取数字 9、8 和 6,总共 23。但是,如果矩阵是:
[,1] [,2] [,3]
[1,] 6 2 1
[2,] 4 9 5
[3,] 8 7 3
那么有3个同样好的解决方案:1,8,9;3,6,9; 和 5,6,7。这些加起来是18。
补充说明:
- 如果有多个同样好的解决方案,我需要找到所有解决方案。(能够找到几乎一样好的其他解决方案也很有用,但不是必需的。)
- 矩阵元素都是非负的,其中许多将为零。每行和每列将包含至少 1 个非零元素。
- 矩阵可以包含重复的元素。
- 矩阵不必是正方形的。它的行数可能多于列数,反之亦然,但约束始终相同:任何行或列都不能使用两次。
- 这个问题也可以重新表述为在二分图的两半之间找到一个最大得分的边集,而无需重新使用任何节点。
- 如果它有帮助,您可以假设存在一些小的固定 k,使得没有行或列包含超过 k 个非零值。
如果有人好奇,矩阵的行代表要标记的项目,列代表标签,每个矩阵元素代表为项目分配标签的“一致性分数”。我想以最大化总一致性的方式将每个标签分配给一个项目。
解决方案
这里有 2 个选项:
1)将此作为一个优化问题来处理,其中目标函数是最大化所选择的元素的总和,受限于每行和列不能被多次选择的约束。
样本数据:
set.seed(0L)
m <- matrix(sample(12), nrow=4)
#m <- matrix(sample(16), nrow=4)
m
[,1] [,2] [,3]
[1,] 9 2 6
[2,] 4 5 11
[3,] 7 3 12
[4,] 1 8 10
代码:
library(lpSolve)
nr <- nrow(m)
nc <- ncol(m)
#create the indicator matrix for column indexes
colmat <- data.table::shift(c(rep(1, nr), rep(0, (nc-1)*nr)), seq(0, by=nr, length.out=nc), fill=0)
#create indicator matrix for row indexes
rowmat <- data.table::shift(rep(c(1, rep(0, nr-1)), nc), 0:(nr-1), fill=0)
A <- do.call(rbind, c(colmat, rowmat))
#call lp solver
res <- lp("max",
as.vector(m),
A,
rep("<=", nrow(A)),
rep(1, nrow(A)),
all.bin=TRUE,
num.bin.solns=3)
样本输出:
which(matrix(res$solution[1:ncol(A)], nrow=nr)==1L, arr.ind=TRUE)
row col
[1,] 1 1
[2,] 4 2
[3,] 3 3
2)以上导致了一种贪婪的启发式方法来选择最大的元素并消除所选的行和列,然后在较小的矩阵上重复:
v <- integer(min(nc, nr))
allix <- matrix(0, nrow=length(v), ncol=2)
for (k in seq_along(v)) {
ix <- which(m == max(m), arr.ind=TRUE)
allix[k,] <- ix
v[k] <- m[ix]
m <- m[-ix[1], -ix[2], drop=FALSE]
}
v
#[1] 12 9 8
但这不会导致多种解决方案,因此不会进一步发展以提取索引。
推荐阅读
- javascript - 如何从依赖包中提取函数并保存在本地?
- javascript - chrome.storage.sync 的替代方案,可以在一个密钥中存储超过 8kb
- hadoop - Databricks 中的 ABFS 驱动程序如何读取 Azure Data Lake 中的 blob?
- json - 如何在 Type Script (Angular 12) 中循环遍历这个 json 数据
- node.js - Azure Blob 存储 SAS ExpireOn 不起作用
- ag-grid - 以编程方式最大化 AG-Grid 集成范围图
- python - 检测组中每个精灵或对象的鼠标点击
- spring-boot - 如何将“上下文初始化期间遇到的异常”视为错误,而不是警告?
- python - 如何从格式不正确的 txt 文件中绘制图形?
- algorithm - 如何在类车移动机器人的路径规划中引入最小掉头次数和强制交叉约束?