题目
代码
import random
import math
import datetime
import os
import time
INSTANCE_NUMBER = 71
LOOP_LENGTH = 1000
MAX_TEMPERATURE = 100
MIN_TEMPERATURE = 0.5
ATTENUATION_QUOTIENT = 0.9
MAX_NUM = 100000000
class CFLP:
def __init__(self, filename): # f means facility, c means customer
self.filename = filename
self.f_num = 0
self.c_num = 0
self.f_capacity = []
self.f_open_cost = []
self.c_demand = []
self.distance_to_f = []
self.read_file()
self.f_open_list = [0]*self.f_num
self.c_allocation = []
self.total_cost = 0
self.temperature = MAX_TEMPERATURE
def read_file(self):
fp = open(self.filename)
problem_size = fp.readline().split()
self.f_num = int(problem_size[0])
self.c_num = int(problem_size[1])
for i in range(0, self.f_num):
f_info = fp.readline().split()
self.f_capacity.append(int(f_info[0]))
self.f_open_cost.append(int(f_info[1]))
while len(self.c_demand) < self.c_num:
demand_info = fp.readline().split()
for i in range(0, len(demand_info)):
self.c_demand.append(float(demand_info[i]))
distance_infos = []
while len(distance_infos) < self.f_num:
distance_info = []
while len(distance_info) < self.c_num:
temp = fp.readline().split()
for i in range(0, len(temp)):
distance_info.append(float(temp[i]))
distance_infos.append(distance_info)
for i in range(0, self.c_num):
temp_distance = []
for j in range(0, self.f_num):
temp_distance.append(distance_infos[j][i])
self.distance_to_f.append(temp_distance)
def init_alloc_c(self):
for i in range(0, self.c_num):
while True:
choose_f = random.randint(0, self.f_num-1)
if self.f_capacity[choose_f] >= self.c_demand[i]:
if self.f_open_list[choose_f] == 0:
self.total_cost += self.f_open_cost[choose_f]
self.f_open_list[choose_f] += 1
self.f_capacity[choose_f] -= self.c_demand[i]
self.total_cost += self.distance_to_f[i][choose_f]
self.c_allocation.append(choose_f)
break
def local_change_f(self): # 局部搜索版移动顾客
while True:
choose_c = random.randint(0, self.c_num-1)
choose_f = random.randint(0, self.f_num-1)
if self.c_allocation[choose_c] == choose_f:
continue
if self.f_capacity[choose_f] < self.c_demand[choose_c]:
continue
# 总花费对比
allocated_f_before = self.c_allocation[choose_c]
cost_before = self.distance_to_f[choose_c][allocated_f_before]
if self.f_open_list[allocated_f_before] == 1:
cost_before += self.f_open_cost[allocated_f_before]
cost_after = self.distance_to_f[choose_c][choose_f]
if self.f_open_list[choose_f] == 0:
cost_after += self.f_open_cost[choose_f]
if cost_before <= cost_after:
return False
self.f_capacity[allocated_f_before] += self.c_demand[choose_c]
self.f_capacity[choose_f] -= self.c_demand[choose_c]
self.f_open_list[allocated_f_before] -= 1
self.f_open_list[choose_f] += 1
self.c_allocation[choose_c] = choose_f
self.total_cost = self.total_cost - cost_before + cost_after
return True
def annealing_change_f(self): # 退火版
while True:
choose_c = random.randint(0, self.c_num-1)
choose_f = random.randint(0, self.f_num-1)
if self.c_allocation[choose_c] == choose_f:
continue
if self.f_capacity[choose_f] < self.c_demand[choose_c]:
continue
allocated_f_before = self.c_allocation[choose_c]
cost_before = self.distance_to_f[choose_c][allocated_f_before]
if self.f_open_list[allocated_f_before] == 1:
cost_before += self.f_open_cost[allocated_f_before]
cost_after = self.distance_to_f[choose_c][choose_f]
if self.f_open_list[choose_f] == 0:
cost_after += self.f_open_cost[choose_f]
# 不能退火
if cost_before <= cost_after and \
random.random() > math.exp((cost_before - cost_after)/self.temperature):
return False
self.f_capacity[allocated_f_before] += self.c_demand[choose_c]
self.f_capacity[choose_f] -= self.c_demand[choose_c]
self.f_open_list[allocated_f_before] -= 1
self.f_open_list[choose_f] += 1
self.c_allocation[choose_c] = choose_f
self.total_cost = self.total_cost - cost_before + cost_after
return True
def write_file(self, method):
if method == 1:
fp = open('Local Search/' + self.filename.split('/')[1], 'w')
elif method == 2:
fp = open('Simulated Annealing Search/' + self.filename.split('/')[1], 'w')
fp.write(str(self.total_cost) + '\n')
for i in range(0, self.f_num):
if self.f_open_list[i] != 0:
fp.write('1 ')
else:
fp.write('0 ')
fp.write('\n')
for i in range(0, self.c_num):
fp.write(str(self.c_allocation[i]) + ' ')
def LocalSearchSolve(self):
self.init_alloc_c()
print('使用局部搜索,初始分配方案花费:', self.total_cost)
for i in range(0, 100*LOOP_LENGTH):
if self.local_change_f():
print('使用局部搜索,第', i, '循环 ','花费:', self.total_cost)
self.write_file(1)
return self.total_cost
def AnnealingSolve(self):
self.init_alloc_c()
print('使用模拟退火,初始分配方案花费:', self.total_cost)
while self.temperature > MIN_TEMPERATURE:
for i in range(0, LOOP_LENGTH):
if self.annealing_change_f():
print('使用模拟退火,当前温度:', self.temperature, ',第', i, '循环 ', '花费:', self.total_cost)
self.temperature *= ATTENUATION_QUOTIENT
self.write_file(2)
return self.total_cost
def __main__():
command = input('请输入您想使用的算法:')
write_file_name = ''
if command == '1':
write_file_name = 'Local Search'
elif command == '2':
write_file_name = 'Simulated Annealing'
fp = open(write_file_name, 'a')
if os.stat(write_file_name).st_size == 0:
fp.write(''.ljust(10) + 'Result'.ljust(20) + 'Time(s)\n')
for i in range(1, INSTANCE_NUMBER+1):
filename = 'Instances/p' + str(i)
res = 0
start_time = datetime.datetime.now()
solution = CFLP(filename)
if command == '1':
res = solution.LocalSearchSolve()
elif command == '2':
res = solution.AnnealingSolve()
end_time = datetime.datetime.now()
fp.write(('p' + str(i)).ljust(10) + str(res).ljust(20) + str((end_time - start_time).seconds) + '\n')
结果
local search
Result Time(s)
p1 10468.0 0
p2 8566.0 0
p3 10095.0 0
p4 12100.0 0
p5 9901.0 0
p6 8663.0 0
p7 10365.0 0
p8 12368.0 0
p9 8836.0 0
p10 7726.0 0
p11 9583.0 0
p12 11454.0 0
p13 9875.0 0
p14 8429.0 0
p15 9804.0 0
p16 12662.0 0
p17 10581.0 0
p18 7396.0 0
p19 10921.0 0
p20 13971.0 0
p21 10197.0 0
p22 8380.0 0
p23 10700.0 0
p24 11569.0 0
p25 15791.0 0
p26 13558.0 0
p27 16148.0 0
p28 18722.0 0
p29 15286.0 0
p30 13716.0 0
p31 16532.0 0
p32 19311.0 0
p33 16470.0 0
p34 12727.0 0
p35 16456.0 0
p36 19165.0 0
p37 15635.0 0
p38 13056.0 0
p39 16449.0 0
p40 17772.0 0
p41 7158.0 0
p42 8216.0 0
p43 8084.0 0
p44 7545.0 0
p45 8151.0 0
p46 7667.0 0
p47 7001.0 0
p48 7549.0 0
p49 6209.0 0
p50 10002.0 0
p51 9738.0 0
p52 10164.0 0
p53 10849.0 0
p54 9936.0 0
p55 10103.0 0
p56 23359.0 0
p57 31983.0 0
p58 50192.0 0
p59 37773.0 0
p60 23505.0 0
p61 31218.0 0
p62 51641.0 0
p63 38067.0 0
p64 23438.0 0
p65 32198.0 0
p66 51364.0 0
p67 36808.0 0
p68 23597.0 0
p69 32359.0 0
p70 51337.0 0
p71 36390.0 0
p1
10468.0
1 1 1 1 1 1 1 1 0 1
0 2 1 6 3 0 2 4 4 1 9 3 3 2 0 1 4 0 9 7 3 4 6 4 2 5 3 5 3 5 2 6 0 3 9 4 4 1 2 4 5 0 3 5 7 0 4 0 4 0
p2
8566.0
1 1 1 1 1 1 1 1 1 1
8 8 1 6 3 0 2 4 4 1 9 0 3 2 0 3 4 0 9 7 3 8 6 4 2 5 3 5 0 5 2 6 0 3 9 4 4 3 0 4 3 0 1 5 7 0 4 0 4 1
p3
10095.0
1 0 1 1 1 1 1 0 1 1
8 2 5 6 3 8 2 4 4 5 9 0 3 2 0 3 4 0 9 4 2 8 6 4 2 5 3 5 0 5 2 6 0 3 9 4 4 3 0 4 5 8 3 5 4 3 4 0 4 0
p4
12100.0
1 1 1 1 1 1 1 1 1 1
0 8 1 6 3 8 2 4 4 1 9 8 3 2 8 3 4 0 9 7 3 4 6 4 2 5 1 5 3 5 2 6 0 3 9 4 4 3 0 4 1 8 1 5 7 0 4 0 4 0
p5
9901.0
1 1 1 1 1 1 1 1 1 1
4 8 1 6 3 8 2 4 2 1 9 8 3 2 8 3 4 8 9 7 3 8 6 7 2 5 1 5 0 5 2 6 0 0 9 4 7 3 0 4 1 8 1 5 7 0 4 0 7 3
annealing
Result Time(s)
p1 8916.0 5
p2 8027.0 6
p3 9385.0 5
p4 10765.0 5
p5 8900.0 7
p6 7821.0 7
p7 9720.0 8
p8 11291.0 8
p9 8483.0 5
p10 7626.0 5
p11 9458.0 5
p12 10427.0 5
p13 8413.0 4
p14 7137.0 4
p15 9177.0 4
p16 11054.0 4
p17 8489.0 4
p18 7125.0 5
p19 8988.0 4
p20 10896.0 4
p21 8114.0 4
p22 7154.0 4
p23 9430.0 4
p24 10614.0 4
p25 12251.0 6
p26 11037.0 6
p27 13533.0 6
p28 15707.0 6
p29 13364.0 7
p30 11900.0 6
p31 13667.0 6
p32 18616.0 6
p33 12427.0 6
p34 11287.0 6
p35 13499.0 6
p36 15006.0 6
p37 12201.0 6
p38 10986.0 7
p39 12985.0 6
p40 14985.0 6
p41 6929.0 10
p42 6542.0 8
p43 6090.0 7
p44 7177.0 9
p45 7540.0 8
p46 6385.0 6
p47 6345.0 10
p48 6288.0 9
p49 6175.0 6
p50 8973.0 10
p51 8112.0 7
p52 9393.0 9
p53 8782.0 7
p54 9018.0 11
p55 7939.0 8
p56 22751.0 5
p57 29681.0 5
p58 44197.0 4
p59 33951.0 5
p60 22665.0 4
p61 28185.0 5
p62 43615.0 5
p63 33479.0 5
p64 22357.0 5
p65 28981.0 5
p66 42186.0 5
p67 32224.0 4
p68 22920.0 5
p69 28815.0 5
p70 44530.0 4
p71 33712.0 5
p1
8916.0
1 1 1 1 1 0 1 0 1 1
2 2 1 6 3 8 2 4 4 1 9 8 3 2 8 3 4 0 9 4 3 8 6 4 2 6 1 6 0 1 2 6 0 3 9 4 4 3 0 4 3 8 1 6 4 0 4 0 4 0
p2
8027.0
1 1 1 1 1 0 1 0 1 0
0 2 1 6 3 8 2 4 4 1 4 8 3 2 8 3 4 0 6 4 3 8 6 4 2 6 1 6 0 1 2 6 0 3 2 4 4 3 0 4 2 8 1 6 4 0 2 0 4 3
p3
9385.0
1 1 1 1 1 0 1 0 1 0
2 8 1 6 3 8 2 4 4 1 4 8 3 2 8 3 2 0 6 4 3 4 6 4 2 6 1 6 0 1 2 6 0 3 4 4 4 3 0 4 3 8 1 6 4 0 2 0 4 0
p4
10765.0
1 1 1 1 1 0 1 0 1 0
8 2 1 6 3 8 2 4 4 1 4 8 3 2 0 3 2 0 6 4 3 4 6 4 2 6 1 6 0 1 2 6 0 3 4 4 4 3 0 4 3 8 1 6 4 0 2 0 4 0
p5
8900.0
1 1 1 1 1 0 1 0 1 1
8 8 1 6 1 8 2 4 4 1 9 8 0 2 8 3 2 0 9 4 3 8 6 4 2 6 1 1 0 1 2 6 0 3 9 9 4 3 0 4 1 8 1 6 4 0 9 0 4 3