# coding:utf-8
from random import choice
import numpy as np
import time
# ---------------------------------------------------#
# globals #
# #
# ---------------------------------------------------#
# greedy ---------------------------
fac_num = 0
cus_num = 0
assign_cost = [[]]
total_cost = -1
facilities = []
customers = []
assign = [[]]
# anneal ---------------------------
t = 99.0
# tabu ---------------------------
history_min_cost = 0
tabu_list = []
tabu_facilities = facilities
tabu_customers = customers
# ---------------------------------------------------#
# classes #
# #
# ---------------------------------------------------#
class Customer:
def __init__(self, id, demond, assign):
self.id = id
self.demond = demond
self.assign = assign
class Facility:
def __init__(self, id, capacity, open_cost, open):
self.id = id
self.capacity = capacity
self.open_cost = open_cost
self.open = open
class tabu_entry:
def __init__(self, fac_to, cus):
self.fac_to = fac_to
self.cus = cus
# ---------------------------------------------------#
# functions #
# #
# ---------------------------------------------------#
# greedy ---------------------------
def readFile():
global fac_num, cus_num, fac_capacity, fac_open_cost, cus_demond, assign_cost, assign
f = open('Instances/p5')
read_nums = f.readline().strip().split()
fac_num = int(read_nums[0])
cus_num = int(read_nums[1])
for i in range(fac_num):
read_cap_and_cost = f.readline().strip().split()
facility = Facility(i, float(read_cap_and_cost[0]), float(read_cap_and_cost[1]), 0)
facilities.append(facility)
for i in range(cus_num / 10):
read_cus_demond = f.readline().strip().split()
for j in range(10):
# cus_demond.append(int(read_cus_demond[j]))
customer = Customer(i * 10 + j, float(read_cus_demond[j]), -1)
customers.append(customer)
assign_cost = [[0 for i in range(cus_num)] for i in range(fac_num)]
for i in range(fac_num):
assign_cost_temp = []
for j in range(cus_num / 10):
read_assign_cost = f.readline().strip().split()
for k in range(10):
assign_cost[i][j * 10 + k] = float(read_assign_cost[k])
assign = [[0 for _ in range(cus_num)] for _ in range(fac_num)]
f.close()
def greedy():
global total_cost
# 对于每个customer
for i in range(len(assign[0])):
min_cost = -1
fac = -1
cus = -1
# 对于每个facility
for j in range(len(assign)):
# facility的剩余capacity要能满足customer的demond
if get_fac_cap(j) < customers[i].demond:
continue
temp_cost = assign_cost[j][i]
# temp_cost = temp_cost + facilities[j].open_cost
# 选择最优惠的facility
if min_cost == -1 or temp_cost < min_cost:
fac = j
cus = i
min_cost = temp_cost
# 如果没有facility能满足该customer的demond, return
if min_cost == -1:
print "false!"
return
# 选择该facility
else:
facilities[fac].open = 1
assign[fac][cus] = 1
customers[cus].assign = fac
def get_fac_cap(j):
cost = 0
for i in range(cus_num):
cost = cost + assign[j][i] * customers[i].demond
return facilities[j].capacity - cost
def get_total_cost():
cost = 0
for i in range(cus_num):
cost = cost + assign_cost[customers[i].assign][i]
for i in range(fac_num):
cost = cost + facilities[i].open_cost * facilities[i].open
return cost
def print_result():
print total_cost
for i in range(fac_num):
print facilities[i].open,
print ''
for i in range(cus_num):
print customers[i].assign,
# anneal ---------------------------
def random_choice():
customer = choice(customers)
facility_from = facilities[customer.assign]
while True:
facility_to = choice(facilities)
if customer.assign != facility_to.id and get_fac_cap(facility_to.id) >= customer.demond:
break
return customer, facility_from, facility_to
def cal_new_cost(fac_from, fac_to, cus):
global total_cost
new_cost = total_cost - assign_cost[fac_from.id][cus.id] + assign_cost[fac_to.id][cus.id]
if get_fac_cap(fac_from.id) == fac_from.capacity - cus.demond:
new_cost = new_cost - fac_from.open_cost
if fac_to.open == 0:
new_cost = new_cost + fac_to.open_cost
return new_cost
def accept(facility_from, facility_to, customer):
global total_cost
if get_fac_cap(facility_from.id) == facility_from.capacity - customer.demond:
facility_from.open = 0
facility_to.open = 1
assign[facility_from.id][customer.id] = 0
assign[facility_to.id][customer.id] = 1
customer.assign = facility_to.id
def anneal():
global t, total_cost
min_cost = total_cost
while t > 1:
for i in range(200):
# 随机选择一个customer和一个facility
customer, facility_from, facility_to = random_choice()
# 计算新的cost
new_cost = cal_new_cost(facility_from, facility_to, customer)
# 当new_cost小于当前最优解时,接受该解,或者以一定概率接受比当前解要差的解
if new_cost < min_cost or np.random.rand() < np.exp(-(new_cost-min_cost)/t):
accept(facility_from, facility_to, customer)
if new_cost < total_cost:
min_cost = new_cost
# 降温
t = t * 0.9
total_cost = min_cost
# tabu ---------------------------
def tabu():
global total_cost, history_min_cost, tabu_customers, tabu_facilities
history_min_cost = total_cost
for n in range(cus_num * fac_num * 4 / 5):
now_min_cost = 99999
fac_from = facilities[0]
fac_to = facilities[0]
cus = customers[0]
# 在当前最优解的基础上,在候选集中寻找cost更低,且不在禁忌表中(或者比历史最低cost更低)的exchange
now_min_cost, fac_from, fac_to, cus = find_best_change(now_min_cost, fac_from, fac_to, cus)
# 更新紧急表
update_tabu_list(fac_to, cus)
# 接受该更改
accept(fac_from, fac_to, cus)
# 当新的cost小于历史最低cost时,更新历史最低cost,并记录此时的facilities和customers状况
if now_min_cost < history_min_cost:
history_min_cost = now_min_cost
tabu_facilities = facilities
tabu_customers = customers
def find_best_change(now_min_cost, fac_from, fac_to, cus):
for i in range(fac_num):# 候选集
customer, facility_from, facility_to = random_choice()
new_cost = cal_new_cost(facility_from, facility_to, customer)
if new_cost < now_min_cost or i == 0:
entry = tabu_entry(facility_to, customer)
in_list = 0
for tabu in tabu_list:
if tabu.cus == entry.cus:
in_list = 1
break
if in_list == 0 or new_cost < history_min_cost:
now_min_cost = new_cost
fac_from = facility_from
fac_to = facility_to
cus = customer
return now_min_cost, fac_from, fac_to, cus
def update_tabu_list(fac_to, cus):
entry = tabu_entry(fac_to, cus)
for tabu in tabu_list:
if tabu.cus == entry.cus:
tabu_list.remove(tabu)
tabu_list.append(entry)
if len(tabu_list) > 3 + cus_num / 2:
tabu_list.pop(0)
def print_tabu():
global history_min_cost
print history_min_cost
for i in range(len(tabu_facilities)):
print tabu_facilities[i].open,
print ''
for i in range(len(tabu_customers)):
print tabu_customers[i].assign,
# ---------------------------------------------------#
# "api" #
# #
# ---------------------------------------------------#
def run_greedy():
global total_cost
print "\n-----\ngreedy\n-----"
readFile()
greedy()
total_cost = get_total_cost()
print_result()
def run_anneal():
global total_cost
print "\n-----\nanneal\n-----"
readFile()
greedy()
total_cost = get_total_cost()
anneal()
print_result()
def run_tabu():
global total_cost
readFile()
greedy()
total_cost = get_total_cost()
# print "-----\ngreedy\n-----"
# print_result()
tabu()
print "\n-----\ntabu\n-----"
print_tabu()
# ---------------------------------------------------#
# run #
# #
# ---------------------------------------------------#
start = time.time()
# run_greedy()
# run_anneal()
run_tabu()
end = time.time()
print '\n',end - start
算法概论 project | python代码
猜你喜欢
转载自blog.csdn.net/cat_xing/article/details/85181945
今日推荐
周排行