赞
踩
导读:本文系统介绍了如何将一个实际的促销定问题转化为一个数学问题,并利用数据预处理与挖掘、统计学与机器学习、运筹优化等技术从 0-1 的解决该问题。 帮助大家深入了解AI技术是如何在【促销定价】场景落地的。本文将包含完整的业务+数据+算法+代码。
大家好!我们是IndustryOR 团队,致力于分享业界落地的OR+AI技术。欢迎关注微信公众号/知乎【运筹匠心】 。本期我们将选择某零售商超“促销定价”场景,来谈一谈AI技术是如何在【促销定价】场景落地的。
由于篇幅原因,数据和代码(超详细注释)附在粉丝群公告,大家可自行加群获取,加群方式在文章末尾~~
在日常生活中,我们经常会遇见线上/线下商家推出各类打折、满减、赠品、新人价、优惠券、捆绑销售等促销活动。一次成功的促销对于消费者和商家来说是双赢的。一方面,促销活动能让消费者买到低价的商品;另一方面,促销活动也能为商家带来可观的利润。
尽管促销活动五花八门、玩法多变,但其底层的核心商业逻辑是“价格”。因此,对于商家来说,如何科学合理地进行促销定价是重中之重。
本文将从以下4个部分讲解:
01 业务拆解
02 数据挖掘
03 价格弹性
04 定价决策
文章有些长,但全是干货,建议横屏观看,看完一定收获满满。坐好板凳,我们正式起航~~~
在新冠疫情、俄乌战争、巴以战争、大国博弈等时代大背景下,全球经济目前正处于下行周期,消费降级趋势已经形成,各行各业都在积极转型变革,以应对时代的挑战,寻找新的增长点。
以零售行业为例,过去几年涌现了不少新业态。如:线上渠道,直播带货、内容电商、社区团购等模式高速发展;线下渠道,折扣店、临期食品店、工厂店等门店遍地开花。不难发现,为了顺应消费降级的大趋势,“低价促销”已逐步成为现阶段零售行业的共识和最重要的竞争要素。
“低价促销”是一种可以让消费者和商家同时受益的经营手段,消费者用“低价”买到了心仪的商品,商家通过“促销”实现了利润的增长。但实现双赢的前提是要保证“促销定价”的合理性,即对每个商品均制定出最合适的价格。否则,就变成了“高价降销”或者“赔本赚吆喝”。那么,商家在“促销定价”时会遇到哪些挑战呢?
抛开活动策划、促销手段、促销时间、促销时长、促销渠道、推广方式、引流策略、售后支持等业务动作不谈。我们单从“定价”的角度上看,挑战可归纳为以下4点:
站在业务的角度上考虑,商家的核心诉求可总结为一句话:在“促销”中,如何“定价”才能保证合理的利润?
要想回答这个问题,就必须知道价格和利润的关系,即定什么价格能得到什么利润。我们都知道:
商品利润 =(商品售价 - 商品成本价) × \times × 商品销量 。
观察上述公式,商品利润是最终的结果,商品售价是待“定价”的变量,商品成本价是已知的常量,商品销量是一个未知的变量。因此,
我们只要知道商品销量的取值,就可以知道定什么价格下能得到什么利润了。
那么,商品销量这个变量该如何被量化呢? 我们都知道商品价格是影响商品销量的重要因素。从整体上看,商品的价格和商品的销量大概率呈现负相关,即价格越高,销量越低。但这并不意味着这种相关性在商品的某个局部价格区间下同样成立。
举个例子说明:泰国猫山王榴莲的是一种比较昂贵的进口水果,市场价大概90-110元/斤。如果商家打折出售1元/斤,肯定1秒就会被抢光;如果商家定价9999元/斤,估计大概率无人购买,当然土豪除外。但这一现象一定能推测出商家定价95元时肯定会比定价105元时销量高吗?显然不一定。也许这两种价格下的销量并没有太大的差别,因为能消费的起泰国猫山王榴莲的客户对10元以内价格波动的感知是微弱的。但如果10元的价格波动发生在鸡蛋上,销量可能会天差地别。
由此,我们可以得出一个重要的结论:
对于不同的商品来说,在一定的价格区间内,相同幅度的价格波动所带来的销量波动的幅度可能是不同的。
这也就意味着,我们如果能找到每种商品的合适的价格区间,并量化出区间内价格与销量的关系,就能预估出每种商品的在不同价格下的大致销量,进而估算出大致的利润,这种定价方式叫做精细化定价。通过这种方式,我们可以精细化地制定出每种商品合适的价格,在保证消费者享受部分商品折扣的同时,实现商家利润的合理最大化。(还有一种更精细化的定价方式叫做差异化定价,侧重于考虑到不同客户群体的消费偏好和消费能力,大家有兴趣可以了解一下。)
接下来,我们用简单的数学语言描述一下该问题:
max
∑
s
∈
S
(
p
s
−
c
s
)
×
q
s
(
1
)
\max \sum_{s \in S} (p_{s}-c_{s})\times q_{s} \space\space\space (1)
maxs∈S∑(ps−cs)×qs (1)
q
s
=
f
(
p
s
,
θ
s
)
∀
s
∈
S
(
2
)
q_{s}=f(p_{s},\theta_{s}) \space\space\space \forall s \in S \space\space\space (2)
qs=f(ps,θs) ∀s∈S (2)
l
s
≤
p
s
≤
h
s
∀
s
∈
S
(
3
)
l_{s} \leq p_{s} \leq h_{s} \space\space\space \forall s \in S \space\space\space (3)
ls≤ps≤hs ∀s∈S (3)
上述公式中, S S S表示商家售卖商品集合; c s c_{s} cs表示商品 s s s的成本价; p s p_{s} ps表示商品 s s s的售价; q s q_{s} qs表示商品 s s s的销量; f ( p s , θ s ) f(p_{s},\theta_{s}) f(ps,θs)表示商品 s s s销量与商品售价之间的量化函数; l s l_{s} ls和 h s h_{s} hs分别商品合适的价格区间的左右边界价格。式 ( 1 ) (1) (1)表示商家利润最大化,即所有种类商品利润加和最大化;式 ( 2 ) (2) (2)表示每种商品的销量与售价之间的关系;式 ( 3 ) (3) (3)表示每种商品的价格均要在合适的区间。
经过以上拆解,我们明确促销定价的3个主要任务:
本案例本案例数据改编自【2019年全国大学生数学建模E题】公开数据集。主要用到销售流水表1/2(附件1/2)和商品信息表(附件4),表结构如下:
字段 | 含义 |
---|---|
order_id | 订单ID |
is_finished | 订单是否完成 |
sku_id | 商品ID |
sku_name | 商品名称 |
sku_prc | 门店价 |
sku_sale_prc | 销售价 |
sku_cost_prc | 成本价 |
sku_cnt | 销售数量 |
upc_code | UPC码 |
create_dt | 创建时间 |
字段 | 含义 |
---|---|
skuid | sku名称 |
skuname | sku名称 |
first_category_id | 一级类目id |
second_category_id | 二级类目id |
third_category_id | 三级类目id |
first_category_name | 一级类目名称 |
second_category_name | 二级类目名称 |
third_category_name | 三级类目名称 |
我们发现:
销售流水表upc_code字段部分缺失,其他字段不缺失。商品信息表无缺失字段。 。
原始数据需要经过清洗、聚合、补全等操作,加工成便于分析求解的数据。
详见代码(文末加粉丝群获取~~~)
最终待分析求解的促销定价数据大宽表(promotional_pricing_data1.csv)结构如下:
字段 | 含义 |
---|---|
sku_id | 商品ID |
sku_name | 商品名称 |
ori_prc | 原价 |
sale_prc | 售价 |
cost_prc | 成本价 |
sku_cnt | 销量 |
cate1_id | 一级类目id |
cate2_id | 二级类目id |
cate3_id | 三级类目id |
cate1_name | 一级类目名称 |
cate2_name | 二级类目名称 |
cate3_name | 三级类目名称 |
sale_dt | 销售日期 |
我们发现:
为了进一步挖掘数据,我们分别在天维度、品维度、价格维度和数量维度对数据进行聚合分析。
统计每日的销量、GMV(销售额)、成本、毛利额、折扣率等信息,画出趋势图。
我们发现:
统计各级品类/sku下子品类宽度(子品类个数)、sku宽度(个数)、sku总销量、sku价格等信息,画出分布图。
我们发现:
统计不同价格区间下sku宽度、总销量、总gmv、总成本、总毛利,画出分布图。
我们发现:
绝大部分sku的价格分布在20元以下,5-10元区间的sku占比最多。
分别统计不同历史售卖天数和不同历史价格数下的sku宽度分布,画出分布图。
我们发现:
不同sku的历史价格数量不同,绝大部分的sku历史价格数量只有1个。针对该现象需要进一步分析,有2种可能:
针对1级品类/2级品类/3级品类/sku,分别计算售价/折扣比例/折扣额与日销量间的pearson相关性系数,画出分布图。
我们发现:
不同品类/sku的售价/折扣比例/折扣额与日销量间相关性差异极大。如:
因此,在促销定价时,需要根据不同的sku制定不同的定价策略。
根据2.3.3节计算出来的3级品类平均售价/折扣比例/折扣额与日销量间的相关性系数,对3级品类进行聚类,画出聚类图。
经过实验我们发现,聚4类即可将样本较好的分开,聚类结果也符合业务常识。详情如下:
综上诉说,我们利用数据挖掘技术,从各个维度较为全面的分析了数据的全貌,并深度挖掘了价格/折扣和销量之间的关系。最终,我们得到了一个核心结论:
不同的sku的价格/折扣与销量之间的关系不同,促销定价做的越精细,效果越好。而精细化正是算法相较人工的优势所在。
经过【01 业务拆解】小结可知,促销定价需要解决的第一个问题是:
经过【02 数据挖掘】小结可知:
因此,接下来我们需要解决的问题是:
如何精细化地确定价格与销量的关系模型 f f f的形式和模型参数 θ s \theta_{s} θs的取值?
针对以上问题,目前业界落地方案可分为3大类:
类别 | 方法 | 优劣势 |
---|---|---|
白盒方案 | 价格弹性模型 | 可解释性强,量化效果一般 |
黑盒方案 | 机器/深度学习模型 | 量化效果好,可解释性弱 |
融合方案 | 机器/深度学习模型+因果推断 | 量化效果较好,可解释性较强 |
一般情况下,业界应用会先选择白盒方案的价格弹性模型作为baseline版本,然后逐步向因果推断方案过渡。因此,本文将重点介绍价格弹性模型是如何量化sku的价格与销量之间的关系的。
价格弹性(price elasticity)是经济学领域的重要概念,可分为需求价格弹性、供给的价格弹性、交叉价格弹性、预期价格弹性等各种类型。由于我们本文主要研究价格与销量之间的关系,因为我们接下来将重点研究需求价格弹性。
需求价格弹性(以下简称“价格弹性”)可定义为需求(销量)变动比率与引起其变动的价格变动比率的比率,反映商品价格与市场消费容量的关系,表明价格升降时需求量的增减程度。
用数学公式可表示为:
e
=
(
Δ
Q
/
Q
)
/
(
Δ
P
/
P
)
(
1
)
e = (\Delta Q / Q)/(\Delta P / P) \space\space\space (1)
e=(ΔQ/Q)/(ΔP/P) (1)
公式(1)中, e e e代表价格弹性; Q Q Q表示销量, Δ Q \Delta Q ΔQ表示销量的变化量,因此 Δ Q / Q \Delta Q / Q ΔQ/Q则表示销量变动比率; P P P表示价格, Δ P \Delta P ΔP表示价格的变化量,因此 Δ P / P \Delta P / P ΔP/P则表示价格变动比率。
通过观察以上公式,我们可用通俗的语言描述价格弹性:
价格弹性表示:价格 P P P每增加(减少)1%所能带来的销量 Q Q Q增加(减少)的比例。
我们已经知道了价格弹性的定义,但是如何求解价格弹性呢?答案就是: l n P lnP lnP - l n Q lnQ lnQ线性回归。接下来我们逐步推导证明。
首先回顾一下导数的定义:
d
y
/
d
x
=
lim
Δ
x
−
>
0
(
Δ
y
/
Δ
x
)
(
1
)
dy / dx = \lim_{\Delta x->0}(\Delta y / \Delta x ) \space\space\space (1)
dy/dx=Δx−>0lim(Δy/Δx) (1)
l
n
P
lnP
lnP -
l
n
Q
lnQ
lnQ线性回归可表示为:
l
n
Q
=
e
∗
l
n
P
+
b
(
2
)
lnQ = e * lnP + b \space\space\space (2)
lnQ=e∗lnP+b (2)
等式两边求导可得:
(
1
/
Q
)
∗
(
d
Q
/
d
P
)
=
e
∗
(
1
/
P
)
(
3
)
(1/Q) * (dQ /dP) = e * (1 / P) \space\space\space (3)
(1/Q)∗(dQ/dP)=e∗(1/P) (3)
当
Δ
P
\Delta P
ΔP较小时,可近似写为:
(
1
/
Q
)
∗
(
Δ
Q
/
Δ
P
)
=
e
∗
(
1
/
P
)
(
4
)
(1/Q) * (\Delta Q / \Delta P) = e * (1 / P) \space\space\space (4)
(1/Q)∗(ΔQ/ΔP)=e∗(1/P) (4)
等号两侧交换并整理可得:
e
/
P
=
Δ
Q
/
(
Δ
P
∗
Q
)
(
5
)
e / P = \Delta Q /(\Delta P* Q) \space\space\space (5)
e/P=ΔQ/(ΔP∗Q) (5)
将
P
P
P移至等式右侧可得:
e
=
(
Δ
Q
/
Q
)
/
(
Δ
P
/
P
)
(
6
)
e = (\Delta Q / Q)/(\Delta P / P) \space\space\space (6)
e=(ΔQ/Q)/(ΔP/P) (6)
而式(6)正是价格弹性的定义。
至此,我们可以看出:
l n P lnP lnP - l n Q lnQ lnQ的线性回归的回归参数 e e e就是我们想求解的价格弹性。
我们选择岭回归(Ridge Regression,L2正则化的线性回归),从聚类簇、3级品类、sku三个维度,分别回归了各自的价格弹性,量化出价格和销量的关系,并选择 W M A P E WMAPE WMAPE(Weighted Mean Absolute Percentage Error)评价回归效果。
详见代码(文末加粉丝群获取~~~)
W
M
A
P
E
WMAPE
WMAPE是指带权重的平均绝对百分比误差,是用来做销量预测最常用的指标,越小越好。公式如下:
W
M
A
P
E
=
∑
n
∣
y
′
−
y
∣
/
∑
n
y
(
7
)
WMAPE=\sum_{n} |y^{'} - y| / \sum_{n} y \space\space\space (7)
WMAPE=n∑∣y′−y∣/n∑y (7)
分别计算聚类簇维度、3级品类维度和sku维度的
W
M
A
P
E
WMAPE
WMAPE值。
价格弹性回归结果为:
评价结果如下:
分组维度 | W M A P E WMAPE WMAPE |
---|---|
聚类簇 | 0.7379 |
3级品类 | 0.6772 |
sku | 0.6198 |
我们发现:
对于 W M A P E WMAPE WMAPE值,聚类簇维度 < 3级品类维度 < sku维度,这也验证了【02 数据挖掘】的结论:不同sku的价格与销量之间的关系不同,促销定价做的越精细,效果越好。
经过【01 业务拆解】小结可知,促销定价需要解决的第二、三个问题是:
经过【03 价格弹性】计算:
因此,接下来我们需要解决的问题是:
这显然是一个运筹决策问题。
l
s
l_{s}
ls 和
h
s
h_{s}
hs 的取值可以根据历史数据统计得出,我们这里通过取商品原价、售价和成本价的历史最小最大值得到。即:
l
s
=
min
(
.
.
.
,
o
s
t
,
p
s
t
,
c
s
t
,
.
.
.
)
(
1
)
l_{s} = \min(...,o_{st},p_{st},c_{st},... ) \space\space\space (1)
ls=min(...,ost,pst,cst,...) (1)
h
s
=
max
(
.
.
.
,
o
s
t
,
p
s
t
,
c
s
t
,
.
.
.
)
(
2
)
h_{s} = \max(...,o_{st},p_{st},c_{st},... ) \space\space\space (2)
hs=max(...,ost,pst,cst,...) (2)
上式中,
t
t
t 表示历史第
t
t
t 天,
o
s
t
/
p
s
t
/
c
s
t
o_{st}/p_{st}/c_{st}
ost/pst/cst 分别表示商品
s
s
s 历史第
t
t
t 天的原价、售价、成本价。
促销定价的决策模型通常有两类建模方式,分别为带有指数二次项的凸优化模型和 0-1 整数规划模型。
经过【03 价格弹性】可知:
e
=
(
Δ
Q
/
Q
)
/
(
Δ
P
/
P
)
(
3
)
e = (\Delta Q / Q)/(\Delta P / P) \space\space\space (3)
e=(ΔQ/Q)/(ΔP/P) (3)
l
n
Q
=
e
∗
l
n
P
+
b
(
4
)
lnQ = e * lnP + b \space\space\space (4)
lnQ=e∗lnP+b (4)
则销量
Q
Q
Q可表示为:
Q
=
e
x
p
(
e
∗
l
n
P
+
b
)
(
5
)
Q = exp(e * lnP + b) \space\space\space (5)
Q=exp(e∗lnP+b) (5)
我们为变量加上下标,可表示为:
q
s
=
e
x
p
(
e
s
∗
l
n
p
s
+
b
s
)
(
6
)
q_{s} = exp(e_{s} * lnp_{s} + b_{s}) \space\space\space (6)
qs=exp(es∗lnps+bs) (6)
式(6)表示商品
s
s
s 的价格
p
s
p_{s}
ps 和销量
q
s
q_{s}
qs 之间的关系,
e
s
e_{s}
es 表示价格弹性,
b
s
b_{s}
bs 表示回归偏置项。
将式(6)代入【01 业务拆解】模型可得:
max
∑
s
∈
S
(
p
s
−
c
s
)
×
e
x
p
(
e
s
∗
l
n
p
s
+
b
s
)
(
7
)
\max \sum_{s \in S} (p_{s}-c_{s})\times exp(e_{s} * lnp_{s} + b_{s}) \space\space\space (7)
maxs∈S∑(ps−cs)×exp(es∗lnps+bs) (7)
l
s
≤
p
s
≤
h
s
∀
s
∈
S
(
3
)
l_{s} \leq p_{s} \leq h_{s} \space\space\space \forall s \in S \space\space\space (3)
ls≤ps≤hs ∀s∈S (3)
其中, p s p_{s} ps 为连续型决策变量,其余项均为已知常量;式(7)表示我们决策的目标函数,即利润最大化。可以发现,上述模型是一个含有指数二次项 p s × e x p ( e s ∗ l n p s + b s ) p_{s}\times exp(e_{s} * lnp_{s} + b_{s}) ps×exp(es∗lnps+bs) 的凸优化问题,模型比较简单,可直接求得解析解。
除方案一外,也可以将商品价格
p
s
p_{s}
ps 离散化为可选价格集合
P
s
=
[
p
s
1
,
p
s
2
,
.
.
.
,
p
s
n
]
P_{s} = [p_{s_{1}},p_{s_{2}},...,p_{s_{n}}]
Ps=[ps1,ps2,...,psn],用(6)计算出对应的预测销量集合
Q
s
=
[
q
s
1
,
q
s
2
,
.
.
.
,
q
s
n
]
Q_{s} = [q_{s_{1}},q_{s_{2}},...,q_{s_{n}}]
Qs=[qs1,qs2,...,qsn],用
r
s
i
=
p
s
i
−
c
s
r_{si} = p_{si}-c_{s}
rsi=psi−cs 表示商品价格
s
s
s 定价为
p
s
i
p_{s_{i}}
psi 时所产生的的单个商品利润。然后建立如下模型:
max
∑
s
∈
S
∑
i
∈
P
s
r
s
i
×
q
s
i
×
x
s
i
(
8
)
\max \sum_{s \in S}\sum_{i \in P_{s}} r_{si} \times q_{si} \times x_{si} \space\space\space (8)
maxs∈S∑i∈Ps∑rsi×qsi×xsi (8)
∑
i
∈
P
s
x
s
i
=
1
∀
s
∈
S
(
9
)
\sum_{i \in P_{s}}x_{si}=1 \space\space\space \forall s \in S \space\space\space (9)
i∈Ps∑xsi=1 ∀s∈S (9)
x
s
i
∈
{
0
,
1
}
∀
s
∈
S
,
∀
i
∈
P
s
(
10
)
x_{si} \in \{0,1\} \space\space\space \forall s \in S, \forall i \in P_{s} \space\space\space (10)
xsi∈{0,1} ∀s∈S,∀i∈Ps (10)
其中,
x
s
i
x_{si}
xsi 为 0-1 决策变量,表示商品
s
s
s 的第
i
i
i 个备选价格
p
s
i
p_{si}
psi 是否被选中;式(8)表示利润最大化的决策目标;式(9)表示每个商品
s
s
s 只能制定一个价格。可以发现,上述模型是一个 0-1 整数规划模型。
分析实际业务,我们发现:
促销商品的价格基本是以 58、66、68、88、98、99 等吉利数字结尾。显然,方案二更适合于实际业务。 因此,我们采用方案二的建模方式求解促销定价问题。
在实际的业务中,精细化定了除了保证利润最大化的决策目标,还需要对配合促销策略的开展。我们这里举一个例子:
我们将如上约束转化为数学语言。定义 d s i = o s − p s i o s d_{si}=\frac {o_{s}-p_{si}}{o_{s}} dsi=osos−psi 表示商品 s s s 定价 p s i p_{si} psi 时的折扣率。则数学公式可表示为:
0.2
≤
∑
s
∈
S
∑
i
∈
P
s
r
s
i
×
q
s
i
×
x
s
i
∑
s
∈
S
∑
i
∈
P
s
c
s
×
q
s
i
×
x
s
i
≤
0.3
(
11
)
0.2 \le \frac {\sum_{s \in S}\sum_{i \in P_{s}} r_{si} \times q_{si} \times x_{si}} {\sum_{s \in S}\sum_{i \in P_{s}} c_{s} \times q_{si} \times x_{si}} \le 0.3 \space\space\space (11)
0.2≤∑s∈S∑i∈Pscs×qsi×xsi∑s∈S∑i∈Psrsi×qsi×xsi≤0.3 (11)
∑
s
∈
S
v
∑
i
∈
P
s
d
s
i
×
x
s
i
∑
s
∈
S
v
∑
i
∈
P
s
x
s
i
≥
0.3
(
12
)
\frac {\sum_{s \in S_{v}}\sum_{i \in P_{s}}d_{si} \times x_{si}} {\sum_{s \in S_{v}}\sum_{i \in P_{s}}x_{si}} \ge 0.3 \space\space\space(12)
∑s∈Sv∑i∈Psxsi∑s∈Sv∑i∈Psdsi×xsi≥0.3 (12)
∑
s
∈
S
f
∑
i
∈
P
s
d
s
i
×
x
s
i
∑
s
∈
S
f
∑
i
∈
P
s
x
s
i
≥
0.2
(
13
)
\frac {\sum_{s \in S_{f}}\sum_{i \in P_{s}}d_{si} \times x_{si}} {\sum_{s \in S_{f}}\sum_{i \in P_{s}}x_{si}} \ge 0.2 \space\space\space(13)
∑s∈Sf∑i∈Psxsi∑s∈Sf∑i∈Psdsi×xsi≥0.2 (13)
∑
s
∈
S
p
∑
i
∈
P
s
d
s
i
×
x
s
i
∑
s
∈
S
p
∑
i
∈
P
s
x
s
i
≥
0.1
(
14
)
\frac {\sum_{s \in S_{p}}\sum_{i \in P_{s}}d_{si} \times x_{si}} {\sum_{s \in S_{p}}\sum_{i \in P_{s}}x_{si}} \ge 0.1 \space\space\space(14)
∑s∈Sp∑i∈Psxsi∑s∈Sp∑i∈Psdsi×xsi≥0.1 (14)
上述公式中:式(11)表示总利润率在 20%-30%之间,分子表示总利润,分母表示总成本;式(12)(13)(14)分别表示蔬菜/国产水果/猪肉类商品平均折扣率不低于 30%/20%/10%,分子表示该类商品的折扣率之和,分母表示该类商品的商品数量。
我们合并 2)、3)节内容,形成最终模型。由于引入式(11)(12)(13)(14)业务约束,模型可能无解并且存在非线性项不利于模型求解。因此,我们引入松弛变量保证模型可解;同时对模型进行不等式变换消除非线性项。
分别引入
α
1
,
α
2
,
β
v
,
β
f
,
β
p
\alpha_{1},\alpha_{2},\beta_{v},\beta_{f},\beta_{p}
α1,α2,βv,βf,βp 松弛变量。
0.2
≤
α
1
+
∑
s
∈
S
∑
i
∈
P
s
r
s
i
×
q
s
i
×
x
s
i
∑
s
∈
S
∑
i
∈
P
s
c
s
×
q
s
i
×
x
s
i
−
α
2
≤
0.3
(
15
)
0.2 \le \alpha_{1} + \frac {\sum_{s \in S}\sum_{i \in P_{s}} r_{si} \times q_{si} \times x_{si}} {\sum_{s \in S}\sum_{i \in P_{s}} c_{s} \times q_{si} \times x_{si}} - \alpha_{2} \le 0.3 \space\space\space (15)
0.2≤α1+∑s∈S∑i∈Pscs×qsi×xsi∑s∈S∑i∈Psrsi×qsi×xsi−α2≤0.3 (15)
∑
s
∈
S
v
∑
i
∈
P
s
d
s
i
×
x
s
i
∑
s
∈
S
v
∑
i
∈
P
s
x
s
i
+
β
v
≥
0.3
(
16
)
\frac {\sum_{s \in S_{v}}\sum_{i \in P_{s}}d_{si} \times x_{si}} {\sum_{s \in S_{v}}\sum_{i \in P_{s}}x_{si}} + \beta_{v} \ge 0.3 \space\space\space(16)
∑s∈Sv∑i∈Psxsi∑s∈Sv∑i∈Psdsi×xsi+βv≥0.3 (16)
∑
s
∈
S
f
∑
i
∈
P
s
d
s
i
×
x
s
i
∑
s
∈
S
f
∑
i
∈
P
s
x
s
i
+
β
f
≥
0.2
(
17
)
\frac {\sum_{s \in S_{f}}\sum_{i \in P_{s}}d_{si} \times x_{si}} {\sum_{s \in S_{f}}\sum_{i \in P_{s}}x_{si}} + \beta_{f} \ge 0.2 \space\space\space(17)
∑s∈Sf∑i∈Psxsi∑s∈Sf∑i∈Psdsi×xsi+βf≥0.2 (17)
∑
s
∈
S
p
∑
i
∈
P
s
d
s
i
×
x
s
i
∑
s
∈
S
p
∑
i
∈
P
s
x
s
i
+
β
p
≥
0.1
(
18
)
\frac {\sum_{s \in S_{p}}\sum_{i \in P_{s}}d_{si} \times x_{si}} {\sum_{s \in S_{p}}\sum_{i \in P_{s}}x_{si}} + \beta_{p} \ge 0.1 \space\space\space(18)
∑s∈Sp∑i∈Psxsi∑s∈Sp∑i∈Psdsi×xsi+βp≥0.1 (18)
α
1
,
α
2
,
β
v
,
β
f
,
β
p
≥
0
(
19
)
\alpha_{1},\alpha_{2},\beta_{v},\beta_{f},\beta_{p} \ge 0 \space\space\space(19)
α1,α2,βv,βf,βp≥0 (19)
由于式(9)(10)(11)(12)的分母恒大于 0,因此将分母移到不等式的另一边不等式符号不改变。以式(14)为例,等价于:
∑
s
∈
S
v
∑
i
∈
P
s
d
s
i
×
x
s
i
+
β
v
×
∑
s
∈
S
v
∑
i
∈
P
s
x
s
i
≥
0.3
×
∑
s
∈
S
v
∑
i
∈
P
s
x
s
i
(
20
)
\sum_{s \in S_{v}}\sum_{i \in P_{s}}d_{si} \times x_{si} + \beta_{v} \times\sum_{s \in S_{v}}\sum_{i \in P_{s}}x_{si} \ge 0.3 \times \sum_{s \in S_{v}}\sum_{i \in P_{s}}x_{si} \space\space\space(20)
s∈Sv∑i∈Ps∑dsi×xsi+βv×s∈Sv∑i∈Ps∑xsi≥0.3×s∈Sv∑i∈Ps∑xsi (20)
又因为,
β
v
\beta_{v}
βv 为松弛变量,且
≥
0
\ge 0
≥0。所以,可将
β
v
×
∑
s
∈
S
v
∑
i
∈
P
s
x
s
i
\beta_{v} \times\sum_{s \in S_{v}}\sum_{i \in P_{s}}x_{si}
βv×∑s∈Sv∑i∈Psxsi 等价为
β
v
\beta_{v}
βv。因此,不等式可转化为:
∑
s
∈
S
v
∑
i
∈
P
s
d
s
i
×
x
s
i
+
β
v
≥
0.3
×
∑
s
∈
S
v
∑
i
∈
P
s
x
s
i
(
21
)
\sum_{s \in S_{v}}\sum_{i \in P_{s}}d_{si} \times x_{si} + \beta_{v} \ge 0.3 \times \sum_{s \in S_{v}}\sum_{i \in P_{s}}x_{si} \space\space\space(21)
s∈Sv∑i∈Ps∑dsi×xsi+βv≥0.3×s∈Sv∑i∈Ps∑xsi (21)
合并同类项,可转化为:
∑ s ∈ S v ∑ i ∈ P s ( d s i − 0.3 ) × x s i + β v ≥ 0 ( 22 ) \sum_{s \in S_{v}}\sum_{i \in P_{s}}(d_{si} -0.3) \times x_{si} + \beta_{v} \ge 0 \space\space\space(22) s∈Sv∑i∈Ps∑(dsi−0.3)×xsi+βv≥0 (22)
因此,最终模型可表示为:
max
∑
s
∈
S
∑
i
∈
P
s
r
s
i
×
q
s
i
×
x
s
i
−
M
×
(
α
1
+
α
2
+
β
v
+
β
f
+
β
p
)
(
23
)
\max \sum_{s \in S}\sum_{i \in P_{s}} r_{si} \times q_{si} \times x_{si} - M \times(\alpha_{1}+\alpha_{2}+\beta_{v}+\beta_{f}+\beta_{p}) \space\space\space (23)
maxs∈S∑i∈Ps∑rsi×qsi×xsi−M×(α1+α2+βv+βf+βp) (23)
∑
i
∈
P
s
x
s
i
=
1
∀
s
∈
S
(
9
)
\sum_{i \in P_{s}}x_{si}=1 \space\space\space \forall s \in S \space\space\space (9)
i∈Ps∑xsi=1 ∀s∈S (9)
∑
s
∈
S
∑
i
∈
P
s
(
r
s
i
−
0.3
×
c
s
)
×
q
s
i
×
x
s
i
+
α
1
≤
0
(
24
)
\sum_{s \in S}\sum_{i \in P_{s}} (r_{si}-0.3 \times c_{s}) \times q_{si} \times x_{si} + \alpha_{1} \le 0 \space\space\space (24)
s∈S∑i∈Ps∑(rsi−0.3×cs)×qsi×xsi+α1≤0 (24)
∑
s
∈
S
∑
i
∈
P
s
(
r
s
i
−
0.2
×
c
s
)
×
q
s
i
×
x
s
i
+
α
2
≥
0
(
25
)
\sum_{s \in S}\sum_{i \in P_{s}} (r_{si}-0.2 \times c_{s}) \times q_{si} \times x_{si} + \alpha_{2} \ge 0 \space\space\space (25)
s∈S∑i∈Ps∑(rsi−0.2×cs)×qsi×xsi+α2≥0 (25)
∑
s
∈
S
v
∑
i
∈
P
s
(
d
s
i
−
0.3
)
×
x
s
i
+
β
v
≥
0
(
22
)
\sum_{s \in S_{v}}\sum_{i \in P_{s}}(d_{si} -0.3) \times x_{si} + \beta_{v} \ge 0 \space\space\space(22)
s∈Sv∑i∈Ps∑(dsi−0.3)×xsi+βv≥0 (22)
∑
s
∈
S
f
∑
i
∈
P
s
(
d
s
i
−
0.2
)
×
x
s
i
+
β
f
≥
0
(
26
)
\sum_{s \in S_{f}}\sum_{i \in P_{s}}(d_{si} -0.2) \times x_{si} + \beta_{f} \ge 0 \space\space\space(26)
s∈Sf∑i∈Ps∑(dsi−0.2)×xsi+βf≥0 (26)
∑
s
∈
S
p
∑
i
∈
P
s
(
d
s
i
−
0.1
)
×
x
s
i
+
β
p
≥
0
(
27
)
\sum_{s \in S_{p}}\sum_{i \in P_{s}}(d_{si} -0.1) \times x_{si} + \beta_{p} \ge 0 \space\space\space(27)
s∈Sp∑i∈Ps∑(dsi−0.1)×xsi+βp≥0 (27)
x
s
i
∈
{
0
,
1
}
∀
s
∈
S
,
∀
i
∈
P
s
(
10
)
x_{si} \in \{0,1\} \space\space\space \forall s \in S, \forall i \in P_{s} \space\space\space (10)
xsi∈{0,1} ∀s∈S,∀i∈Ps (10)
α
1
,
α
2
,
β
v
,
β
f
,
β
p
≥
0
(
19
)
\alpha_{1},\alpha_{2},\beta_{v},\beta_{f},\beta_{p} \ge 0 \space\space\space(19)
α1,α2,βv,βf,βp≥0 (19)
其中,
M
M
M 为极大地数,以便松弛变量尽可能取 0,及所有业务约束均被满足。
我们选择ORTools 建模,并选择 SCIP 求解。
详见代码(文末加粉丝群获取~~~)
求解结果如下:
最优解状态: 0
总利润: 36880.27
总成本: 123319.58
总营收: 160199.84999999998
总利润率:0.2990625657336815
总折扣率:0.05771901890183243
蔬菜利润率:0.12843251752888687
蔬菜折扣率:0.2994485707115351
国产水果利润率:0.2352903707735693
国产水果折扣率:0.20145441470807798
猪肉利润率:0.2583410761044007
猪肉折扣率:0.14393190181238136
我们发现:
模型求得了最优解,所有业务约束均被满足。 这说明了:精细化定价可以保证商家的利润,同时也能让消费者买到低价的商品,实现双赢。
当然,本文讲解的是最基础版本的定价算法,在实际业务落地时还需要考虑其他细化条件,如:连续多天定价、库存情况等。但整体求解框架不会有太大的改动。
附求解log如下:
presolving: (round 1, fast) 18 del vars, 6 del conss, 0 add conss, 0 chg bounds, 0 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs (round 2, fast) 18 del vars, 6 del conss, 0 add conss, 0 chg bounds, 12 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs (round 3, fast) 218 del vars, 8 del conss, 0 add conss, 0 chg bounds, 12 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs (round 4, exhaustive) 4178 del vars, 8 del conss, 0 add conss, 5 chg bounds, 12 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs Deactivated symmetry handling methods, since SCIP was built without symmetry detector (SYM=none). presolving (5 rounds: 5 fast, 2 medium, 2 exhaustive): 4178 deleted vars, 8 deleted constraints, 0 added constraints, 8 tightened bounds, 0 added holes, 12 changed sides, 0 changed coefficients 0 implications, 0 cliques presolved problem has 185999 variables (0 bin, 0 int, 0 impl, 185999 cont) and 3184 constraints 3184 constraints of type <linear> Presolving Time: 9.00 time | node | left |LP iter|LP it/n|mem/heur|mdpt |vars |cons |rows |cuts |sepa|confs|strbr| dualbound | primalbound | gap | compl. *24.0s| 1 | 0 | 44153 | - | LP | 0 | 185k|3184 |3184 | 0 | 0 | 0 | 0 | 3.694357e+04 | 3.694357e+04 | 0.00%| unknown 24.0s| 1 | 0 | 44153 | - | 851M | 0 | 185k|3184 |3184 | 0 | 0 | 0 | 0 | 3.694357e+04 | 3.694357e+04 | 0.00%| unknown SCIP Status : problem is solved [optimal solution found] Solving Time (sec) : 24.00 Solving Nodes : 1 Primal Bound : +3.69435660720141e+04 (1 solutions) Dual Bound : +3.69435660720141e+04 Gap : 0.00 % [I 21:09:48.234 NotebookApp] Saving file at /4.model_algorithm_elasticity.ipynb [I 21:11:47.859 NotebookApp] Saving file at /4.model_algorithm_elasticity.ipynb [I 21:13:48.244 NotebookApp] Saving file at /4.model_algorithm_elasticity.ipynb [I 21:15:44.505 NotebookApp] Saving file at /4.model_algorithm_elasticity.ipynb [I 21:15:48.779 NotebookApp] Starting buffering for b14080f5-0663-41c6-b4f6-ac64dcade9f1:9a94821c2c27446a9b8551c893a4613f [I 21:15:50.912 NotebookApp] Kernel restarted: b14080f5-0663-41c6-b4f6-ac64dcade9f1 [I 21:15:51.976 NotebookApp] Restoring connection for b14080f5-0663-41c6-b4f6-ac64dcade9f1:9a94821c2c27446a9b8551c893a4613f [I 21:15:51.976 NotebookApp] Replaying 3 buffered messages [I 21:17:54.218 NotebookApp] Saving file at /4.model_algorithm_elasticity.ipynb presolving: (round 1, fast) 18 del vars, 6 del conss, 0 add conss, 0 chg bounds, 0 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs (round 2, fast) 18 del vars, 6 del conss, 0 add conss, 0 chg bounds, 12 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs (round 3, fast) 218 del vars, 8 del conss, 0 add conss, 0 chg bounds, 12 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs (round 4, exhaustive) 4178 del vars, 8 del conss, 0 add conss, 5 chg bounds, 12 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs Deactivated symmetry handling methods, since SCIP was built without symmetry detector (SYM=none). presolving (5 rounds: 5 fast, 2 medium, 2 exhaustive): 4178 deleted vars, 8 deleted constraints, 0 added constraints, 8 tightened bounds, 0 added holes, 12 changed sides, 0 changed coefficients 0 implications, 0 cliques presolved problem has 185999 variables (0 bin, 0 int, 0 impl, 185999 cont) and 3184 constraints 3184 constraints of type <linear> Presolving Time: 10.00 time | node | left |LP iter|LP it/n|mem/heur|mdpt |vars |cons |rows |cuts |sepa|confs|strbr| dualbound | primalbound | gap | compl. *28.0s| 1 | 0 | 44372 | - | LP | 0 | 185k|3184 |3184 | 0 | 0 | 0 | 0 | 3.694604e+04 | 3.694604e+04 | 0.00%| unknown 28.0s| 1 | 0 | 44372 | - | 851M | 0 | 185k|3184 |3184 | 0 | 0 | 0 | 0 | 3.694604e+04 | 3.694604e+04 | 0.00%| unknown SCIP Status : problem is solved [optimal solution found] Solving Time (sec) : 28.00 Solving Nodes : 1 Primal Bound : +3.69460373439469e+04 (1 solutions) Dual Bound : +3.69460373439469e+04 Gap : 0.00 %
加粉丝群后见群公告获取~~~
粉丝1群二维码:
加不了群,请加管理员微信:IndustryOR
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。