全渠道定價、庫存決策,混合整數規劃建模求解,MNL選擇模型,內附程式碼!

碼頭牛牛發表於2023-03-29

0. 寫在前面

?刊論文!模型簡單,程式碼實現更簡單,牆裂推薦!可為運籌建模提供參考,也可作為全渠道零售研究的入門資料ε٩(๑> ₃ <)۶з 全文有點長,前面先放一個博文結構和涉及內容:

  • 第一部分為文章資訊,主要介紹了這篇論文的基本資訊、發表時間、研究方向,以及對論文難度的評價。

  • 第二部分為主要內容,介紹了論文內容,幫助讀者快速瞭解論文。

  • 第三部分為模型構建,對文章中所涉及的模型進行了詳細解釋。

  • 第四部分為程式碼求解,介紹了文章的求解方法,同時附加了Python的PyLogit庫的詳解,以及我嘗試用PyLogit包去求解論文中MNL模型的程式碼。

1. 文章資訊

  • 基本資訊

    (1)發表期刊:Transportation Research Part E(10.047/Q1,運輸領域的good good刊 ૮ ´͈ ᗜ `͈ ა♡)

    (2)標題:Fulfillment and pricing optimization for omni-channel retailers considering shipment of in-store demand(為考慮店內需求發貨的全渠道零售商提供履行和定價最佳化)

    (3)作者/發表時間:Khosro Pichka, Layth C. Alwan*, Xiaohang Yue / November 2022

    (4)研究方向:運籌學,全渠道物流,定價,庫存,MNL,混合整數規劃

  • 難度評價

    (1)模型難度:★★★☆☆

    (2)程式設計難度:★☆☆☆☆

    (3)評價:適合用於入門全渠道物流/運籌排程,模型較為基礎,但又因為它很基礎,所以能給讀者帶來很多靈感和啟發。這篇文章乍一看很難,甚至附錄部分還將正文運籌模型的約束條件化為了80多條。但文中的非線性運籌模型,最後實際上化為了線性規劃模型,作者直接用了Cplex求解;其他需要程式設計的部分,作者甚至直接import了python的包去解決 ૮₍ ˙О˙₎ა

2. 主要內容

2.1 摘要、關鍵字(翻譯版)

摘要: 全渠道零售商透過電子商務渠道和不同區域的實體商店滿足各地客戶的需求。他們不僅可以透過電子履行中心來滿足他們的線上訂單,還可以透過實體店的店內庫存來滿足線上訂單。另一方面,零售商可以使用定價決策來控制線上、實體渠道的需求。我們首先透過多項式 logit(MNL)選擇模型,對客戶需求進行建模。然後,我們提出了兩個混合整數非線性規劃(MINLP)模型,透過考慮履行和定價決策來最大化總利潤。我們假設,如果商店庫存不足,電子履行中心的庫存也可以用作店內訂單的備用庫存,但僅適用於同一區域中的商店。我們還假設初始庫存有限,並且在有限的銷售範圍內沒有補貨。在第二個 MINLP 模型中,我們還允許多種運輸選項和庫存決策。透過數值實驗,我們表明全渠道零售商可以透過控制初始庫存分配並透過電子履行庫存滿足店內需求來增加利潤。

關鍵字:全渠道零售;跨渠道履行;定價;整數規劃程式設計

2.2 研究思路

  • 全渠道履行方式

    請結合下圖一起食用:

(1)每個區域都有各自的電子履行庫存和門店庫存,每個區域都有各自的實體店及實體店顧客,及透過線上渠道購買商品的線上顧客。

(2)對於同一地區,電子履行庫存可滿足該地區線上顧客的需求,門店庫存可滿足該地區實體店顧客的需求。當出現缺貨情況時,電子履行庫存和門店庫存可互補,但履行成本會發生變化。

(3)對於不同地區,當電子履行庫存發生缺貨時,可使用另一地區的電子履行庫存滿足線上顧客的需求。對於實體店顧客的需求,不能透過跨區域排程電子履行庫存來滿足;對於門店庫存,不能跨區域排程以滿足其他區域的線上或線下顧客需求。

  • 文章的研究思路

    (1)利用多項式logit(MNL)選擇模型,對客戶需求進行建模,從而預估需求量

    (2)在得到客戶需求量的基礎上,第一個模型以最大化總利潤為目標,考慮履行和定價決策。由於對庫存是短期計劃,故該模型不考慮庫存持有成本。

    (3)第二個模型在上一個模型的基礎上進行擴充,對於庫存,加入對庫存持有成本的考慮;對於線上渠道履行方式,為客戶增加常規運輸和次日達的配送選項。模型在增加上述因素後,仍以最大化總利潤為目標,考慮履行及定價決策。

    (4)文章最後透過數值實驗,表明全渠道零售商可以透過控制初始庫存分配並透過電子履行庫存滿足店內需求來增加利潤。

3. 模型建立

3.1 MNL選擇模型的建立

文中MNL選擇模型的建立,主要參考了Ben-Akiva等人1985年時發的一篇有關Travel Demand研究的論文,該篇論文連結如下:

Discrete Choice Analysis: Theory and Application to Travel Demand | SpringerLink

文中構建MNL選擇模型的目的是預估線上、線下渠道的客戶需求,以便後面建立運籌學模型。下面是文章建立MNL選擇模型的過程:

  • 假設客戶效用的隨機分量\(\xi_i\)是相互獨立的,且服從\(Gumbel\)分佈,累積分佈函式為:

    \[F(x)=P(\xi_i\leq x)=e^{-\mu(x-\eta)} \]

    其中,\(x\)是誤差隨機變數,\(\eta\)是位置引數,\(\mu\)是正比例函式。

    隨機變數\(\xi_i\)的均值和方差為:

    \[E[\xi_i]=\eta+\frac{\gamma}{\mu}Var[\xi_i]=\frac{\pi^2}{6\mu^2} \]

    其中,\(\pi\approx3.14\)\(\gamma\approx0.57\)(尤拉常數)

  • 假設全渠道網路中共有\(Z\)個地區,客戶從實體渠道購買的效用為\(U_{bz}\),從網上渠道購買商品的效用為\(U_{ez}\)(對於\(z\)地區來說,\(z\in{Z}\)

    \[U_{bz}=u_{bz}+\xi_{bz} \]

    \[U_{ez}=u_{ez}+\xi_{ez} \]

    其中,\(u_{iz}(i\in{\{b,e\}})\)是選擇\(i\)的效益,\(\xi_{iz}(i\in{\{b,e\}})\)是一個\(i.i.d. Gumber\)隨機變數,所有的\(i\)均值為0標度函式為1.

    如果客戶不從這些渠道購買,那麼此時的平均效用為0,在這個效用模型下,客戶選擇渠道\(i\)購買的效益為:

    \[\theta=\frac{e^{u_{iz}}}{\sum\limits_{j\in{\{e,b\}}}(e^{u_{jz}})+e^{u_0}}\forall{i}\in{\{e,b\}},\forall{z}\in{Z} \]

    其中,\(\theta_{iz}\)是客戶從區域\(z\)中選擇渠道\(i\)購買的機率,而\(u_0\)是客戶選擇不購買時的平均效用。

3.2 模型1的建立(短期規劃)

  • 假設選擇\(i\)的平均效用\(u_{iz}(i\in{\{e,b\}})\)是一個關於渠道價格的線性函式。

    \[u_{bz}=\beta_{0z}+\beta_{1z}P_{bz} \]

    \[u_{ez}=\beta_{0z}+\beta_{1z}P_{ez} \]

    其中,\(\beta_{0z}\)是常量,\(\beta_{1z}\)是線上或實體渠道中的價格係數,它可以透過使用歷史資料計算。\(P_{iz}(i\in{{e,b}})\)是z區域的渠道為顧客提供的價格,它是一個向量。

    價格向量函式\(P^t_z\)的計算方法如下:

    \[D^t_{bz}(P^t_z)=n^t_z×\theta_{bz}D^t_{bz}(P^t_z)=n^t_z×\frac{e^{\beta_{0z}+\beta_{1z}P_{bz}}}{e^{\beta_{0z}+\beta_{1z}P_{bz}}+e^{\beta_{0z}+\beta_{1z}P_{ez}+1}} \]

    \[D^t_{ez}(P^t_z)=n^t_z×\theta_{ez}D^t_{ez}(P^t_z)=n^t_z×\frac{e^{\beta_{0z}+\beta_{1z}P_{bz}}}{e^{\beta_{0z}+\beta_{1z}P_{ez}}+e^{\beta_{0z}+\beta_{1z}P_{ez}+1}} \]

    其中,\(n^t_z\)\(z\)區域\(t\)時間段的市場規模,\(\theta_{bz}\)\(\theta_{ez}\)分別是客戶從線下、線上渠道購買的機率。\(P^t_z=(P^t_{bz},P^t_{ez})\)是價格向量,其包括在\(z\)區域\(t\)時間中提供的線下和線上渠道價格。

3.2.1 基本假設和符號說明

  • 論文的基本假設如下:

    (1)假設客戶從線下渠道取貨的平均效用與線上渠道相同。

    (2)線下和線上渠道庫存有限。

    (3)銷售週期有限,且分為T個週期。

    (4)在週期t開始時,零售商公開每個銷售區域z中的價格向量\(P^t_z=(P^t_{bz},P^t_{ez})\),消費者可以據此瞭解到各個渠道的價格。

    (5)線下和線上渠道在區域z中的需求表示為\(D^t_{bz}(P^t_z)\)\(D^t_{ez}(P^t_z)\)

    (6)不考慮補貨和缺貨,不考慮缺貨成本。

  • 論文的符號說明如下:

  • 決策變數:\(S^t_{bwz}、S^t_{ewz}、O^t_{bwz}、O^t_{ewz}、L_{bz}、L_{ez}、P^t_{bz}、P^t_{ez}\)

3.2.2 模型建立

\[Max\sum\limits_{t\in{T}}\sum\limits_{w\in{Z}}\sum\limits_{z\in{Z}}[P^t_{bz}(S^t_{bwz}+S^t_{ewz})+P^t_{ez}(O^t_{bwz}+O^t_{ewz})]+v[\sum\limits_{w\in{Z}}(L_{bw}+L_{ew})]\\-\sum\limits_{t\in{T}}\sum\limits_{w\in{Z}}\sum\limits_{z\in{Z}}(c^s_{bwz}S^t_{bwz}+c^s_{ewz}S^t_{ewz}+c^o_{bwz}O^t_{bwz}+c^o_{ewz}O^t_{ewz}) \]

\(s.t.\)

\[\sum\limits_{w\in{Z}}(S^t_{bwz}+S^t_{ewz})\leq{D^t_{bz}(P^t_z)} \forall{z}\in{Z},\forall{t\in{T}} \]

\[\sum\limits_{w\in{Z}}(O^t_{bwz}+O^t_{ewz})\leq{D^t_{ez}(P^t_z)} \forall{z}\in{Z},\forall{t\in{T}} \]

\[L_{bw}=x_{bw}-\sum\limits_{t\in{T}}\sum\limits_{z\in{Z}}(S^t_{bwz}+O^t_{bwz})\forall{w}\in{Z} \]

\[L_{ew}=x_{ew}-\sum\limits_{t\in{T}}\sum\limits_{z\in{Z}}(S^t_{bwz}+O^t_{bwz})\forall{w}\in{Z} \]

\[P^t_z=(P^t_{bz},P^t_{ez})\forall{z}\in{Z},\forall{t\in{T}} \]

\[S^t_{bwz},S^t_{ewz},O^t_{bwz},O^t_{ewz}\geq0\forall{z}\in{Z},\forall{w}\in{Z},\forall{t\in{T}} \]

\[L_{ez},L_{bz}\geq0\forall{z\in{Z}} \]

  • 目標函式為總利潤最大化,主要分為三部分:第一部分為滿足線上、線下渠道需求的收入;第二部分為剩餘庫存的價值;第三部分為線下、線上渠道的履行成本。

  • 關於約束條件:第一、第二條約束條件為需求約束,即銷售額必須小於對應渠道的需求;第三、第四條為剩餘庫存的計算;第五條為價格向量約束;其他約束條件為變數的非負約束。

3.3 模型2的建立(長期規劃)

  • 假設客戶購買渠道為線下和線上渠道,其中線上渠道又可以選擇常規運輸次日達兩種配送方式。客戶從商店購買產品的效用與網上購買到店取貨(BOPS)的平均效用相同。基於此定義的客戶效用函式為:

    \[u_{bz}=\beta_{0z}+\beta_{1z}P_{bz}+\beta_{2z}t_{bz}+\beta_{3z}t_{bz}P_{bz} \]

    \[u_{fz}=\beta_{0z}+\beta_{1z}P_{fz}+\beta_{2z}t_{fz}+\beta_{3z}t_{fz}P_{fz} \]

    \[u_{sz}=\beta_{0z}+\beta_{1z}P_{sz}+\beta_{2z}t_{sz}+\beta_{3z}t_{sz}P_{sz} \]

    其中,\(P_{iz}\)\(t_{iz}\)\(i\in{\{b,f,s\}}\)分別代表向客戶交付的價格、時間;\(b、f、s\)分別代表實體渠道、常規運輸、次日達;\(\beta_{0z}\)是截距;\(\beta_{1z}\)分別是實體渠道、常規運輸、次日達的價格係數;\(\beta_{2z}\)是交貨時間係數;\(\beta_{3z}\)是價格與交貨時間的相互作用係數。

  • 假設有\(T\)個週期,在區域\(z\)\(t\)時間段的市場規模為\(n^t_t\)。此時,線上和實體渠道對於區域\(z\)和時間\(t\)下不同的商品配送方式選擇的需求函式遵循以下形式:

    \[D^t_{bz}(P^t_z)=n^t_z×\frac{e^{u_{bz}}}{e^{u_{bz}}+e^{u_{fz}}+e^{u_{sz}}+1} \]

    \[D^t_{fz}(P^t_z)=n^t_z×\frac{e^{u_{fz}}}{e^{u_{bz}}+e^{u_{fz}}+e^{u_{sz}}+1} \]

    \[D^t_{sz}(P^t_z)=n^t_z×\frac{e^{u_{sz}}}{e^{u_{bz}}+e^{u_{fz}}+e^{u_{sz}}+1} \]

    其中,\(P^t_z\)為價格向量函式,\(P^t_z=(P^t_{bz},P^t_{fz},P^t_{sz})\)是價格向量,在區域\(z\)時間段\(t\)中為線上和實體渠道提供的價格。

3.3.1 基本假設和符號說明

  • 論文的基本假設如下:

    (1)在週期\(t\)開始時,零售商在每個區域\(z\in{Z}\)設定價格向量\(P^t_z=(P^t_{bz},P^t_{fz},P^t_{sz})\),確定價格後,估算實體渠道的需求\(D^t_{bz}(P^t_z), D^t_{fz}(P^t_z), D^t_{sz}(P^t_z)\)

    (2)假設零售商在每個區域都有一家商店和一個電子履行中心。

    (3)不考慮缺貨成本。

    (4)店內庫存可用於滿足常規配送和次日達需求。

  • 論文的符號說明如下:

  • 決策變數:\(S^t_{bwz}、S^t_{ewz}、O^{ft}_{bwz}、O^{ft}_{ewz}、O^{st}_{bwz}、O^{st}_{ewz}、P^t_{bz}、P^t_{fz}、P^t_{sz}、X_{bz}、X_{ez}\)

3.3.2 模型建立

\[Max\sum\limits_{t\in{T}}\sum\limits_{w\in{Z}}\sum\limits_{z\in{Z}}[P^t_{bz}(S^t_{bwz}+S^t_{ewz})+P^t_{fz}(O^{ft}_{bwz}+O^{ft}_{ewz})+P^t_{sz}(O^{st}_{bwz}+O^{st}_{ewz})]+v[\sum\limits_{z\in{Z}}(X^T_{bz}+X^T_{ew})]+h[\sum\limits_{t\in{T}}\sum\limits_{z\in{Z}}(X^t_{bz}+X^t_{ez})] \]

\[-\sum\limits_{t\in{T}}\sum\limits_{w\in{Z}}\sum\limits_{z\in{Z}}(c^s_{bwz}S^t_{bwz}+c^s_{ewz}S^t_{ewz}+c^f_{bwz}O^{ft}_{bwz}+c^s_{ewz}O^{ft}_{ewz}+c^s_{bwz}O^{st}_{bwz}+c^s_{ewz}O^{st}_{ewz}) \]

\(s.t.\)

\[\sum\limits_{w\in{Z}}(S^t_{bwz}+S^t_{ewz})\leq{D^t_{bz}(P^t_z)} \forall{z}\in{Z},\forall{t\in{T}} \]

\[\sum\limits_{w\in{Z}}(O^{ft}_{bwz}+O^{ft}_{ewz})\leq{D^t_{fz}(P^t_z)} \forall{z}\in{Z},\forall{t\in{T}} \]

\[\sum\limits_{w\in{Z}}(O^{st}_{bwz}+O^{st}_{ewz})\leq{D^t_{sz}(P^t_z)} \forall{z}\in{Z},\forall{t\in{T}} \]

\[X^t_{bw}=X^{t-1}_{bw}-\sum\limits_{z\in{Z}}(S^t_{bwz}+O^{ft}_{bwz}+O^{st}_{bwz})\forall{w}\in{Z}, \forall{t}\in{T} \]

\[X^t_{ew}=X^{t-1}_{ew}-\sum\limits_{z\in{Z}}(S^t_{ewz}+O^{ft}_{ewz}+O^{st}_{ewz})\forall{w}\in{Z}, \forall{t}\in{T} \]

\[\sum\limits_{w\in{Z}}X^0_{ew}+\sum\limits_{w\in{Z}}X^0_{bw}=x \]

\[P^t_z=(P^t_{bz},P^t_{fz}, P^t_{sz})\forall{z}\in{Z},\forall{t\in{T}} \]

\[S^t_{bwz}, S^t_{ewz}, O^{ft}_{bwz}, O^{ft}_{ewz}, O^{st}_{bwz}, O^{st}_{ewz}\geq{0}\forall{z}\in{Z}, \forall{w}\in{Z}, \forall{t\in{T}} \]

\[X^t_{ez}, X^t_{bz}\geq0\forall{z}\in{Z}, \forall{t}\in{T} \]

  • 目標函式為總利潤最大化,主要分為四部分:第一部分為滿足線上、線下渠道需求的收入;第二部分為剩餘庫存的價值;第三部分為庫存持有成本;第四部分為線下、線上渠道的履行成本。

  • 關於約束條件:第一、第二、第三條約束條件為需求約束,即銷售額必須小於對應渠道的需求;第四、第五條為區域\(z\)\(t\)期末的剩餘庫存計算;第五條為庫存約束,確保期初線上、線下的庫存之和為整個計劃期前的庫存量;第六條為價格向量約束;其他約束條件為變數的非負約束。

4. 模型求解

文中的模型主要是用PyLogit和CPLEX求解器求解的,CPLEX求解比較簡單,所以在這裡不加贅述。但我發現有關PyLogit函式的資料居然全網都搜不到(╯‵□′)╯︵┻━┻,於是我採用了一些技術手段,找ChatGPT幫我寫了個詳解和程式碼。下面主要介紹PyLogit的詳解及文章的MNL選擇模型程式碼。

4.1 Python的PyLogit包詳解

以下為ChatGPT的回答。

使用Python的PyLogit包求解MNL模型有以下幾個步驟:

1.   計算變數並生成資料集

首先,您需要確定MNL模型中需要考慮哪些變數並將這些變數收集到一個資料集中。然後需要計算其中變數的值,這些值可能來自不同的資料集,可以直接從程式碼中讀取,也可以從檔案中讀取到資料集中。在將資料集匯入Python環境中之後,可以使用Pandas DataFrame屬性計算變數。

2.   模型擬合

使用PyLogit包的模型擬合函式,您可以擬合MNL模型。這個函式將需要以下引數:

  • formula:一個字串表示模型公式,語法可以參照R語言的glam()函式。

  • data:包含資料集和變數的Pandas DataFrame物件。

  • alt_name:一個字串,是資料集中包含選擇項的列名。

  • obs_id:一個字串,表示資料集中包含觀測編號的列名。

  • num_params:一個整數,表示模型引數的數量。

3.   模型評價

使用PyLogit包的模型評價函式評價模型。這個函式將需要以下引數:

  • model_results:包含模型擬合結果的PyLogit Mnlogit結果物件。

  • print_results:一個布林值,表示是否列印出結果。

透過這些步驟完成之後,您將擬合一個MNL模型並可以使用PyLogit包進行相關的分析,如預測新資料等。

程式碼示例:

# 匯入PyLogit包
from pylogit import PyLogit

# 從檔案中讀取資料集
data = pd.read_csv("data.csv")

# 計算變數
# ...

# 將變數新增到資料集中
# ...

# 指定模型公式
formula = 'Y ~ X1 + X2 + X3'

# 擬合模型
mnl_model = PyLogit(data=data,
                    formula=formula,
                    alt_name='Y',
                    obs_id='Obs_ID',
                    # num_params 等於 X1 + X2 + X3 中變數數量
                    num_params=3)

# 評估模型
mnl_model.fit(maxiter=1000,   # 最大迭代次數
              halton_iterations=0,
              check_gradient=True)

# 列印結果
print(mnl_model.summary())

4.2 PyLogit求解MNL選擇模型

我後面又詢(奴)問(役)了一下ChatGPT,讓它幫我寫使用PyLogit包求解MNL選擇模型的程式碼,以下程式碼是我根據GPT的程式碼進行修改,對論文中MNL選擇模型的復現。

import numpy as np
import pandas as pd
import pylogit as pl

#ID代表客戶的ID
#Choice代表客戶對渠道的選擇(b為線下渠道,e為線上渠道)
#Price代表對應的價格
data = pd.DataFrame({
    'ID': [1, 1, 2, 2, 3, 3, 4, 4],
    'Choice': ['b', 'e', 'b', 'e', 'b', 'e', 'b', 'e'],
    'Price': [10, 8, 12, 6, 20, 15, 18, 10]
})

#'gev'是對Gumbel分佈的定義
data['b_Price_Utility'] = pl.create_choice_column(data['Price'], 0.0, 'gev', (1,))
data['e_Price_Utility'] = pl.create_choice_column(data['Price'], 0.0, 'gev', (1,))

# 將資料重構為"wide"格式
long_data = pl.convert_wide_to_long(data, id_col='ID', alt_col='Choice', 
                                    observation_col=None, drop_alt_id=False)
wide_data = pl.convert_long_to_wide_format(long_data, id_col='ID', 
                                            value_col='Price Utility')

#使用MNL訓練模型
model = pl.create_choice_model(data=wide_data, alt_id_col='alt_id', 
                                obs_id_col='obs_id', choice_col='choice', 
                                specification={
                                    'Price': [1, 2]
                                }, 
                                model_type='MNL')
result = model.fit()

#輸出模型的引數,裡面包含了文中所需的β引數
print(result.summary())

程式碼中ID、Choice、Price的資料都是我亂編的,因為論文中沒給訓練資料集。但大家如果有需要的話可以自己收集資料讀入訓練。

相關文章