You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于Haskell实现输入组合寻优:求解计算式最小输出值

解决Haskell寻优问题:找到longCalc的最小输入组合

嘿,我来帮你搞定这个寻找最小计算结果的问题!首先咱们先理清楚你已经写的代码,然后一步步完善寻优逻辑——顺便说一句,直接生成allPairs这种超大列表可不太现实,后面我会给你更高效的方案。

先回顾你的基础代码

你已经定义了计算函数和所有可能输入的配对列表:

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]]

方案1:基于现有列表的寻优(注意:仅理论可行)

如果非要用allPairs来找最小值,Haskell的Data.List模块里的minimumBy函数正好能派上用场。我们只需要比较每个元组的第二个元素(也就是计算结果):

首先导入必要的模块:

import Data.List (minimumBy)
import Data.Ord (comparing)

然后定义寻优函数:

findMinInput :: (String, Double)
findMinInput = minimumBy (comparing snd) allPairs

为什么说理论可行?

40^7等于163840000000个元素——这可是百亿级别的列表,你的内存根本装不下,运行起来直接就会崩溃。所以这个方法只能用来理解思路,实际用不了。

方案2:高效遍历跟踪最小值(推荐实际使用)

我们可以不用生成整个列表,而是逐个遍历所有输入组合,只保留当前找到的最小值,这样内存占用几乎是常数:

findMinEfficient :: (String, Double)
findMinEfficient = go 1 1 1 1 1 1 1 ("", 1/0)  -- 初始最小值设为无穷大
  where
    -- 递归遍历所有输入组合
    go a b c d e f g currentMin
      | a > 40 = currentMin  -- 所有a遍历完,返回结果
      | b > 40 = go (a+1) 1 1 1 1 1 1 currentMin  -- 当前b遍历完,a+1
      | c > 40 = go a (b+1) 1 1 1 1 1 currentMin
      | d > 40 = go a b (c+1) 1 1 1 1 currentMin
      | e > 40 = go a b c (d+1) 1 1 1 currentMin
      | f > 40 = go a b c d (e+1) 1 1 currentMin
      | g > 40 = go a b c d e (f+1) 1 currentMin
      | otherwise =
          let currentVal = longCalc a b c d e f g
              -- 比较当前值和已存最小值,更新最小值
              newMin = if currentVal < snd currentMin
                       then (show [a,b,c,d,e,f,g], currentVal)
                       else currentMin
          in go a b c d e f (g+1) newMin

这个版本会逐个计算每个输入组合的结果,只记住最小的那个,不会占用大量内存,运行起来流畅很多。

方案3:数学分析直接找最优解(最高效)

其实咱们可以先分析longCalc的表达式,直接推导出最小值对应的输入:
把表达式整理一下:

longCalc = a*b + c - (d*f)/e + g

要让整个结果最小,我们需要:

  • a*b尽可能小:a和b都取最小值1,得到1*1=1
  • c尽可能小:取最小值1
  • (d*f)/e尽可能大:d和f取最大值40,e取最小值1,得到(40*40)/1=1600
  • g尽可能小:取最小值1

代入计算:1 + 1 - 1600 + 1 = -1597,对应的输入组合是[1,1,1,40,1,40,1]

这种方法完全不需要遍历,直接就能得到结果,效率最高!

内容的提问来源于stack exchange,提问作者uglyoldbob

火山引擎 最新活动