1. 程式人生 > >Capacitated Facility Location Problem貪心演算法實現

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