【问题标题】:Need an algorithm approach to calculate meal plan需要一种算法方法来计算膳食计划
【发布时间】:2014-06-26 03:40:09
【问题描述】:

我无法解决一个看似简单的问题。我和我的女朋友正在尝试制定每周的膳食计划,我有一个绝妙的主意,我可以优化我们购买的东西,以最大限度地利用它来制作东西。问题是,问题并不像看起来那么容易。简而言之,问题陈述如下:

问题: 给定 100 种成分的列表和由 100 种成分中的一种或多种成分组成的 50 种菜肴的列表,找出可以产生最多菜肴数量的 32 种成分的列表。

这个问题看起来很简单,但我发现计算答案并非易事。我采用的方法是将 32 种成分的组合计算为 100 位字符串,其中设置了 32 位。然后我检查一下可以用那个配料号做哪些菜。如果菜肴的数量大于当前的最大值,我会从列表中保存。然后我计算下一个有效的成分组合并重复、重复和重复。

32 种成分的组合数量惊人!在我看来,使用我的方法计算大约需要 300 万亿年。我已经优化了代码,因此每个组合只需要 75 微秒就可以计算出来。假设我可以优化代码,我也许可以将运行时间减少到仅仅万亿年。

我认为需要一种全新的方法。我目前在 XOJO (REALbasic) 中对此进行编码,但我认为真正的问题在于方法而不是具体实现。有人对本世纪有可能完成的方法有想法吗?

谢谢,

罗恩

【问题讨论】:

  • 我发现了一个真正了不起的算法,可以使用 BASIC 在 O(1) 中计算这个,这个评论太窄了,无法包含。
  • 可能类似于this question
  • 马特,我很想看看你有什么。可以PM我看看吗?
  • 彼得,是的,这本质上是同一个问题。感谢您向我指出。我会研究一下,看看我能不能找到它。

标签: algorithm optimization combinations


【解决方案1】:

mcdowella 的分支定界解决方案将比穷举法有很大的改进,但可能仍需要几千年的时间。这种问题最好由ILP solver 解决。

假设第 i 餐的配料集由 R[i] = { R[i][1], R[i][2], ..., R[i][|R[i ]|] },你可以将问题编码如下:

  • 为每个成分 1
  • 为每餐 1
  • 对于每一餐 i,创建 |R[i]| y[i]
  • 添加所有 x[i] 之和必须为
  • 最后,目标函数应该是所有 y[i] 的总和,我们应该尝试将其最大化。

解决此问题将为所有变量 x[i] 生成赋值:1 表示应包含该成分,0 表示不应包含该成分。

我的感觉是,像 CPLEX 或 Gurobi 这样的商业 ILP 求解器可能会在几毫秒内解决像这样的 150 变量 ILP 问题;即使是像lp_solve 这样免费提供的求解器,通常很多 慢,应该没有问题。在似乎需要永远等待的不太可能的情况下,您仍然可以解决 LP 松弛问题,这将非常快(毫秒)并且会给您(a)可以准备的最大膳食数量的上限和( b) 变量值中的“提示”:虽然 x[i] 通常不会正好为 0 或 1,但接近 1 的值暗示应该包含的成分,而接近 0 的值暗示无用的成分。

【讨论】:

  • 我一直在查看 lp_solve 文档,并且已经尝试了几个小时来解决这个问题。我认为您可能正在做某事,但我对这种事情很陌生,我完全不知道如何设置输入文件来运行它。我什至不确定 lp_solve 是否接受输入文件中的矩阵和行列式。我见过的所有示例都使用单个整数变量。我会在这件事上多花点心思。你肯定给了我一些思考!
  • 好吧,我被你的符号弄糊涂了。作者 |R[i]|你的意思是R数组中的元素个数,对吧?
  • @user3777515:不确定为什么需要指定矩阵或行列式?您只需要我提到的整数变量和约束。也许我写“x[i]”把事情搞糊涂了——你通常会把你的变量命名为x1、x2、y1等。通常的文件格式(如果我记得是MPS)相当简单,但一旦你弄清楚了,你可能会发现编写脚本来生成 ILP 输入文件(来自一些更高级别的描述)更容易。是的,R[i] 表示第 i 餐的配料集合,|R[i]|表示该集合中的元素数。
  • 太棒了!我刚刚用 LP_Solver 在 0.051 秒内解决了它。你救了我几万亿年!谢谢!!!!
  • @user3777515:不客气,很高兴结果和我希望的一样快:)
【解决方案2】:

将有一个http://en.wikipedia.org/wiki/Branch_and_bound 解决方案,但获得确切答案可能太昂贵 - j_random_hacker 建议的 ILP 可能更好 - LP 松弛可能比这里提出的松弛更好的启发式,并且 ILP 求解器将得到大量优化。

