Capacitated Facility Location Problem贪心算法实现

1. 问题描述

给定n个工厂和m个顾客,开工厂需要一定的费用,一个工厂有一定的容量限制,每个顾客也有一定的需求,而每个顾客要选取某个工厂也需要一定的分配费用,现在要求找出一个分配方案,把顾客分配给不同的工厂,然后在可以满足所有顾客需求的前提下让所有的花费(开工厂的花费和分配的花费)最小。

问题分析:

2. 解决思路

设集合 I  = { 1, … , m } 是所有Facilities

集合 J = { 1, …, n } 是所有Customers

对于每个Customer 都有一个 demand, d_{j},只能被一个facility提供

对于每个Facility 都有一个 capacity, b_{i},是该facility最多能提供的容量

对于每个Facility 都有一个 fixed cost, f_{i},当该facility开启的时候固定的开销

定义 c_{ij}是facility j 满足 customer i 的要求的开销

对于每个facility i ∈ I ,定义变量y_{i}

          y_{i} = \left\{\begin{matrix} 1 , if facility open & \\ 0 , if facility close & \end{matrix}\right.

对于每个facility i ∈ I ,每个customer j ∈J, 定义变量 x_{ij}

x_{ij} = \left\{\begin{matrix} 1 , if.facility.i.is.assigned.for.customer.j & \\ 0 , otherwise& \end{matrix}\right.
对于Single Source Capacitated Facility Location Problemk可以描述为如下

因为customer一般都比facility多,所以只关注customer的cost,可以制定出如下策略:

1. 遍历所有customer,对于每一个customer,将该customer安排到所有facility的cost进行从小到大排序
2.对排序好的cost进行遍历,假如该facility剩余的容量满足customer的要求,则将该customer安排到该facility

3. 代码实现

import random
import math
import matplotlib.pyplot as plt

CAPACITY = []
OPENCOST = []
ASSIGNCOST = []
OPENSTATUS = []
DEMAND = []
FACNUM = 0
CUSNUM = 0
Num = 0

#读取文件,获取各项变量
def init(filepath):
    with open(filepath, 'r') as f:
        global FACNUM
        global CUSNUM
        global CAPACITY
        global OPENCOST
        global ASSIGNCOST
        global OPENSTATUS
        FACNUM, CUSNUM = f.readline().strip("\n").split()
        FACNUM = int(FACNUM)
        CUSNUM = int(CUSNUM)
        OPENSTATUS = [0] * FACNUM
        for i in range(FACNUM):
            line = f.readline().strip("\n").split()
            CAPACITY.append(int(line[0]))
            OPENCOST.append(int(line[1]))

        for i in range(int(CUSNUM / 10)):
            line = f.readline().strip("\n").replace(' ', '').split(".")
            for j in range(10):
                DEMAND.append(int(line[j]))

        for i in range(CUSNUM):
            linetoread = int(FACNUM / 10)
            temp = []
            for j in range(linetoread):
                line = f.readline().strip("\n").replace(' ', '').split(".")
                for k in range(10):
                    temp.append(int(line[k]))

            ASSIGNCOST.append(temp)

    print(ASSIGNCOST)

def greedy():
    global CAPACITY

    capacity = CAPACITY.copy()
    openstatus = [0] * FACNUM
    totalcost = 0
    assign = [-1] * CUSNUM
    assigncost = 0
    opencost = 0

    for cus in range(CUSNUM):
    
        facIndex = []       # the facilities may be chosen
        for i in range(FACNUM):
            if capacity[i] >= DEMAND[cus]:
                facIndex.append(i)

        # ASSIGNCOST for customer i
        asforeach = ASSIGNCOST[cus]

        # ASSIGNCOST + OPENCOST for customer i
        temp = [sum(x) for x in zip(asforeach, OPENCOST)]

        # select the min cost index
        sindex = facIndex[0]
        for i in facIndex:
            if temp[i] < temp[sindex]:
                sindex = i

        openstatus[sindex] = 1
        capacity[sindex] = capacity[sindex] - DEMAND[cus]
        assign[cus] = sindex

        assigncost += asforeach[sindex]

    for i in range(FACNUM):
        opencost += openstatus[i] * OPENCOST[i]

    totalcost = assigncost + opencost

    print(assign)
    print("assignment cost: %d"%assigncost)
    print("opencost: %d"%opencost)
    print(totalcost)
    print("openstatus: {}".format(openstatus))

    return assign

运行结果

  Result Time(s)
p1 9440 0.000475
p2 8126 0.000641
p3 10126 0.000518
p4 12126 0.000599
p5 9375 0.000423
p6 8061 0.00029
p7 10061 0.001217
p8 12061 0.000298
p9 9040 0.000337
p10 7726 0.000411
p11 9726 0.000441
p12 11726 0.000364
p13 12032 0.001095
p14 9180 0.00073
p15 13180 0.000643
p16 17180 0.000682
p17 12032 0.000952
p18 9180 0.00051
p19 13180 0.000724
p20 17180 0.001145
p21 12032 0.001239
p22 9180 0.000643
p23 13180 0.000572
p24 17180 0.000571
p25 18753 0.003807
p26 15831 0.003425
p27 21031 0.002265
p28 26231 0.002439
p29 20007 0.002902
p30 16812 0.003054
p31 22212 0.00184
p32 27612 0.004533
p33 18611 0.002598
p34 15689 0.002882
p35 20889 0.003181
p36 26089 0.002619
p37 18611 0.004204
p38 15689 0.003696
p39 20889 0.00272
p40 26089 0.002611
p41 7226 0.000569
p42 9957 0.001687
p43 12448 0.001289
p44 7585 0.000704
p45 9848 0.000852
p46 12639 0.001293
p47 6634 0.000446
p48 9044 0.000963
p49 12867 0.001634
p50 10062 0.000485
p51 11175 0.000991
p52 10364 0.000545
p53 12876 0.001308
p54 10351 0.000907
p55 12383 0.001636
p56 23882 0.003144
p57 32882 0.004378
p58 53882 0.004073
p59 39121 0.003088
p60 23882 0.00407
p61 32882 0.003173
p62 53882 0.004647
p63 39121 0.003963
p64 23882 0.004642
p65 32882 0.002274
p66 53882 0.003318
p67 39671 0.005819
p68 23882 0.003292
p69 32882 0.003722
p70 53882 0.003989
p71 39121 0.00351


 

 

猜你喜欢

转载自blog.csdn.net/huang_wx/article/details/85374515