如何对Eigen::Array进行无序的逐行近似相等比较?
问题:验证Eigen数组行无序近似相等的简洁单元测试写法
我正在为一个输出4行2列Eigen::Array的函数写单元测试,需要验证实际输出和预期结果近似相等,但行的顺序不要求一致——也就是实际结果的每一行都要能匹配预期结果里的任意一行。目前用嵌套循环实现了验证,但觉得不够简洁,想利用Eigen的any()简化,试了一段代码但编译不通过,求更优实现方式。
现有测试代码
Eigen::Array<float, 4, 2> expectedResult {{-14.1421356F, -14.1421356F}, {-28.2842712F, 28.2841712F}, {14.1421356F, 14.1421356F}, {28.2842712F, -28.284172F}}; Eigen::Array<float, 4, 2> result = myFunction(); for (int rowIndex = 0; rowIndex < 4; rowIndex++) { // 检查result的每一行是否匹配expectedResult中的某一行,顺序无关 // @todo 找更简洁的写法 bool foundMatch = false; for (int comparisonRowIndex = 0; comparisonRowIndex < 4; comparisonRowIndex++) { if (result.row(rowIndex).isApprox(expectedResult.row(comparisonRowIndex), TOLERANCE)) { foundMatch = true; } } EXPECT_TRUE(foundMatch); }
尝试的错误代码
for (int rowIndex = 0; rowIndex < 4; rowIndex++) { EXPECT_TRUE(expectedResult.rowwise().isApprox(result.row(rowIndex), TOLERANCE).any()); // 无法编译 }
错误原因
rowwise().isApprox()要求两个操作数的行数完全匹配,而result.row(rowIndex)是单行数组,和4行的expectedResult维度不兼容,导致编译失败。
简洁实现方案
方案1:利用广播+逐行比较
通过广播将单行结果扩展为和预期数组行数一致的矩阵,再逐行做近似比较,最后用any()判断是否存在匹配:
const float TOLERANCE = 1e-6f; // 根据你的需求调整容差 for (int rowIdx = 0; rowIdx < 4; ++rowIdx) { // 将当前结果行复制4行,和expectedResult逐行对比 auto diff = expectedResult.rowwise() - result.row(rowIdx).replicate(4, 1); // 每行两个元素的绝对值都小于等于容差时,该行匹配 auto rowMatches = diff.abs().rowwise().maxCoeff() <= TOLERANCE; // 只要有任意一行匹配就通过 EXPECT_TRUE(rowMatches.any()); }
方案2:生成匹配矩阵(可选,支持重复匹配校验)
如果需要确保结果的每一行都唯一匹配预期的某一行(避免结果出现重复行但预期没有的假阳性),可以生成一个匹配矩阵,再验证是否存在合法排列:
const float TOLERANCE = 1e-6f; // 生成4x4的布尔矩阵,matches[i][j]表示expectedResult第i行是否匹配result第j行 Eigen::Array<bool, 4, 4> matches = (expectedResult.replicate(1,4) - result.replicate(4,1)).abs() <= TOLERANCE; matches = matches.rowwise().all(); // 该行两个元素都满足容差才算匹配 // 验证result的每一行都能找到匹配的预期行 EXPECT_TRUE(matches.colwise().any().all()); // 可选:验证匹配关系是一个排列(每行每列仅一个匹配),避免重复匹配 Eigen::PermutationMatrix<4,4> perm; EXPECT_TRUE(matches.transpose().fullPivLu().isInvertible() && perm.linearize(matches.transpose()));
内容的提问来源于stack exchange,提问作者Emil Lundh
相关产品推荐
相关产品推荐

