2011-03-06 80 views
1

我正在写一个模拟退火程序,并且在调试时遇到了一些麻烦。任何的建议都受欢迎。如何更快地调试蒙特卡罗仿真?

首先,输出是不确定的,所以我已经运行了一百次,查看平均值和标准偏差。

但是,它需要年龄和年龄(> 30分钟)才能完成一个测试用例。

通常,我会尽量减少输入,但减少迭代的次数会直接降低结果的准确性,但这种方式不是完全可预测的。例如,冷却时间表是按照迭代次数缩放的指数衰减。减少单独运行的次数使输出非常不可靠(我试图追捕的一个错误是运行之间的巨大差异)。我知道不成熟的优化是所有邪恶的根源,当然,在程序正确之前进行优化肯定还为时过早,但我认真考虑重写这是一种更快的语言(Cython或C),知道我为了提交,我们必须将其移回Python。

那么,有没有什么办法比我现在有更好的测试模拟退火算法?还是应该在测试之间进行其他工作?

信息披露:这是课程作业的作业,但我并没有要求您帮助我进行实际的模拟。

+0

你可以做很多日志记录,然后手动运行,直到找到出错的地方。 – 2011-03-06 00:54:08

+0

你可能想要分析你的代码,看看什么是如此之慢。并提出一些测试用例,并确保它们在尝试复杂之前正在工作。从小开始建立。 – madmik3 2011-03-06 00:55:30

+0

我已经尝试了日志记录和单元测试。看起来进入主退火循环的所有功能都是正确的,而且从记录来看,它看起来像我正在做出我打算做出的决定。问题似乎在于我不明白产生候选人和冷却计划的正确策略,导致快速收敛,所以我正在测试一系列不同的策略。我已经考虑将单独运行并行化,但是我想知道这是否值得付出努力。 – Wang 2011-03-06 01:10:38

回答

0

这里有一些调试技巧,我从执行元启发式算法(如模拟退火和禁忌搜索)在Drools Planner学会(Java,开源):

  1. 它支持不同environmentMode S(DEBUGREPRODUCIBLE (默认)和PRODUCTION)。在模式DEBUGREPRODUCIBLE,所有代码使用相同的随机实例和Random实例seed是固定的。因此,两次运行禁忌搜索实施给出完全相同的动作,步骤和得分。模拟退火实现依赖于时间梯度,所以根据当时的CPU,可能会有细微的差异。注意:这并不能让你免于统计运行,但它确实可以重现一次运行。
  2. 良好的可读日志。使用日志级别。不要记录太冗长。
  3. 我们的构建服务器(Hudson)保留了性能统计信息。
  4. 有一个Benchmarker工具输出图表,使其更容易看到算法做了什么。所以,不要只看结果,还要看看它是如何到达那里的。它起初可能做得很好,但之后会陷入局部最佳状态。

Benchmarker summary

Benchmarker detail

它的东西,喜欢哪给你什么算法中的实际发生的洞察力。

另外,请参阅我的博客文章Simulated Annealing