基本思想是对部分解决方案树进行递归深度优先搜索,一次扩展一个。一旦递归足够远以达到完全填充的解决方案,您就可以开始跟踪迄今为止找到的最佳解决方案。如果我标记您的成分 A、B、C、D... 部分解决方案是长度

对于每个部分解决方案,您计算出该解决方案的任何后代可以达到的最高分。对此有一个准确的认识很重要。这里有一个建议 - 假设您有一个长度为 20 的部分解决方案。剩下 12 种成分可供选择,因此您可以做的最好的事情是制作所有需要不超过 12 种成分的菜肴,而不是您选择的 20 种成分到目前为止,计算出其中有多少,这是对部分解决方案的任何后代的最佳得分的一个示例。

现在,当您考虑将部分解决方案 ABC 扩展到 ABCD 或 ABCE 或 ABCF...您无需考虑 32 种成分的所有可能组合。

一旦您确定了哪些可能的扩展可能包含新的最佳答案,您的递归搜索应该继续使用这些可能的扩展中最有希望的扩展,因为这是最有可能存活的扩展到目前为止找到更好的最佳解决方案。

加快速度的一种方法是巧妙地对其进行编码,以便向上和向下递归仅意味着对现有数据结构的微小更改,您通常在向下和向上进行反向操作。

另一种方法是偷工减料。一种明显的方法是在时间用完时停下来,并寻求迄今为止在该阶段找到的最佳解决方案。另一种方法是更积极地丢弃部分解决方案。如果你到目前为止的分数是例如100 分,您可以舍弃得分不超过 110 分的部分解决方案。这加快了搜索速度,而且您知道,尽管您可能有比 100 分更好的答案,但您错过的任何问题都不会比 110 分好。

【讨论】:

  • 这是一个有趣的方法。我将不得不考虑如何实施。谢谢!
  • 最实用的方法可能是 j_random_hacker 的 ILP 方法和开源 ILP 求解器。您需要实现的只是设置 ILP 问题和一些围绕求解器的粘合代码 - 可能也更快。
【解决方案3】:

解决一些离散数学吧? here 是维基。

您也没有考虑任何有关数量的因素。例如,面粉会用于很多油炸食谱,但购买 10 磅面粉可能不是很好。对于您的解决方案所需的某些成分,成本可能过高。更不用说每样东西都有很多成分。 (牛奶、水、盐、胡椒、糖之类的东西)

实际上,这种程度的优化可能没有必要。但我不会提供关于 SO 的关系建议。

至于新的解决方案:

我建议确定很多你想做什么和用什么,然后编写一个程序来建议用其余的东西做什么。

【讨论】:

  • 感谢您将我指向该 wiki。是的,我的问题非常相似。我当然看到了这个问题与背包和旅行推销员问题之间的相似之处。你的建议肯定比我想做的更容易解决。如果一切都失败了,我可能会依靠这个。谢谢!
【解决方案4】:

为什么不按使用的菜肴数量来排列配料表呢?

当然,这更像是一个贪婪的解决方案,但它应该为您提供一些关于哪些成分最常用的线索。从中您可以编制一份可以使用前 30 种(或其他)食材烹制的菜肴列表。 此外,您还可以按缺少的食材数量订购剩余(不可烹饪)菜肴的列表,并可能尝试对其进行优化以最大限度地增加可烹饪菜肴的数量。

为了更“算法”,我认为本地搜索在这里最有希望。从一个候选解决方案开始(随机分配 32 种成分)并计算可烹饪菜肴的数量作为适应度函数。然后检查相邻状态(切换一种成分)并移动到具有最高值的状态。重复直到达到最大值。经常这样做,你应该找到一个好的解决方案。 (这将是一个简单的贪心爬山算法)

有很多本地搜索算法,你应该可以在网上找到足够多的信息。大多数情况下,您不会找到最佳解决方案(当然这取决于问题),但仍然是一个非常好的解决方案。

【讨论】:

  • 谢谢。是的,我已经尝试过你所说的按最常用的成分对列表进行排序。它确实可以更快地找到更好的解决方案,但仍然需要相同的时间来进行详尽的搜索。我一直在研究本地搜索算法,您可能会有所了解。我有很多东西要看这里!谢谢!
  • 我认为详尽的搜索在这里可能是不可行的。本地搜索似乎很有希望,但定义“良好”的邻域关系很重要。如果邻域太大,计算下一次迭代仍然需要很长时间。可能是这样:从 32 种成分的随机分配开始,并将所有未分配的成分保留在按“最常用”排序的列表中。然后,您可以将邻域定义为所有状态,其中一种分配的成分与“未分配”列表中的“最佳”成分进行切换。
  • 这意味着每次迭代有 32 个邻居状态,这应该很快就能找到一些局部最大值。您可以经常重新启动此过程以找到可能的更好解决方案。您还可以包括随机步骤(从未分配列表中选择随机成分进行切换,概率可能为 0.5)以进行更改。试验了一下,应该没问题,速度很快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 2020-04-17
相关资源
最近更新 更多