伊莉討論區

標題: 訂貨及存缺貨機制 [打印本頁]

作者: garylai1990    時間: 2010-4-24 03:02 AM     標題: 訂貨及存缺貨機制

本帖最後由 garylai1990 於 2010-4-24 03:04 AM 編輯

問題背景與概述
假設有一3C 量販店之門市販售自家品牌電腦,其每日的顧客需求量(D)為一個隨機整數(譬如昨天無顧客購買、今天有3 台電腦的需求、明天有2 台電腦需求等等),且根據歷史銷售記錄可歸納出不同需求量之機率分佈情況(譬如表1)。

表1 每日需求與機率分配
每日需求(台)          2        5        4       6     3
機率                   15%  35%  25% 15% 10%

站在增加營收的立場上,商家會希望盡可能滿足顧客需求,亦即希望每天皆可將店中的電腦完全清空賣出。若每日在打烊盤點時尚有部分電腦在庫(此即為存貨),則每台在庫之電腦必須付出一筆「單位存貨成本(H)」;反之,若盤點時發現當天有顧客無法當場取貨(此即為缺貨),則每筆無法完成的買賣每延交貨一日必須付出一筆「單位缺貨成本(S)」。存貨與缺貨其實是一體兩面,可用以下公式(1)計算之:

I[t] = I[t-1] + O[t-L] – D[t], t=1,...,T (1)

其中t 為時間(日為單位),I[t]、O[t]、D[t]分別代表第t 日的存貨(或缺貨,為當日打烊前盤點結果)、訂貨量(為當日開店前決定)、預測需求量。當I[t]>0 時,代表第t 天有存貨;當I[t]<0 時,代表第t 天有缺貨;當I[t]=0 時,代表第t 天無存(缺)貨。而L 代表每次訂貨時送出訂單至收到貨品中間所耗費的「前置時間」;舉例來說,每筆門市之訂貨自第t 日早上送出訂單至其上游工廠製造後,會於第t+L 日早上接收到該批貨物。本作業假設I[0]為給定,而I[1],...,I[T]必須依式(1)推導而得;O[-L],...,O[0]皆為0,而O[1],...,O[T]必須依本作業規劃的四種訂價機制( 兩種訂貨量及折扣、兩種訂貨時機) 來設定;D[0]=0,D[T+1],...,D[T+L] 皆為0,而D[1],...,D[T]由給定的需求預測趨勢依電腦亂數產生而得。
假設每次訂貨需耗費一筆訂貨成本(C),訂貨量的多寡及時機皆會影響整體營收,本作業假設在訂貨量的數量及折扣上有以下兩種機制(假設目前為第t 日, t=1,…,T):

1. O[t] = Q1,即訂購Q1單位,每單位貨品之製造成本為M1

2. O[t] = Q2 (>Q1),即訂購Q2單位,每單位貨品之製造成本為M2(<M1)

在訂貨的時機方面,本作業假設第t 日開店前(t=1,…,T)有以下兩種機制:

1. 檢 驗 I[t-1] 再扣除第t,…,t+L-1 日( 不含第t+L 日) 產生的總需求量( 即I[t-1]-D[t]-D[t+1]-…-D[t+L-1])是否小於「安全存貨(A)」。若是,則訂貨O[t] =Q2 或Q1單位;反之,O[t] = 0。!!注意!! 此機制必須於每日早上執行一次。
2. 檢驗 I[t-1]是否小於「再訂購點(R)」。若是,則訂貨O[t] = Q2 或Q1;反之,O[t] = 0。

!!注意!! 此機制一旦決定於第t 日訂貨的話,則在第t+1,…,t+L 日皆不可再訂貨。
其中,安全存貨是為了應付突發的需求,在系統中設定隨時應有的庫存量;以上兩種訂貨時機及存貨機制皆是實務上生產管理中為減少存缺貨而常見的營運手法。相關術語更詳細的解釋說明如下:
&#1048698; 每日之顧客需求(Demand,D[ ]):
每一天的電腦需求量,在此題我們將其設為機率分佈已知的隨機整數,如表1 所示。

