我试图编写一些haskell代码来计算给定一些输入的属性。我是通用的,因为我有一些不同的应用程序,我喜欢这种程序风格。
--some random calculation
longCalc a b c d e f g = a*b+c-d/e*f+g
我想找到结果最少的输入组合。所以我生成了一对配对列表。
allPairs = [(show [a,b,c,d,e,f,g], longCalc a b c d e f g) | a<-[1..40],b<-[1..40],c<-[1..40],d<-[1..40],e<-[1..40],f<-[1..40],g<-[1..40]]
minimum' :: Ord a => [(t, a)] -> (t, a)
minimum' [] = error "minimum of empty list"
minimum' (x:xs) = minTail x xs
where minTail currentMin [] = currentMin
minTail (m, n) (p:ps)
| n > (snd p) = minTail p ps
| otherwise = minTail (m, n) ps
现在我有一个列表,其中包含输入和答案的描述符。
bestAnswer =最低&#39; allPairs
我不确定这是进行此计算的最有效方式。
此外,我希望看到最佳答案的逐步计算。
onlyLessFunc f _ [] = []
onlyLessFunc f y (x:xs)
| f(x) < f(y) = [x] ++ onlyLessFunc f x xs
| otherwise = onlyLessFunc f x xs
此函数应生成一个列表,其中只有更好的结果才会添加到最后。
我如何才能提高效率?我目前看到我的方法使用了大量的内存(所有内容都是具体的)。
答案 0 :(得分:1)
您可以使用
提高建议minimum'
的效率
minimum' :: Ord a => [(t, a)] -> (t, a)
minimum' [] = error "minimum of empty list"
minimum' (x:xs) = minTail x xs
where minTail m@(xm, fm) (xf@(x, f): xs) | f < fm = minTail xf xs
| otherwise = minTail m xs
minTail cm [] = cm
使用一些额外的技术,我们肯定可以进一步增强它,但总的来说这不会显着提升性能。
将对内存使用产生巨大影响的第二个优化是不用allPairs
构建此类函数,但要通过列表马上进入功能。现在Haskell可以垃圾收集已经评估过的列表元素。所以我们可以用:
minimum' [([a,b,c,d,e,f,g], longCalc a b c d e f g) | a<-[1..40],b<-[1..40],c<-[1..40],d<-[1..40],e<-[1..40],f<-[1..40],g<-[1..40]]
但我们仍然不会将算法提升到约束编程和整数线性编程所能达到的水平。通常这些机制旨在利用函数中的关系,从而从计算第一个值的时刻开始限制变量的域。对于整数线性编程(ILP),通常使用称为切割平面的优化技术来完成。
至于你的第二个问题,我们再次无法在时间复杂度方面提升这一点,但我们可以通过以下方式提升绩效:
onlyLessFunc f y = go (f y)
where go _ [] = []
go fy (x:xs) | fx < fy = x : go fx xs
| otherwise = go fy xs
where fx = f x
但是,如上所述,您实际上是在尝试优化算法的错误部分。通常,最好先防止生成所有这些值。