rightTrianglesOriginal = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2, a+b+c == 24]
那要看。在这种情况下,更改谓词的顺序不会改变任何实质性的东西,因此差异(如果有的话)将非常小。由于a^2 + b^2 == c^2
检查比 贵一点a + b + c == 24
,并且两个测试都过滤掉了许多值,我希望通过交换两个测试来加快速度
rightTrianglesSwapped = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a+b+c == 24, a^2 + b^2 == c^2]
但是整个计算是如此之小,以至于很难可靠地测量。一般来说,您可以通过重新排序测试和生成器来获得很大的差异,特别是交叉测试和生成器到捷径死胡同会产生巨大的影响。在这里,您可以在和生成器之间添加一个b < c
测试到快捷方式。当然,将生成器更改为更有效。b
a
b <- [1 .. c-1]
- 添加谓词(其他谓词暗示)会影响性能吗?(例如
a > b, c > a, c > b
?)?
是的,但通常很少,除非谓词的评估成本异常昂贵。在上面,如果谓词成立,您将对隐含的第三个谓词进行不必要的评估。在这里,谓词对于标准数字类型的计算成本很低,并且不经常评估(大多数候选三元组较早失败),因此几乎无法衡量影响。但这是额外的工作——编译器不够聪明,无法消除它——因此需要额外的时间。
- 根据谓词 (1)
a > b
和 (2)制作元组列表,c > a
然后进一步应用 a^2 + b^2 = c^2 是否会提高整体性能?
那要看。如果你把一个谓词放在一个可以捷径的地方,那将提高性能。使用这些谓词需要重新排序生成器(获取a
before b
,因此您可以在 上捷径c > a
)。比较的计算成本也比 低一些a^2 + b^2 == c^2
,所以即使测试的总数增加(后一种条件比前一种情况淘汰了更多的三倍),它仍然可以提高性能先进行更便宜的测试(但做最有区别的先测试也可能是更好的策略,即使它们更昂贵,也取决于成本和功耗之间的关系)。
(a,b,c)
如果我们更改参数位置,例如或,会对性能产生影响(c, b, a)
吗?
基本上,这不会产生任何可衡量的影响。
- 如果需要如此重的排列和组合,在现实生活应用中的可取策略是什么——我们是否应该(尽可能)存储预先计算的答案以供下次使用以提高性能或其他?
那要看。如果计算复杂并且结果很小,最好将结果存储起来以供重用。如果计算成本低且结果大,则最好重新计算。在这种情况下,毕达哥拉斯三元组的数量很少,计算也不是很便宜,因此存储以供重用可能是有益的。
rightTriangles10 = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2, a > b , c > a]
几乎立即给出结果。
rightTriangles100 = [ (a,b,c) | c <- [1..100], b <- [1..100], a <- [1..100], a^2 + b^2 == c^2, a > b , c > a]
在几分钟内给出结果。
rightTriangles1000 = [ (a,b,c) | c <- [1..1000], b <- [1..1000], a <- [1..1000], a^2 + b^2 == c^2, a > b , c > a]
好吧,要检查的三元组的数量在限制中是三次方,因此将限制增加 10 倍会使要检查的三元组数量增加 1000 倍,运行时间的因素大致相同,可能是由于更大的内存要求,略大。因此,甚至没有编译,更不用说优化的代码,
ghci> [ (a,b,c) | c <- [1..100], b <- [1..100], a <- [1..100], a^2 + b^2 == c^2, a > b , c > a]
[(4,3,5),(8,6,10),(12,5,13),(12,9,15),(15,8,17),(16,12,20),(24,7,25),(20,15,25),(24,10,26)
,(21,20,29),(24,18,30),(30,16,34),(28,21,35),(35,12,37),(36,15,39),(32,24,40),(40,9,41)
,(36,27,45),(48,14,50),(40,30,50),(45,24,51),(48,20,52),(45,28,53),(44,33,55),(42,40,58)
,(48,36,60),(60,11,61),(63,16,65),(60,25,65),(56,33,65),(52,39,65),(60,32,68),(56,42,70)
,(55,48,73),(70,24,74),(72,21,75),(60,45,75),(72,30,78),(64,48,80),(80,18,82),(84,13,85)
,(77,36,85),(75,40,85),(68,51,85),(63,60,87),(80,39,89),(72,54,90),(84,35,91),(76,57,95)
,(72,65,97),(96,28,100),(80,60,100)]
(2.64 secs, 2012018624 bytes)
限制 1000 的预期时间约为 45 分钟。对数据使用一些约束,我们可以做得更快:
ghci> length [(a,b,c) | c <- [2 .. 1000], b <- [1 .. c-1], a <- [c-b+1 .. b], a*a + b*b == c*c]
881
(87.28 secs, 26144152480 bytes)