我试图想出一个快速且合理的最优算法来解决以下TSP /类似哈密顿路径的问题:
运载工具有许多需要的拾取和下降 执行:
对于每次发货,皮卡需要在发货之前 送货。
车辆很小,包装尺寸不一。 总运载量不能超过某个上限(例如1立方 仪表)。每次交货都有截止日期。
计划员可以在中途运行,因此车辆将从已经拾取的一些工作开始,并且已经占用了一些容量。
近乎最优的解决方案应该最小化每个航路点之间的总成本(为简单起见,距离)。如果由于时间限制而不存在解决方案,我需要找到一个具有最少数量的延迟交付的解决方案。示例问题的一些说明和非最佳但有效的解决方案:
我目前正在使用贪婪的最佳首次搜索,回溯到100个分支。如果它找不到按时交付的解决方案,我会在一秒内随机生成尽可能多的数据(我可以节省的最多计算时间)并选择延迟交付次数最少的那个。我已经研究过线性编程,但不能理解它 - 加上我认为它是不合适的,因为它需要非常频繁地运行。我也尝试过需要改变游览的算法,但是由于容量限制和优先级的原因,游戏几乎总是变得无效。谁能想到一个更好的启发式方法来解决这个问题?非常感谢!
答案 0 :(得分:2)
以下是安全地改变现有可行解决方案的一些想法:
如果你是从纯粹随机生成的时间表开始,那么只需尝试所有可能的动作,贪婪地选择最佳动作,应用它然后重复直到不再有动作产生改进应该会给你带来很大的质量提升!
获得解决方案的方法非常有用,以便可以订购它们。分数的好处在于它很容易融入重要性:就像两位数字的第一个数字比第二个数字更重要一样,你可以设计分数以便更重要的事情(例如,截止日期违规)比不太重要的事情(例如总旅行时间或距离)获得更大的权重。我建议像1000 * num_deadline_violations + total_travel_time
这样的东西。 (这当然假设total_travel_time的单位将保持在1000以下。)然后我们会尽量减少这个。
我建议使用存储在min-heap中的k个解决方案(例如,k = 10000)的池,而不是采用一个解决方案并尝试上述所有可能的移动。 。这允许您在O(log k)时间内提取池中的最佳解决方案,并在同一时间插入新的解决方案。
您最初可以使用随机生成的可行解决方案填充池;然后在每个步骤中,您将在池中提取最佳解决方案,尝试所有可能的移动以生成子解决方案,并将任何比其父级更好的子解决方案插入池中。每当游泳池的大小增加一倍时,拔出第一个(即最好的)k解决方案并用它们制作一个新的最小堆,丢弃旧的。 (在堆增长到其原始大小的常量多个之后执行此步骤,这样就可以保持分摊的时间复杂度不变。)
可能会发生一些关于解决方案X的移动产生已经在池中的子解决方案Y.这浪费了内存,这是不幸的,但是最小堆方法的一个不错的特性是,当它们到达堆的前面时,你至少可以廉价地处理这些重复:所有重复都将具有相同的分数,因此它们都会出现从堆顶部提取解决方案时连续进行。因此,为了避免重复的解决方案生成重复的子代,直到几代人,只需检查堆的新顶部是否与刚刚提取的解决方案不同,并继续提取和丢弃解决方案,直到它成立为止
关于保持更糟糕解决方案的说明:看起来保留儿童解决方案可能是值得的,即使他们比他们的父母稍微差一点,事实上这可能是有用的(甚至可能是必要的绝对最佳解决方案),但这样做有一个令人讨厌的后果:它意味着它可以从一个解决方案循环到它的孩子并再次返回(或者可能是一个更长的周期)。这会浪费我们已经访问过的解决方案的CPU时间。
答案 1 :(得分:1)
您基本上将背包问题与旅行推销员问题结合起来。
这里的主要问题似乎实际上是背包问题,而不是旅行商问题,因为它有一个硬限制(最大交货量)。也许尝试将背包问题的解决方案与旅行推销员结合起来。
如果你真的只有一秒的最大计算时间,那么带回溯的贪婪算法实际上可能就是你能得到的最佳解决方案之一。