1. 供应链双零售商模型解析与Mathematica复现指南
在供应链管理研究中,一个供应商对应多个零售商的模型是经典研究场景。最近我在复现某篇论文时,发现其中关于单供应商-双零售商模型的求解过程特别具有代表性。这个模型不仅涉及库存优化、定价策略等核心供应链问题,还能延伸出博弈论中的竞争与合作分析。本文将分享如何用Mathematica完整复现这个模型的求解过程,包括模型建立、参数设置、方程求解和可视化分析的全套方法。
这个模型特别适合研究供应链中的横向竞争关系——当两个零售商面对同一供应商时,他们的订购策略会如何相互影响?作为从业十余年的供应链系统优化专家,我认为Mathematica的符号计算和数值优化能力,能完美处理这类包含复杂约束的非线性规划问题。相比Python需要调各种库,Mathematica提供了从建模到求解的一站式环境,特别适合学术研究的快速验证。
2. 模型基础架构与关键假设
2.1 基础模型框架
论文中的基础模型包含三个主体:
- 单一供应商(Supplier):负责生产产品并以批发价w向零售商供货
- 零售商1(Retailer1)和零售商2(Retailer2):分别以零售价p₁和p₂向市场销售产品
需求函数采用线性形式:
- 零售商1的需求:D₁ = a - bp₁ + cp₂
- 零售商2的需求:D₂ = a - bp₂ + cp₁
(其中a>0, b>0, 0<c<b保证自身价格影响大于交叉影响)
2.2 模型的核心参数设置
在Mathematica中我们首先定义这些基础参数:
mathematica复制ClearAll["Global`*"];
a = 100; (* 基础市场需求量 *)
b = 2; (* 自身价格弹性系数 *)
c = 1; (* 交叉价格弹性系数 *)
w = 20; (* 供应商批发价 *)
重要提示:参数设置必须满足b>c>0的条件,否则会出现不符合经济意义的解。这是模型成立的前提条件。
2.3 利润函数的建立
两个零售商的利润函数分别为:
- π₁ = (p₁ - w)D₁ = (p₁ - w)(a - bp₁ + c*p₂)
- π₂ = (p₂ - w)D₂ = (p₂ - w)(a - bp₂ + c*p₁)
在Mathematica中表示为:
mathematica复制profit1 = (p1 - w)*(a - b*p1 + c*p2);
profit2 = (p2 - w)*(a - b*p2 + c*p1);
3. 模型求解与博弈分析
3.1 纳什均衡求解
假设两个零售商同时决策,形成非合作博弈。我们需要求纳什均衡解,即同时满足:
- p₁* = argmax π₁(p₁, p₂*)
- p₂* = argmax π₂(p₂, p₁*)
在Mathematica中可以通过求一阶条件并解方程组实现:
mathematica复制foc1 = D[profit1, p1] == 0;
foc2 = D[profit2, p2] == 0;
equilibrium = Solve[{foc1, foc2}, {p1, p2}];
p1Opt = p1 /. equilibrium[[1]];
p2Opt = p2 /. equilibrium[[1]];
3.2 结果可视化分析
为了更直观理解均衡结果,我们可以绘制利润函数的三维图像:
mathematica复制Plot3D[{profit1, profit2}, {p1, 0.5*w, 3*w}, {p2, 0.5*w, 3*w},
AxesLabel -> {"p1", "p2", "Profit"},
PlotLegends -> {"Retailer1 Profit", "Retailer2 Profit"}]
通过添加交互式控件,可以动态观察参数变化对均衡的影响:
mathematica复制Manipulate[
Plot3D[(p1 - w)*(a - b*p1 + c*p2), {p1, 10, 50}, {p2, 10, 50}],
{{a, 100}, 50, 200}, {{b, 2}, 1, 5}, {{c, 1}, 0, 2}, {{w, 20}, 10, 30}]
4. 模型扩展与灵敏度分析
4.1 合作情形下的联合利润最大化
如果两个零售商形成联盟,则变为求解:
max π_total = π₁ + π₂
对应的Mathematica求解代码:
mathematica复制totalProfit = profit1 + profit2;
focTotal1 = D[totalProfit, p1] == 0;
focTotal2 = D[totalProfit, p2] == 0;
coopSolution = Solve[{focTotal1, focTotal2}, {p1, p2}];
4.2 参数灵敏度分析
研究关键参数变化对均衡价格的影响:
mathematica复制sensitivityAnalysis = Table[
aVal = 50 + 10*i;
sol = Solve[{D[(p1 - w)*(aVal - b*p1 + c*p2), p1] == 0,
D[(p2 - w)*(aVal - b*p2 + c*p1), p2] == 0}, {p1, p2}];
{aVal, p1 /. sol[[1]], p2 /. sol[[1]]},
{i, 0, 10}];
ListLinePlot[Transpose[{sensitivityAnalysis[[All, 1]], #}] & /@
{sensitivityAnalysis[[All, 2]], sensitivityAnalysis[[All, 3]]},
PlotLegends -> {"p1", "p2"}, AxesLabel -> {"a", "Price"}]
5. 完整论文复现流程
5.1 数据准备与模型校准
实际论文复现时,需要根据原文数据校准参数。假设论文给出了某组均衡价格,我们可以反向求解参数:
mathematica复制knownP1 = 35; knownP2 = 36;
paramSolution = FindInstance[
{(knownP1 - w)*(a - b*knownP1 + c*knownP2) == 1200,
(knownP2 - w)*(a - b*knownP2 + c*knownP1) == 1250,
b > c > 0, a > 0},
{a, b, c}, Reals]
5.2 完整求解流程封装
将整个求解过程封装为可重用的函数:
mathematica复制SolveRetailerCompetition[a_, b_, c_, w_] := Module[
{p1, p2, profit1, profit2, foc1, foc2, sol, eqPrices},
profit1 = (p1 - w)*(a - b*p1 + c*p2);
profit2 = (p2 - w)*(a - b*p2 + c*p1);
foc1 = D[profit1, p1] == 0;
foc2 = D[profit2, p2] == 0;
sol = Solve[{foc1, foc2}, {p1, p2}];
eqPrices = {p1, p2} /. sol[[1]];
Return[<|
"EquilibriumPrices" -> eqPrices,
"Retailer1Profit" -> (profit1 /. {p1 -> eqPrices[[1]], p2 -> eqPrices[[2]]}),
"Retailer2Profit" -> (profit2 /. {p1 -> eqPrices[[1]], p2 -> eqPrices[[2]]})
|>]
]
6. 常见问题与调试技巧
6.1 模型无解情况处理
当出现"Solve: Equations may not give solutions for all variables"警告时,通常是因为:
- 参数组合不满足b>c>0的条件
- 方程存在矛盾(如a值过小导致需求为负)
解决方法:
mathematica复制(* 检查参数有效性 *)
Assert[b > c > 0 && a > 0];
(* 使用NSolve获取数值解 *)
numericSol = NSolve[{foc1, foc2}, {p1, p2}, Reals]
6.2 多均衡解的筛选
某些参数组合可能导致多个均衡解,需要根据经济意义筛选:
mathematica复制allSolutions = Solve[{foc1, foc2}, {p1, p2}];
validSolutions = Select[allSolutions,
(p1 > w && p2 > w &&
(a - b*p1 + c*p2) > 0 &&
(a - b*p2 + c*p1) > 0) /. # &]
6.3 性能优化技巧
对于复杂模型,可以采用以下优化:
- 提前符号化简:
mathematica复制profit1 = Simplify[(p1 - w)*(a - b*p1 + c*p2)];
- 使用//.重复替换规则
- 对固定参数使用With注入:
mathematica复制With[{a=100, b=2, c=1}, Solve[...]]
7. 高级应用扩展
7.1 引入供应商定价决策
将批发价w作为供应商决策变量:
mathematica复制supplierProfit = (w - cost)*(D1 + D2) /. {p1 -> p1Opt[w], p2 -> p2Opt[w]};
supplierOpt = Solve[D[supplierProfit, w] == 0, w];
7.2 随机需求模型
引入随机需求因子ε~N(0,σ²):
mathematica复制demand1 = a - b*p1 + c*p2 + σ*ε1;
demand2 = a - b*p2 + c*p1 + σ*ε2;
expectedProfit1 = Expectation[(p1 - w)*demand1, ε1 \[Distributed] NormalDistribution[]];
7.3 微分博弈模型
考虑动态定价策略:
mathematica复制sol = NDSolve[{
p1'[t] == k1*(D[profit1, p1] /. {p1 -> p1[t], p2 -> p2[t]}),
p2'[t] == k2*(D[profit2, p2] /. {p1 -> p1[t], p2 -> p2[t]}),
p1[0] == p10, p2[0] == p20},
{p1, p2}, {t, 0, 10}]
8. 完整复现案例演示
假设要复现的论文给出了以下情景:
- 基础需求a=120
- 价格弹性b=3, c=1.5
- 批发价w=25
- 成本cost=10
完整复现代码:
mathematica复制(* 参数初始化 *)
params = {a -> 120, b -> 3, c -> 1.5, w -> 25, cost -> 10};
(* 零售商均衡求解 *)
retailerSol = Solve[{
D[(p1 - w)*(a - b*p1 + c*p2), p1] == 0,
D[(p2 - w)*(a - b*p2 + c*p1), p2] == 0} /. params, {p1, p2}];
(* 供应商利润最大化 *)
supplierProfit = (w - cost)*((a - b*p1 + c*p2) + (a - b*p2 + c*p1)) /.
Join[retailerSol[[1]], params];
wOpt = w /. Last@Maximize[supplierProfit, w];
(* 打印最终结果 *)
Print["Optimal wholesale price: ", wOpt];
finalPrices = {p1, p2} /. retailerSol[[1]] /. w -> wOpt;
Print["Equilibrium retail prices: ", finalPrices];
9. 可视化分析进阶
9.1 价格反应曲线
mathematica复制react1 = Solve[D[profit1, p1] == 0, p1][[1]];
react2 = Solve[D[profit2, p2] == 0, p2][[1]];
Plot[{p2 /. react1, p1 /. react2 /. p2 -> p1}, {p1, 20, 50},
AxesLabel -> {"p1", "p2"}, PlotLegends -> {"Retailer1's reaction", "Retailer2's reaction"}]
9.2 利润等高线分析
mathematica复制ContourPlot[profit1 /. params /. w -> wOpt,
{p1, 0.5*wOpt, 1.5*wOpt}, {p2, 0.5*wOpt, 1.5*wOpt},
Contours -> 20, PlotLegends -> Automatic,
FrameLabel -> {"p1", "p2", "Retailer1 Profit"}]
10. 模型验证与稳健性测试
10.1 对称性测试
验证当参数对称时,均衡价格是否相同:
mathematica复制symTest = SolveRetailerCompetition[100, 2, 1, 20];
If[Abs[symTest["EquilibriumPrices"][[1]] - symTest["EquilibriumPrices"][[2]]] < 0.001,
Print["Symmetry test passed"], Print["Symmetry test failed"]]
10.2 边界情况验证
检查当c→0时,是否退化为两个独立垄断定价:
mathematica复制monopolyPrice = (a + b*w)/(2*b);
limitCase = Limit[SolveRetailerCompetition[100, 2, c, 20]["EquilibriumPrices"][[1]], c -> 0];
If[Abs[limitCase - monopolyPrice] < 0.001,
Print["Limit test passed"], Print["Limit test failed"]]
通过Mathematica的符号计算能力,我们可以建立完整的供应链模型分析框架,从基础模型到扩展应用,系统性地复现论文中的各类分析。这种方法不仅适用于学术研究,也能为实际供应链决策提供量化支持。