&#1048698; 單位製造成本(Manufacturing Cost,M):本題設為M1或M2
生產一台電腦的總花費。
E.g. 假設訂購4 台電腦,總共將花費4M1或4M2元製造之。

&#1048698; 單位缺貨成本(Shortage Cost,S):
在電腦已賣光無存貨的情形下,每產生一台電腦的需求隨即損失S 元。
E.g. 假設昨天已賣光電腦,而新訂的4 台電腦後天才會到,則今明兩天將無電腦可賣。
倘若今天及明天各有2 台電腦需求,則因兩天缺貨,商家將付出4S+2S=6S 元的代價。

&#1048698; 單位存貨成本(Holding Cost,H):
倉庫每存放一台電腦(過夜)會造成H 元的成本。
E.g. 假設昨天在打烊後發現尚存5 台電腦在庫,則這些(過夜)存貨將造成5H 元成本。

&#1048698; 單筆訂貨成本(Ordering Cost,C):
預估目前存貨可能無法滿足未來的需求時,將會向工廠訂貨。本題假設每天最多僅能訂一次(即一筆)貨,每次訂貨會產生C 元的成本。

&#1048698; 訂貨量(Ordering Quantity,Q):本題設為Q1或Q2

&#1048698; 前置時間(Lead Time,L):
營運者於當日早上向工廠下訂單後,至營運者收到從工廠運來的電腦前,會有一段工廠的處理時間,其中包含製造時間、運送時間…等,總共花費的時間為L 單位時間。
E.g. 假設營運者預估無法供應未來產生的需求,於是今天向工廠下訂單,預計2 天後(即於後天)才收到工廠送來的電腦,則整個前置時間為2 天。

&#1048698; 安全庫存(Safety Stock,A):
為了能降低缺貨的可能性,除了滿足事先預測可能產生的需求外,在許可範圍內為因應突然出現、所料未及的偶發需求,而多準備的存貨量A 台。
E.g. 假設預測未來三天的需求皆為20 台電腦,營運者避免市場波動性太大而產生缺貨,故在倉庫額外多放置2 台電腦,則這2 台電腦就是安全庫存量。

&#1048698; 再訂購點(Reorder Point,R):
從訂貨到收到貨物需要一段時間,避免在這段時間內因需求波動過大造成缺貨,故設置一「存貨水準」為再訂購點,也就是當存貨量低於該存貨水準(亦即,再訂購點)時,營運者將會向工廠發出訂單訂貨。
E.g. 假設前置時間為2 天,但市場波動性太大,使得營運者無法利用兩天前下訂單的策略,故設定當倉庫存貨低於10 台電腦時,則向工廠下訂單,則10 台為再訂購點。


作業目的及假設
本作業簡化現實中商家常面臨的「訂貨、存(或缺)貨」問題,以電腦程式測試模擬四種訂存貨策略對於不同的顧客需求趨勢所造成的營收差別。
假設總共欲模擬T 日(即t = 1,…,T),顧客的需求情況為已知的趨勢(在現實中可將此視為「需求預測」的結果,如表1 所示),給定期初的存缺貨情況(I[0]),假設O[0]=D[0]=0,試算營運者擬定訂存貨的數量及時機各兩種(總共四種)策略所導致的O[t]、I[t]及其引發的成本,並將最佳策略(即花費最少)的結果列印出來。

