在C#中编写0-1背包的模拟退火算法

时间:2010-08-02 08:10:20

标签: algorithm genetic-algorithm simulated-annealing

我正在学习模拟退火算法,并对如何修改示例算法以解决0-1背包问题提出了一些问题。

我在CP上发现了这个很棒的代码:

http://www.codeproject.com/KB/recipes/simulatedAnnealingTSP.aspx

我很确定我现在理解它是如何运作的(除了整个Bolzman条件,只要我关注的是黑魔法,虽然我理解逃避局部优化并且显然这确实如此)。我想重新设计这个以解决0-1背包 - “ish”问题。基本上我将5,000个物品中的一个放入10个袋中,并且需要针对最少的未使用空间进行优化。我为解决方案分配的实际“分数”有点复杂,但与算法无关。

这似乎很容易。这意味着Anneal()函数基本相同。我必须实现GetNextArrangement()函数以满足我的需求。在TSM问题中,他只是沿着路径交换两个随机节点(即,他每次迭代都会进行非常小的更改)。

对于我的问题,在第一次迭代中,我会选择10个随机对象并查看剩余空间。对于下一次迭代,我会选择10个新的随机对象吗?或者我最好只换掉一些物体,比如它们中的一半或者甚至只有其中一个?或者我换出的物体数量应该与温度有关?这些似乎对我来说都是可行的,我只是想知道是否有人对最佳方法有一些建议(尽管我可以在代码工作后搞乱改进)。

谢谢!

麦克

2 个答案:

答案 0 :(得分:3)

使用模拟退火,您希望使邻居状态尽可能接近能量。如果邻居有更大的能量,那么它将永远不会在没有高温的情况下跳到它们 - 足够高以至于它永远不会取得进展。另一方面,如果你能提出利用低能量状态的启发式方法,那就利用它们。

对于TSP,这意味着交换相邻的城市。对于您的问题,我建议采用如下条件邻居选择算法:

  1. 如果有适合空白空间的物体,那么它总是放入最大的物体。
  2. 如果没有对象适合空白空间,则选择要替换的对象 - 但更喜欢交换相似大小的对象。
  3. 即,对象具有与其大小差异相反的概率。你可能想在这里使用类似轮盘选择的东西,切片大小类似于(1 /(size1 - size2)^ 2)。

答案 1 :(得分:2)

啊,我想我在维基百科上找到了答案。它建议转移到“邻居”状态,这通常意味着尽可能少地改变(比如在TSM问题中交换两个城市)。

来自:http://en.wikipedia.org/wiki/Simulated_annealing

“状态的邻居是在以某种特定方式改变给定状态之后产生的问题的新状态。例如,在旅行商问题中,每个状态通常被定义为特定的排列一些特定排列的邻居是通过交换一对相邻城市而产生的排列。为改变解决方案以寻找邻近解决方案所采取的行动被称为“移动”和不同的“移动”。 “给出不同的邻居。这些移动通常会导致解决方案的最小变化,如前面的示例所示,以帮助算法最大程度地优化解决方案并保留已经最优的解决方案解决方案的一部分,只影响次优部分。在前面的例子中,解决方案的各个部分是巡回的部分。“

所以我相信我的GetNextArrangement函数会想要将一个随机项替换为集合中未使用的项目。