本次项目使用两种算法完成,一为遗传算法,二为贪婪算法。以下分别阐述两种算法的框架和实验结果。
遗传算法
-
约定
- N N N 表示顾客(customer) 总数
- M M M 表示设施(facility) 总数
- c i j c_{ij} cij 表示将 i i i 号顾客分配到 j j j 号设施的 cost
- C j C_j Cj 表示开放 j j j 号设施的 cost
- d i d_i di 表示 i i i 号顾客的 demand
- D j D_j Dj 表示 j j j 号设施的 capacity
-
编码方式
使用长度为 N N N 的一维数组 X X X 来表示一个可能的解,第 i ( i = 0 , 1 , ⋯   , N − 1 ) i(i=0,1,\cdots,N-1) i(i=0,1,⋯,N−1) 位数字 X i X_i Xi 表示 i i i 号顾客被分配到设施 X i X_i Xi ( X i ≤ M − 1 ) X_i \leq M-1) Xi≤M−1) 。 -
适应度函数
(1) f ( X ) = G − ( C ( X ) + ∑ j = 0 M − 1 P j ( X ) ) f(X) = G - (C(X) + \sum_{j=0}^{M-1} P_j(X)) \tag{1} f(X)=G−(C(X)+j=0∑M−1Pj(X))(1)
其中, G G G为一个足够大的常数, C ( X ) C(X) C(X)为目标函数,即总的 cost, P j ( x ) P_j(x) Pj(x)为设施 j j j 容积超出的惩罚函数。两个函数定义如下:
(2) C ( X ) = ∑ i = 0 N − 1 c i X i C(X) = \sum_{i=0}^{N-1} c_{iX_{i}} \tag{2} C(X)=i=0∑N−1ciXi(2)
(3) P j ( X ) = { α ( D j ′ − D j ) v j ′ , 当 D j ′ > D j ( D j ′ 为 j 设施中实际的总demand) 0 , 当 D j ′ ≤ D j P_j(X) = \begin{cases} \alpha(D'_j - D_j)v'_j, & \text {当$D'_j>D_j$($D'_j$ 为 $j$ 设施中实际的总demand)} \\ 0, & \text {当$D'_j\leq D_j$} \tag{3} \end{cases} Pj(X)={α(Dj′−Dj)vj′,0,当Dj′>Dj(Dj′ 为 j 设施中实际的总demand)当Dj′≤Dj(3)
这里的 α \alpha α 为惩罚系数; v j ′ v'_j vj′ 为每个设施已分配的顾客中, c o s t d e m a n d \frac {cost}{demand} demandcost最大的值。
另外, ( 1 ) (1) (1) 式若计算结果为负数,则 f ( X ) f(X) f(X) 为0。 -
初始化种群
首先,计算出每个顾客到每个设施的一个比例 v i j = c i j d i v_{ij} = \frac {c_ij}{d_i} vij=dicij,即 c o s t d e m a n d \frac {cost}{demand} demandcost 的值。
从种群的多样性考虑,将种群的大小设为设施数 M M M 的 β ( β ≥ 2 ) \beta(\beta \geq 2) β(β≥2) 倍,并且设计让每一个设施在初始种群中开放的次数至少为 β \beta β 次(让每个设施都有开放的机会)。
通过循环,生成初始种群中的每一个个体。在第 k ( k = 1 , 2 , ⋯   , β × M ) k(k=1, 2, \cdots,\beta ×M) k(k=1,2,⋯,β×M) 次循环中:- 首先开放第一个设施 t t t, t = ⌊ k − 1 β ⌋ t=\lfloor{\frac{k-1}{\beta}}\rfloor t=⌊βk−1⌋ ,然后在 t t t 号设施的前 3 个最小的 v v v 中随机选择一个分配到该设施(贪心),并开始记录当前已开放的设施的总 capacity 。
- 遍历分配每一个未被分配的顾客到一个设施中。
- 设置一个概率 p p p ,表示接下来的一个顾客将要被分配到的设施是从已开放的设施中选择还是从全体设施中选择,以此获取一个候选列表。概率 p p p 根据当前已开放的设施的总 capacity 是否大于总体顾客的 demand 来设置。
- 对要分配的顾客 i i i,从候选列表中选出一个设施 j j j,使得 v i j v_{ij} vij 对于候选列表中的那些可容纳该顾客的设施是最小的,将顾客 i i i 分配到设施 j ( X i = j ) j(X_i = j) j(Xi=j)(贪心)。若顾客 i i i 不能被分配到候选列表中的任何一个设施,则随机分配到候选列表以外的一个设施中(新开一个设施)。
这样,初始种群中的每一个个体都是合法的,并在初始化种群中应用一些贪心策略,可能会得到更好的结果。
-
选择
采用锦标赛策略(Tournament Selection),随机选择的个体数设为 2 。 -
交叉
交叉操作设计得较为简单,即随机在两个个体中选择一段进行交换。 -
变异
随机选择 n ( n = 1 , 2 , ⋯   , ⌊ N 2 ⌋ ) n(n=1,2,\cdots,\lfloor \frac N2 \rfloor) n(n=1,2,⋯,⌊2N⌋) 个顾客,按照各50%的概率将他们分别分配到已开放的设施之一或是全体设施之一。 -
产生下一代种群
将父代产生的后代和父代一起组成一个候选池,采用锦标赛策略(Tournament Selection)从候选池中一个个地选择出个体作为下一代,随机选择的个体数设为 ⌊ β × M 3 ⌋ \lfloor \frac {\beta × M}3 \rfloor ⌊3β×M⌋ ,即种群数的三分之一。 -
其他细节
- 设计总的代数为10000代。
- 每当20代后最佳结果都没有发生改变时,增加变异概率(+0.1),以期跳出局部最优。
当然,以上的一些参数数字还可以做各种调整以改进解的质量。以下的实验结果取 α = 1 \alpha=1 α=1, β = 2 \beta=2 β=2 。(这里所写的所有算法参数使得算法可能对大规模一些的测试样例有好一点点的结果)
Result | Time(s) | |
---|---|---|
p1 | 9024 | 20.61 |
p2 | 8056 | 19.53 |
p3 | 9444 | 20.37 |
p4 | 11754 | 20.56 |
p5 | 9425 | 20.13 |
p6 | 7966 | 20.57 |
p7 | 10045 | 19.98 |
p8 | 11621 | 20.58 |
p9 | 8637 | 19.89 |
p10 | 7617 | 20.32 |
p11 | 9771 | 19.90 |
p12 | 10373 | 20.10 |
p13 | 9379 | 43.32 |
p14 | 7394 | 43.53 |
p15 | 9936 | 43.42 |
p16 | 12259 | 45.25 |
p17 | 9498 | 46.36 |
p18 | 7306 | 45.54 |
p19 | 9400 | 46.45 |
p20 | 11673 | 46.13 |
p21 | 8755 | 45.58 |
p22 | 7725 | 44.22 |
p23 | 9584 | 43.19 |
p24 | 11478 | 44.03 |
p25 | 12587 | 143.66 |
p26 | 11305 | 152.75 |
p27 | 14592 | 142.35 |
p28 | 16299 | 132.92 |
p29 | 13777 | 124.52 |
p30 | 12371 | 131.54 |
p31 | 14587 | 130.54 |
p32 | 17775 | 132.95 |
p33 | 13282 | 137.83 |
p34 | 11653 | 138.18 |
p35 | 13596 | 139.97 |
p36 | 16898 | 136.84 |
p37 | 12459 | 135.75 |
p38 | 11295 | 125.29 |
p39 | 13536 | 122.03 |
p40 | 15203 | 126.16 |
p41 | 7192 | 29.29 |
p42 | 6216 | 55.43 |
p43 | 5845 | 76.63 |
p44 | 7594 | 29.28 |
p45 | 6894 | 52.86 |
p46 | 6417 | 72.98 |
p47 | 6880 | 27.68 |
p48 | 6799 | 51.53 |
p49 | 6564 | 72.77 |
p50 | 9204 | 27.91 |
p51 | 8317 | 61.33 |
p52 | 9908 | 29.70 |
p53 | 9592 | 60.13 |
p54 | 9800 | 29.79 |
p55 | 8979 | 61.95 |
p56 | 22932 | 157.19 |
p57 | 29771 | 158.61 |
p58 | 42190 | 155.72 |
p59 | 33111 | 162.50 |
p60 | 22523 | 157.12 |
p61 | 29021 | 155.06 |
p62 | 39131 | 150.16 |
p63 | 31067 | 158.76 |
p64 | 22012 | 151.67 |
p65 | 27011 | 158.99 |
p66 | 35986 | 171.32 |
p67 | 30207 | 172.71 |
p68 | 23228 | 171.35 |
p69 | 27965 | 170.76 |
p70 | 41475 | 166.52 |
p71 | 31348 | 185.35 |
贪婪算法
贪婪算法的设计较为简单,主要是为了做一定程度的对比。
首先同遗传算法一样,计算出
v
i
j
v_{ij}
vij。按照开放的cost的升序给设施排序,按序开放设施,每开放一个设施
k
k
k,按照该设施对应的
v
i
k
v_{ik}
vik 从小到大将相应的顾客分配到该设施,直到不能再分配下一个顾客(即使在这个顾客之后可能还有顾客能够被分配到该设施)。
当所有顾客都被分配到一个设施后,算法结束。
实验结果如下:
Result | Time(s) | |
---|---|---|
p1 | 16844 | 0.00105 |
p2 | 13644 | 0.00090 |
p3 | 14844 | 0.00097 |
p4 | 16044 | 0.00105 |
p5 | 13883 | 0.00129 |
p6 | 13459 | 0.00109 |
p7 | 15059 | 0.00202 |
p8 | 16659 | 0.00129 |
p9 | 14127 | 0.00095 |
p10 | 12251 | 0.00095 |
p11 | 13451 | 0.00090 |
p12 | 14651 | 0.00090 |
p13 | 13799 | 0.00156 |
p14 | 10640 | 0.00152 |
p15 | 12240 | 0.00174 |
p16 | 13840 | 0.00156 |
p17 | 13755 | 0.00179 |
p18 | 10808 | 0.00256 |
p19 | 12408 | 0.00220 |
p20 | 14008 | 0.00176 |
p21 | 16145 | 0.00163 |
p22 | 13764 | 0.00158 |
p23 | 15164 | 0.00151 |
p24 | 16564 | 0.00148 |
p25 | 52440 | 0.00969 |
p26 | 51533 | 0.00670 |
p27 | 53333 | 0.00838 |
p28 | 55133 | 0.00638 |
p29 | 38957 | 0.00910 |
p30 | 45784 | 0.00744 |
p31 | 47984 | 0.00737 |
p32 | 50184 | 0.00780 |
p33 | 64030 | 0.00669 |
p34 | 47576 | 0.00844 |
p35 | 49176 | 0.00675 |
p36 | 50776 | 0.00966 |
p37 | 102125 | 0.00717 |
p38 | 63723 | 0.00777 |
p39 | 64723 | 0.00695 |
p40 | 65723 | 0.01497 |
p41 | 10237 | 0.00170 |
p42 | 11890 | 0.00265 |
p43 | 8318 | 0.00481 |
p44 | 12283 | 0.00155 |
p45 | 11467 | 0.00256 |
p46 | 8900 | 0.00298 |
p47 | 10853 | 0.00163 |
p48 | 9897 | 0.00280 |
p49 | 8809 | 0.00428 |
p50 | 14969 | 0.00172 |
p51 | 10816 | 0.00310 |
p52 | 16277 | 0.00167 |
p53 | 16811 | 0.00302 |
p54 | 15030 | 0.00564 |
p55 | 13649 | 0.00349 |
p56 | 41900 | 0.01262 |
p57 | 46700 | 0.01061 |
p58 | 57900 | 0.01346 |
p59 | 40656 | 0.01292 |
p60 | 47208 | 0.01167 |
p61 | 50508 | 0.01255 |
p62 | 58208 | 0.01311 |
p63 | 42637 | 0.01151 |
p64 | 46891 | 0.01066 |
p65 | 49291 | 0.00990 |
p66 | 54891 | 0.00984 |
p67 | 46772 | 0.01119 |
p68 | 50104 | 0.01127 |
p69 | 53104 | 0.00906 |
p70 | 60104 | 0.00939 |
p71 | 39253 | 0.00981 |