程式要求及作法
本作業大概可切割成以下三個PART:
PART1 讀輸入檔:以一函式
void initialize_p(int *T, int *K , int *i, int **d, double **p, int *M1, int *M2, int *S, int *H, int *C, int *Q1, int *Q2, int *L, int *A, int *R); 或
void initialize_r(int &T, int &K , int &i, int *&d, double *&p, int &M1, int &M2, int &S, int &H, int &C, int &Q1, int &Q2, int &L, int &A, int &R); 實作之
本問題相關資料,包括n、K、表一的機率分佈(d[k], p[k],k=0,…,K-1),及諸如M(包括M1, M2)、S、H、C、Q(包括Q1, Q2)、L、A、R 等參數必須存至一個名為「input.txt」
的文字檔。其格式定義如下:
T  10 &#1048781; T = 10:總共模擬10 日
i     2 &#1048781; I[0] = 2:期初之存缺貨量
K   5 &#1048781; K = 5:總共有5 種不同的需求值
d   2   0.15 &#1048781; d[0] = 2, p[0] = 15%:需求為2 單位的機率為15%
d   5   0.35 &#1048781; d[1] = 5, p[1] = 35%:需求為5 單位的機率為35%
d   4   0.25 &#1048781; d[2] = 4, p[2] = 25%:需求為4 單位的機率為25%
d   6   0.15 &#1048781; d[3] = 6, p[3] = 15%:需求為6 單位的機率為15%
d   3   0.10 &#1048781; d[4] = 3, p[4] = 10%:需求為3 單位的機率為10%
M  500   350 &#1048781; M1 = 500, M2 = 350:兩種不同的單位製造成本
S   400 &#1048781; S = 400
H   100 &#1048781; H = 100
C   250 &#1048781; C = 250
Q   6   12 &#1048781; Q1 = 6, Q2 = 12
L    2 &#1048781; L = 2
A   2 &#1048781; A = 2
R   5 &#1048781; R = 5

關於讀檔


    char var;     //此變數用來讀字元
    string inFileName, outFileName;


    cout<<"which file in : "; cin>>inFileName;   //開啟需讀入的檔案名稱
    cout<<"which file out : "; cin>>outFileName;   //新建立的檔案名稱


    ifstream ifs;//產生負責讀取檔案資料的物件ifs
    ofstream ofs;//產生負責將資料輸出至檔案的物件ofs


    ifs.open(inFileName.c_str());    // .c_str()是將sting轉成字元   open inFile
    ofs.open(outFileName.c_str());   // .c_str()是將sting轉成字元   open outFile


    if(!ifs)//判斷是否能開啟需讀進的檔案
    {
        cout<< inFileName << " not found."<<endl;
        exit(1);
        system("pause");
    }


    if(!ofs)//判斷是否能開啟需讀出的檔案
    {
        cout<< outFileName << " not found."<<endl;
        exit(1);
        system("pause");
    }


    while(!ifs.eof()) //讀取的檔案尚未結束
    {
        ifs>>var;       //讀每一行第一個字元
        switch (var)
        {
            case 'T':
                    ifs>>T;
                    break;


            case 'i':
                    ifs>>i;
                    break;


            case 'K':
                    ifs>>K;
                    break;


            case 'M':
                    ifs>>M1;
                    ifs>>M2;
                    break;


            case 'S':
                    ifs>>S;
                    break;


            case 'H':
                    ifs>>H;
                    break;


            case 'C':
                    ifs>>C;
                    break;


            case 'Q':
                    ifs>>Q1;
                    ifs>>Q2;
                    break;





            case 'L':
                    ifs>>L;
                    break;


            case 'A':
                    ifs>>A;
                    break;


            case 'R':
                    ifs>>R;
                    break;





            default:
                cout<<"default";
                break;
        }// switch


    }//while


    ofs.flush();      //將buffer資料寫入outFile中,並將buffer清空


    ifs.close();     //inFile關檔
    ofs.close();     //outFile關檔




    system("PAUSE");


    return 0;


此部分為我寫的讀檔,因為讀檔是初學,所以不大確定題目的意思是不是只是要把這些變數讀到程式中使用就好,還是有什麼宣告是要在這個switch裡面寫呢?





程式中必須用switch 判讀檔中各參數之值,並將之一一存入程式所定義之變數。其中,d[ ]、p[ ]為array,而其大小必須於函式中讀入、allocate memory,再回傳之。
本部分困難之處:如何用pointer 讓函式可以一次回傳多個值(包括array)?如何開檔讀檔?

PART2 以隨機亂數產生對應的顧客需求量:以一函式
int GetDemand(int K, int **d, double **p) 或int GetDemand(int K, int *&d, double *&p) 實作之
其中,K 表示所有可能的需求量種類(以表1 為例,K=5);d[ ]及p[ ]分別記錄各種需求量及其對應之機率(以表1 為例,d[0]=2, p[0]=0.15,…,d[4]=3,p[4]=0.1);而函數將回傳其中的一種需求量(即d[0]~d[4]其中一值)至D[t], t=1,…,T。
圖1 根據隨機亂數以產生需求量
[attach]37767008[/attach]


