【发布时间】:2022-01-12 17:56:41
【问题描述】:
问题:
假设我有集合 A 和集合 B 不一定大小相等。
然后我想为A 中的每个a 和B 中的每个b 找到一组最高得分对。
主要规定A中的每个a和B中的每个b只能使用一次。所以如果score(a1, b1) == score(a1, b2)我们只能保留两个分数之一。
下面是一个包含相似度矩阵的具体示例。每一行代表集合 A 的一个元素,每一列是集合 B 的一个元素。所以M[i][j] = score(a_i, b_j)
new double[][]{{1, 4, 1, 1}, // 4 occurs twice in a column
{3, 1, 2, 3}, // 3 occurs twice in a row
{1, 4, 1, 1}};
我们首先会说 (0,1) 包含第 1 行中的最高分。因此 a_0 和 b_1 不再可用于任何匹配。
接下来,我们会说(1, 0) 或(1, 3) 包含第2 行中的最高分。由于两者都是公平游戏,我们选择(1, 0)。现在,a_1 和 b_0 是禁区。
最后,我们看到第三行的最高分是(2, 1)。但是因为B 中的b_1 是针对的,所以我们必须选择别的东西。我们改为选择(2, 3)。
所以我们没有重复的成对最高得分对是(a_0, b_1), (a_1, b_0), (a_2, b_3)。
这是我尝试过的:
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.RealVector;
import org.apache.commons.math3.util.Pair;
public static double rankBySimilarity(Array2DRowRealMatrix simMatrix) {
Set<Integer> rowIdxs =
IntStream.range(0, simMatrix.getRowDimension()).boxed().collect(Collectors.toSet());
Set<Integer> colIdxs =
IntStream.range(0, simMatrix.getColumnDimension()).boxed().collect(Collectors.toSet());
Set<Pair<Integer, Integer>> bestScoreIdxs = new HashSet<>();
for (int row : rowIdxs) {
RealVector rowVec = simMatrix.getRowVector(row);
int col = rowVec.getMaxIndex();
bestScoreIdxs.add(new Pair<>(row, col));
rowIdxs.remove(row);
colIdxs.remove(col);
if (rowIdxs.isEmpty() || colIdxs.isEmpty()) {
break;
}
}
double score = 0;
for (Pair<Integer, Integer> coord : bestScoreIdxs) {
int x = coord.getFirst();
int y = coord.getSecond();
score += simMatrix.getEntry(x, y);
}
return score / bestScoreIdxs.size();
}
但是,这会引发异常,因为我正在迭代并同时更改集合。我已阅读并理解该错误。我想不出一个有效的替代方案。
也许继续使用相似矩阵不是一个好主意?欢迎任何建议或提示。
编辑 我刚刚用 rowIdxs.iterator() 替换了 rowIdxs 并逐步调试了我的调试器。上面的逻辑就算不抛出异常也不行。
【问题讨论】:
-
我不完全理解您在寻找什么。 cowIdxs 上没有循环,那么您如何比较所有内容?我也没有看到 score 方法,当你让它听起来像是某种计算时,我会预料到的。也没有关于什么是“最好成绩”的比较。您只需将它们加在一起即可。
-
@Aldert 没有分数方法,因为分数是在相似度矩阵中预先计算的(正如我在问题中提到的,并且方法签名很明显)。谢谢。