Capacitated Facility Location Problem
题目描述
Suppose there are n facilities and m customers. We wish to choose:
(1) which of the n facilities to open
(2) the assignment of customers to facilities
The objective is to minimize the sum of the opening cost and the assignment cost.
Note: The total demand assigned to a facility must not exceed its capacity.
input:
解题思路
算法一:贪心算法
该算法主要的贪心策略为:创建一个bool二维数组alloc,alloc[i][j]表示第i个顾客可以分配到第j个设施。在整个assignmentCost表中找到cost最小且可以被分配的assignmentCost[i][j],该cost对应顾客i和设施j,如果该设施没有足够的容量给该顾客,那么将alloc[i][j]标记为false;如果该设施有足够的容量,就将该顾客分配给该设施,并将alloc[i]标记为false。
主要代码
1 | /* |
输出
Result | Time(s) | |
p1 | 9307 | 0.005 |
p2 | 7993 | 0.004 |
p3 | 9993 | 0.005 |
p4 | 11993 | 0.004 |
p5 | 9220 | 0.005 |
p6 | 7906 | 0.004 |
p7 | 9906 | 0.005 |
p8 | 11906 | 0.004 |
p9 | 9040 | 0.005 |
p10 | 7726 | 0.004 |
p11 | 9726 | 0.006 |
p12 | 11726 | 0.004 |
p13 | 12032 | 0.007 |
p14 | 9180 | 0.007 |
p15 | 13180 | 0.008 |
p16 | 17180 | 0.009 |
p17 | 12032 | 0.009 |
p18 | 9180 | 0.009 |
p19 | 13180 | 0.008 |
p20 | 17180 | 0.009 |
p21 | 12032 | 0.009 |
p22 | 9180 | 0.008 |
p23 | 13180 | 0.008 |
p24 | 17180 | 0.008 |
p25 | 19248 | 0.054 |
p26 | 16182 | 0.054 |
p27 | 21582 | 0.055 |
p28 | 26982 | 0.054 |
p29 | 19224 | 0.054 |
p30 | 16158 | 0.072 |
p31 | 21558 | 0.053 |
p32 | 26958 | 0.056 |
p33 | 19055 | 0.054 |
p34 | 15989 | 0.054 |
p35 | 21389 | 0.055 |
p36 | 26789 | 0.056 |
p37 | 19055 | 0.052 |
p38 | 15989 | 0.053 |
p39 | 21389 | 0.054 |
p40 | 26789 | 0.055 |
p41 | 7103 | 0.009 |
p42 | 9957 | 0.015 |
p43 | 12448 | 0.018 |
p44 | 7222 | 0.009 |
p45 | 9848 | 0.016 |
p46 | 12639 | 0.018 |
p47 | 6490 | 0.009 |
p48 | 9044 | 0.015 |
p49 | 12420 | 0.018 |
p50 | 10060 | 0.011 |
p51 | 11396 | 0.019 |
p52 | 10764 | 0.012 |
p53 | 12834 | 0.022 |
p54 | 10143 | 0.011 |
p55 | 11938 | 0.022 |
p56 | 23882 | 0.087 |
p57 | 32882 | 0.083 |
p58 | 53882 | 0.081 |
p59 | 39121 | 0.084 |
p60 | 23882 | 0.081 |
p61 | 32882 | 0.082 |
p62 | 53882 | 0.082 |
p63 | 39121 | 0.083 |
p64 | 23882 | 0.082 |
p65 | 32882 | 0.082 |
p66 | 53882 | 0.084 |
p67 | 39671 | 0.085 |
p68 | 23882 | 0.082 |
p69 | 32882 | 0.08 |
p70 | 53882 | 0.081 |
p71 | 39121 | 0.082 |
算法二:模拟退火
模拟退火算法是一种通用概率演算法,用来在一个大的搜寻空间内找寻命题的最优解。其出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退火算法是一种通用的优化算法,其物理退火过程由加温过程、等温过程、冷却过程这三部分组成。
模拟退火最重要的部分就是状态产生函数,我在实现中随机采用三种邻域搜索策略的其中一种,一是随机将一位顾客转移到另一个设施,二是随机交换两位顾客,三是随机关闭一个设施。除此之外,模拟退火通常还有一些参数需要手动调整,如初温,末温,降温系数,内循环迭代次数等。
主要代码
1 | /* |
输出
Result | Time(s) | |
p1 | 8950 | 2.581 |
p2 | 8011 | 2.588 |
p3 | 9525 | 2.592 |
p4 | 11063 | 2.643 |
p5 | 9119 | 2.786 |
p6 | 7841 | 2.702 |
p7 | 9759 | 2.721 |
p8 | 11189 | 2.731 |
p9 | 8711 | 2.505 |
p10 | 7767 | 2.503 |
p11 | 9181 | 2.509 |
p12 | 10453 | 2.514 |
p13 | 9444 | 2.53 |
p14 | 8015 | 2.523 |
p15 | 9744 | 2.506 |
p16 | 11679 | 2.518 |
p17 | 9258 | 2.495 |
p18 | 7900 | 2.51 |
p19 | 10007 | 2.521 |
p20 | 11965 | 2.53 |
p21 | 8686 | 2.47 |
p22 | 7909 | 2.497 |
p23 | 9872 | 2.464 |
p24 | 11444 | 2.469 |
p25 | 15214 | 4.129 |
p26 | 14073 | 4.123 |
p27 | 16139 | 4.106 |
p28 | 18126 | 4.1 |
p29 | 15433 | 4.127 |
p30 | 13485 | 4.143 |
p31 | 16344 | 4.133 |
p32 | 19387 | 4.145 |
p33 | 14511 | 4.096 |
p34 | 12636 | 4.099 |
p35 | 15439 | 4.108 |
p36 | 17748 | 4.105 |
p37 | 13732 | 4.094 |
p38 | 13508 | 4.093 |
p39 | 15310 | 4.07 |
p40 | 17069 | 4.077 |
p41 | 6920 | 3.215 |
p42 | 6570 | 2.972 |
p43 | 6271 | 2.836 |
p44 | 7962 | 3.294 |
p45 | 7568 | 2.972 |
p46 | 7171 | 2.861 |
p47 | 7081 | 3.298 |
p48 | 6762 | 2.997 |
p49 | 6664 | 2.883 |
p50 | 9235 | 3.424 |
p51 | 8574 | 3.286 |
p52 | 9735 | 3.542 |
p53 | 10140 | 3.29 |
p54 | 9475 | 3.646 |
p55 | 8809 | 3.282 |
p56 | 29207 | 4.951 |
p57 | 36679 | 4.978 |
p58 | 48192 | 4.994 |
p59 | 38646 | 4.996 |
p60 | 29440 | 4.896 |
p61 | 33582 | 4.887 |
p62 | 43497 | 4.898 |
p63 | 35568 | 4.885 |
p64 | 29247 | 4.888 |
p65 | 33168 | 4.875 |
p66 | 42706 | 4.87 |
p67 | 34610 | 4.928 |
p68 | 28324 | 4.896 |
p69 | 34992 | 4.886 |
p70 | 43708 | 4.934 |
p71 | 35096 | 4.938 |
算法对比
- 速度:从时间上可以看出,贪心算法运行速度很快,而模拟退火因为每一轮都跑了十次,所以速度较慢。
- 结果:贪心算法的结果没有模拟退火好。尤其是贪心策略没有考虑设施开启时的费用,仅考虑分配顾客时的费用,容易陷入局部最优。而模拟退火在整个大的搜索空间求解,并通过几种邻域搜索策略,即使陷入局部最优解,也有几率可以跳出,最终得到的解与全局最优解更加接近。
实验思考
在实现贪心算法时,我后来考虑到了把设施的开启费用加进去,我将整个顾客分配损失表assignmentCost每一列加上了对应设施的开启费用,然后重复之前的贪心策略,选取费用最小的进行分配,如果分配成功且之前该设施未开启,就把assignmentCost的该列减去开启费用,即开启该设施。然而做了这个改进之后并没有之前的效果好,感觉应该是因为这种贪心策略会使得很多顾客挤在某几个设施。
在实现模拟退火时,一开始我实现了两种邻域搜索策略,即随机将一位顾客分配到另一个设施和随机交换两位顾客,在观察结果时我发现,几乎每个设施都打开了,因此我引入了第三种邻域搜索策略,即随机关闭一个设施,并使得这种操作的概率较低,这样做似乎比较容易跳出局部最优,效果挺好。
具体每个测试样例的详细结果和项目源码请参考:github