首先,本作業要求使用系統時間一一產生T 個介於0 至1 之間的隨機實數,再針對所產生的每個隨機實數找出其所對應的顧客需求量,存入D[t], t=1,…,T 中(D[0]先設為0,D[T+1],…,D[T+L]亦設為0)。其對應方式可用表1 及圖1 解釋之:舉例來說,表1 的5 種機率分配分別可對應到圖1 中 [0,0.15)、[0.15,0.5)、[0.5,0.75)、[0.75,0.9) 、[0.9,1]等5 段區間(可由各區間的長度來想其原因)。因此,若所產生的亂數值為0.08,則應回傳2;同理,若所產生的亂數值為0.88,則應回傳6。


!!注意!! 雖然以上我們用D[T+1],…,D[T+L]設為0 來說明時間超過T 的需求不用處理,其實D[]這個array 只要宣告其大小為T+1(即=0,1,…,T),對於超過T+1 的部分一律以程式將之歸零即可。同理,在第一頁中提及的O[-L],...,O[-1]亦可用類似手法處理,不必煩惱如何設定index 為負數的array。

int GetDemand (int K,int **d,double **p)
{
    int *d;
    d=new int [K];
   
    srand(time(NULL));
    for (int i=1;i<K;i++)
    {
        if(rand()/RAND_MAX<=0.15)
             {
             }
        
    }
}



我的架構上大致為此,但內容不知道該如何下手,希望大大給予一點提示




PART3 計算各機制(P,s=0,…,3)之各天存缺貨量I[t]、訂貨量O[t]、日花費
DC[t],及其總花費:
本部分主要包括以下兩個子步驟:

PART3.1. 設定 4 種機制之相關參數及allocate memory。
PART3.2. 針對每種機制,依其運作規則計算其天存缺貨量 I[t]、訂貨量O[t]、日花費DC[t],及其總花費TCost。

PART3.1 設定4 種機制之相關參數及allocate memory

首先,必須在程式開頭宣告一個名為「Policy」的struct,其定義如下:
typedef struct {
int M, Q; //分別代表M1或M2,Q1或Q2
int *I, *O; //分別代表I[ ],O[ ]
int *DC; //代表日花費 DC[ ]
int TCost; //代表總花費
} Policy;

在main()中先宣告Policy P[4],代表 P[0],…,P[3]等四種不同的訂存貨機制:
P[0]:其M=M1, Q=Q1; 使用安全存貨量來決定訂貨時機(詳見第二頁開頭第一項)
P[1]:其M=M1, Q=Q1; 使用再訂購點來決定訂貨時機(詳見第二頁開頭第二項)
P[2]:其M=M2, Q=Q2; 使用安全存貨量來決定訂貨時機(詳見第二頁開頭第一項)
P[3]:其M=M2, Q=Q2; 使用再訂購點來決定訂貨時機(詳見第二頁開頭第二項)
之後,必須針對各種機制之I[ ],O[ ], DC[] allocate memory(這些array 的元素個別有T+1 個,t=0,1,…,T)。


PART3.2 計算各機制每天之存缺貨量I[t]、訂貨量O[t]、日花費DC[t],及其總花費TCost
首先,I[0]=i(PART1 讀檔的第2 項),而O[0]=D[0]=DC[0]=0針對第一種用安全存貨量訂貨時機之機制(即P[0]&P[2]),以函式
void GetCost1(Policy *P, int T, int K , int i, int *D, int S, int H,int C, int L, int A) 實作,計算P.I[], P.O[], P.DC[]及P.TCost
針對第二種用再訂購點訂貨時機之機制(即P[1]&P[3]),以函式void GetCost2(Policy *P, int T, int K , int i, int *D, int S, int H,
int C, int L, int R) 實作,計算P.I[], P.O[], P.DC[]及P.TCost再以函式 void Print_Policy(Policy P, int T, int *D)將P[0],…,P[3]等四種
機制中總成本最小者之D[t]、O[t]、I[t]、DC[t]列印出來,t=0,…,T。

