Capacity Facility Location Problem

本文探讨了Capacity Facility Location Problem(CFLP),一种有容量限制的设施选址问题。文章详细介绍了使用贪心算法、局部搜索法和模拟退火法来解决此NP难问题的策略,并分析了各种方法的效果和代码实现。实验表明,局部搜索和模拟退火能提供较好的解,但模拟退火可能需要更多的时间来达到最优解。
摘要由CSDN通过智能技术生成

Capacity Facility Location Problem

CFLP

Capacity Facility Location Problem,即有容量限制的设施选址问题,更准确地说,这次解决的问题为 SSCFLP(Single Source Capacity Facility Location Problem),其对资源的分配更为严格:每个顾客只能由一个设施来服务。下面我们来更准确地描述这个问题:

  1. 给定 m 个工厂,n 个用户
  2. 每个工厂有容量 ci 、建设费用 fi ( 1 <= i <= m )
  3. 每个用户有需求 di (1 <= i <= n)
  4. 对于每个用户 i ,不同的设施 j 的服务费用不同,表示为 costij
  5. 每个用户只能由一个设施服务,即 Single Source

求建设设施和服务每一个用户的费用总和的最小值。

方案

从问题描述来看,我们大概就能看出它并不是个善茬,它没有办法像解 LeetCode 上的题一样,用上一个简单算法,就能准确地求解,而事实上,它确实也是个 NP 难问题,所以穷搜绝对是行不通的,无论时间、空间服务度都是爆炸性的。所以不妨试试人工智能课上学到的近似求解方法:爬山法、模拟退火法、遗传算法以及禁忌搜索等。在这次实验中,我将依次使用贪心算法、局部搜索法(爬山法)、模拟退火法来逐渐提高解的质量。

贪心算法

对于每个用户 i ,不同的设施 j 的服务费用不同,利用这一点,我们可以想到一个简单的贪心策略:依次遍历每个用户 m ,找到其服务费用最少的设施 i:

  • 如果设施 i 已开
    • 如果容量不足,寻找服务费用仅次于它的下一个设施 j
    • 如果容量充足,就选定 i
  • 如果设施 i 未开,找到对该用户服务费用最少且容量充足的已开设施 j
    • 如果 ( fj + costmi ) < costmj ,则选设施 i
    • 否则,选设施 j

局部搜索法

我先用上述贪心算法产生一个初始解,这样可以减少算法的收敛时间,事实上贪心算法得到的解质量很差,这也就不用担心一开始就陷入局部最优啦,不过最重要的还是怎么去配合这个初解搜索领域,我使用了 4 种邻域搜索策略:

  1. 选定两个顾客,交换他们的服务设施,邻域空间为 n(n-1)/2
  2. 选定两个顾客,然后反转他们的服务设施,例如 [1, 3, 4, 2],我选中了顾客0和顾客3,则结果为 [2,4,3,1],邻域空间为 n(n-1)/2
  3. 选定两个已开设施,交换它们的客户,邻域空间为 O(m(m-1)/2)
  4. 选定一个顾客,将其转移到其它设施(已开和未开都行)

前三种策略是在已固定建设哪些设施的情况下,对顾客选择进行优化;而最后一种则是进一步在设施选址空间上进行扩张,而在实验过程中,证明在添加第 4 种策略后,解的质量会更上一层楼!

每次随机采用其中一种策略搜索邻域,如果找到更好的解,则接收;否则更换策略,直至再无策略可用。

模拟退火

与局部搜索算法略微不同的地方在于:局部搜索不接受比当前解更差的解。模拟退火有一个跳出局部最优的机制:若搜索的解劣于当前解,以一定的概率(与温度有关,温度越高概率越大)接受该劣解。

模拟退火的框架伪代码如下:

while temperature > lower_bound
	for i=1:100
    new_solution = search()
    dcost = cost(new_solution) - cost(current_solution)
    if dcost < 0
    	current_solution = new_solution
    else 
      exp(-dcost / temperature) to receive new_solution
  temperature *= COOLING_RATE

效果

贪心只是我拿来做局部搜索或模拟退火的一个踏板,所以我们主要看看后两者的效果,因为时间不太够,模拟退火没有细致地去调参,只是根据经验去随意设置了一下,同时在跑的时候,发现如果每次搜索邻域都穷搜某种搜索策略的解空间,耗时是相当恐怖的,所以我就限制了一下。下面是每种算法跑5次,目前最优 是这15次中最优的一次,模拟退火有时不比局部搜索做得好,有可能是还未收敛,但是可以看到,有些测例都跑了10来分钟了。

如果想看最优解,请直接拉到本文的最下面。

Result(avg.) Time(s)
样例 目前最优 贪心 局部搜索 模拟退火 贪心 局部搜索 模拟退火
1 9929 16511 11579 10282 0 0 55
2 8928 12899 9803 9132 0 0 62
3 10420 18441 11604 10583 0 0 57
4 11811 22698 13116 12381 0 0 59
5 10209 17830 10561 10856 0 0 36
6 9025 12930 9679 9494 0 0 43
7 11204 20782 11726 11436 0 0 41
8 12334 23191 12833 13356 0 0 27
9 9543 13788 9849 9708 0 0 66
10 8778 11172 9102 8909 0 0 72
11 10221 20501 10468 10308 0 0 70
12 11397 21717 13049 11665 0 0 65
13 9271 17143 10588 9890 0 0 71
14 8113 12419 9001 8659 0 0 78
15 9955 16778 11502 10543 0 0 78
16 11805 23752 12232 12352 0 0 75
17 9297 18344 9993 9698 0 0 78
18 8482 12005 8808 8805 0 0 73
19 9804 18851 11202 10555 0 0 78
20 11890 22479 12402 12540 0 0 59
21 8826 16099 10114 9064 0 0 87
22 8375 11524 8859 8608 0 0 77
23 9956 17018 10803 10206 0 0 77
24 11015 22259 11794 11352 0 0 88
25 11630 18366 12073 13346 0 3 402
26 10575 17971 11573 12029 0 3 398
27 12675 18773 12795 13816 0 3 369
28 14642 25728 16824 16232 0 3 332
29 12630 21995 12932 13820 0 4 378
30 12109 17967 12658 12762 0 4 356
31 13628 27093 13765 15131 0 4 435
32 16054 29694 16129 20256 0 4 192
33 11620 17118 11647 14072 0 3 296
34 10928 17622 12332 11658 0 3 406
35 12200 17141 12286 15068 0 4 317
36 14878 22775 16029 16852 0 4 290
37 11120 15844 11120 13157 0 3 348
38 11297 15195 11361 12511 0 3 325
39 11901 17114 11902 13210 0 3 427
40 13717 24008 13752 15440 0
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值