单元测试逼近算法

Posted

技术标签:

【中文标题】单元测试逼近算法【英文标题】:Unit Testing Approximation Algorithms 【发布时间】:2011-11-15 12:26:12 【问题描述】:

我正在使用一些流行的 python 包作为基础,为图形和网络开发一个开源近似算法库。主要目标是包含针对图和网络上的 NP 完全问题的最新近似算法。这样做的原因是 1)我还没有看到一个很好的(现代)整合包来涵盖这一点,并且 2)这将是一个很好的教学工具,用于学习 NP-Hard 优化问题的近似算法。

在构建这个库时,我使用单元测试来进行完整性检查(就像任何合适的开发人员一样)。我对我的单元测试有些谨慎,因为就其本质而言,近似算法可能不会返回正确的解决方案。目前我正在手动解决一些小实例,然后确保返回的结果与之匹配,但这是不可取的,在实现意义上也不可扩展。

对近似算法进行单元测试的最佳方法是什么?生成随机实例并确保返回的结果小于算法保证的界限?这似乎有误报(那个时候测试很幸运,不能保证所有实例都低于界限)。

【问题讨论】:

如果您为 NP 完全问题生成“随机实例”,如何知道真正的答案以测试边界?恕我直言,您仍然需要仔细选择测试用例。选择您可以作为人类发现真正答案的案例,但对于近似算法而言,这可能会或可能不会被证明是棘手的,或者至少可以练习。这样的案例仍然可以通过编程方式生成,以便足够大以成为现实。它们不应该是随机的 扩展@Ray Toal 的评论,如果您生成了问题,则有一些很容易解决的难题;例如,分解 pq 很难,除非你已经知道 pq 因为你生成了它们。可以将类似的原则应用于您的图/网络问题吗? +1 Tom 这正是我所说的以编程方式生成已知案例的意思。我现在有点犹豫要不要添加答案,因为我不是这方面的权威;也许有人可以来这里有经验。我只是想在“随机”这个词周围竖起一面红旗。 【参考方案1】:

您需要在这里分离两个关注点。您的近似算法的质量以及这些算法实现的正确性。

测试近似算法的质量通常不适用于软件开发中使用的单元测试方法。例如,您需要生成代表问题实际规模的随机问题。您可能需要做一些数学工作来获得一些上限/下限来判断您的算法对于无法解决的大型实例的质量。或者使用具有已知或最知名解决方案的问题测试集并比较您的结果。但无论如何,单元测试对提高近似算法的质量没有多大帮助。这就是您在优化和数学方面的领域知识将有所帮助的地方。

实现的正确性是单元测试真正有用的地方。您可以在这里使用玩具大小的问题,并将已知结果(手动解决,或通过代码中仔细的逐步调试验证)与您的代码生成的结果进行比较。有小问题不仅足够,而且在这里也是可取的,这样测试可以快速运行,并且可以在开发周期中运行多次。这些类型的测试可确保整体算法得出正确的结果。它介于单元测试和集成测试之间,因为您将大部分代码作为黑盒进行测试。但我发现这些类型的测试在优化领域非常有用。我建议为此类测试做的一件事是通过随机数生成器的固定种子来消除算法中的所有随机性。这些测试应始终以确定性方式运行,并在 100% 的时间内给出完全相同的结果。 我还建议在算法的较低级别模块中进行单元测试。隔离为图形上的弧分配权重的方法,并检查是否分配了正确的权重。隔离您的目标函数值计算函数并对其进行单元测试。你明白我的意思。

另一个影响这两个方面的问题是性能。您无法可靠地测试小玩具问题的性能。还非常希望实现快速显着降低工作算法性能的变化。一旦你有了一个运行版本的算法,你就可以创建更大的测试问题,你可以在其中测量性能并将其自动化作为你的性能/集成测试。您可以不那么频繁地运行它们,因为它们会花费更多时间,但至少会在重构期间尽早通知您新引入的性能瓶颈或算法的新功能添加

【讨论】:

【参考方案2】:

检查生成的解决方案的有效性显然是第一步。

此外,一种攻击角度可以是regression testing,使用已知预期近似解的实例(例如,通过手动执行算法或使用其他人的相同算法实现获得)。

还存在具有已知(最佳)解决方案的问题实例存储库,例如用于类似 TSP 的问题的TSPLIB。也许这些可以派上用场。

如果所讨论的算法有已知的上限,那么生成许多随机实例并针对上限验证启发式解决方案可能会证明是富有成效的。如果您这样做,我会敦促您使运行可重现(例如,始终使用相同的随机数生成器和种子)。

最后一点:对于某些问题,完全随机的实例平均而言很容易找到好的近似解。具有统一且独立选择的弧权重的非对称 TSP 就是一个这样的例子。我之所以提到这一点,是因为它可能会影响您的测试策略。

【讨论】:

【参考方案3】:

您通常可以检查一些事情 - 例如,您的算法总是返回满足其约束的解决方案,即使它们不是最优的。您还应该在每一个可能的机会进行断言检查 - 这些将特定于您的程序,但可能会检查一些数量是守恒的,或者应该增加或最坏情况保持不变的东西没有减少,或者一些假定的本地最优确实是局部最优。

鉴于这些类型的检查,以及您已经提到的边界检查,我倾向于对大量随机生成的小问题运行测试,随机种子的选择方式是如果它在问题 102324 上失败您可以重复该故障以进行调试,而无需解决之前的 102323 问题。对于大量的问题,您增加了潜在错误导致明显足以使您的检查失败的错误的机会。对于小问题,您可以增加找到并修复错误的机会。

【讨论】:

以上是关于单元测试逼近算法的主要内容,如果未能解决你的问题,请参考以下文章

单元测试之Mock(Moq)

单元测试嵌入式软件[关闭]

vs2015安装与单元测试以及经过优化的算法

手撸golang 学etcd 手写raft协议之12 单元测试

您将如何对内存分配器进行单元测试?

如何用Eclipse进行单元测试