期末项目:Capacitated Facility Location Problem

题目

在这里插入图片描述
在这里插入图片描述

代码

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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值