此部分則完全沒有想法
請大大給我一點提示吧


流程綜合說明
假設輸入檔名為HW4_input.txt,其內容如第三頁所示,則程式會在讀完輸入檔之後(即PART1 結束)開始產生T 日的需求D[1],…,D[T](此即為PART2);之後,依PART3.1 將4 種機制P[0],…,P[3]的相關array 設定好,再依PART3.2 規定之函式一一依不同機制的規則計算其第t 日的O[t]、I[t]、DC[t]及其T 日總成本 TCost,最後印出如下結果:
Total Cost: P[0]= 34650, P[1]= 51800, P[2]= 31800, P[3]= 26100

Detailed info for P[3] is:
t    D    O    I    DC
----------------------------------
0    0    0    2    0
1    2  12    0    4450
2    3    0   -3    1200
3    5    0    4     400
4    4  12    0     4450
5    6    0   -6     2400
6    2    0    4     400
7    5  12   -1     4850
8    6    0   -7     2800
9    2    0    3     300
10  4  12   -1    4850
解題建議
&#1048698; 老師估計初學者必須花至少 10 天才能將本題作好,因此請同學務必早日開始。
&#1048698; 本題分成 3 個PART 處理,這3 個PART 其實可以先分開做好。由於讀檔或函式傳pointer等PART1 的要求可能對大部分初學pointer 的同學造成較大困擾,老師較建議先由PART2 及PART3 切入。最沒有困難的應該是PART3,因此老師建議同學可先將D[]當成已知的某些值,以其為基礎先將PART3 各機制的O[]、I[]、D[]之關係推導出來(譬如先在紙上將本頁「流程綜合說明」的範例之D[]當已知,自行將其餘數字推導出來),再將該推導之邏輯寫成程式;待PART3 處理完,再處理PART2 及PART1,這樣的順序可能較快。

附錄:
以下附上四種機制使用第一頁資料所產生的結果,老師建議同學可先用這個結果推導驗證自己是否理解本題的要求。先假設10 天的需求量為D=[2,3,5,4,6,2,5,6,2,4],如何可計算出O[t]、I[t]、DC[t]及TCost

P[0] (安全存貨 & Q = Q1 = 6)
t D O I DC
-----------------------------------------------
0 0 0 2 0
1 2 6 0 3250
2 3 6 -3 4450
3 5 6 -2 4050
4 4 6 0 3250
5 6 6 0 3250
6 2 6 4 3650
7 5 6 5 3750
8 6 6 5 3750
9 2 6 9 4150
10 4 0 11 1100
TCost = 34650

P[1] (再訂購點 & Q = Q1 = 6)
t D O I DC
-----------------------------------------------
0 0 0 2 0
1 2 6 0 3250
2 3 0 -3 1200
3 5 0 -2 800
4 4 6 -6 5650
5 6 0 -12 4800
6 2 0 -8 3200
7 5 6 -13 8450
8 6 0 -19 7600
9 2 0 -15 6000
10 4 6 -19 10850
TCost = 51800


P[2] (安全存貨 & Q = Q2 = 12)
t D O I DC
-----------------------------------------------
0 0 0 2 0
1 2 12 0 4450
2 3 12 -3 5650
3 5 12 4 4850
4 4 12 12 5650
5 6 0 18 1800
6 2 0 28 2800
7 5 0 23 2300
8 6 0 17 1700
9 2 0 15 1500
10 4 0 11 1100
TCost = 31800


P[3] (再訂購點 & Q = Q2 = 12)
t D O I DC
-----------------------------------------------
0 0 0 2 0
1 2 12 0 4450
2 3 0 -3 1200
3 5 0 4 400
4 4 12 0 4450
5 6 0 -6 2400
6 2 0 4 400
7 5 12 -1 4850
8 6 0 -7 2800
9 2 0 3 300
10 4 12 -1 4850
TCost = 26100


其實我不是希望大大幫我寫完作業

作業星期一就要交了

但是我還是沒有什麼想法

進度緩慢

希望大大給我一點detail的想法

謝謝^^




歡迎光臨 伊莉討論區 (http://ww2.eyny.com/) Powered by Discuz!