概述
Managerial Negotiation 第五周的案例,强调了在谈判前要发现双方共同利益、maximize value creation。在本案例情境中,谈判轮数增加会导致双方可变成本增加,且谈判核心-\(w\) 值的增加会导致双方总福利的降低。在设计本模拟工具时也考虑了两种情况:
君子条约: 在罢工(即造成双方成本增加)开始前确定\(w\) 在 \(0.5-0.52\) 范围内,对两者较为公平且最大化总价值
消耗战(War of Attrition): 通过模拟发现作为Kunzler(希望w小),利用前两轮压价、第三轮结束通常能获得最好结果,但该结果仍比君子条约差;作为Arnold(希望w大),第六轮后结果比君子条约差,但在此之前有较大的议价空间。没有达成君子条约默契并消耗至第六轮,最终结果\(w\) 通常在0.6左右,Arnold小赚而Kunzler较亏
针对消耗战情况,又设计了一个函数find_Case
来针对当前已知信息(轮数,己方出价,对方出价),找出一个模拟情况,从而对未来局势有所判断。
1 def find_Case (round, w_K, w_A )
案例材料
代码部分
Import
1 2 3 4 5 import numpy as npimport matplotlib.pyplot as pltimport pandas as pdimport seaborn as snsimport scipy.stats as spst
Simulation1
Distribution: triangular(0,0,1)
1 h = plt.hist(np.random.triangular(0 , 0 , 1 , 10000 ),bins = 200 , density=True )
Simulation Code
As two parties approaching the final \(w\) , they do not calculate their gain&loss in each round. The next bid is solely subject to the triangular distribution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def Kunzler (w, d ): return -5 *w -(0.1 *d + 0.015 *d**2 ) def Arnold (w, d ): return 4 *w - (0.05 *d + 0.005 *d**2 ) def simulation (): bid_Kunzler = 10 bid_Arnold = 11 round = 0 while ((bid_Kunzler+0.0004 < bid_Arnold) & (round <=22 )): round += 1 if (np.random.random()>0.2 ): bid_Kunzler += (bid_Arnold - bid_Kunzler)*np.random.triangular(0 , 0 , 1 ) if (np.random.random()>0.2 ): bid_Arnold -= (bid_Arnold - bid_Kunzler)*np.random.triangular(0 , 0 , 1 ) round -= 1 if round==22 : w = 0 else : w = np.around(bid_Kunzler, 3 ) - 10 d = (round > 2 )*(round - 2 ) return (round, w, Kunzler(w, d), Arnold(w, d))
Run Simulation 100000 times
1 sim = np.array([simulation() for i in range(100000 )])
1 df_sim = pd.DataFrame(sim, columns = ["round" , "w" , "Kunzler" , "Arnold" ])
1 df_sim = df_sim.assign(total = lambda x: x.Kunzler + x.Arnold)
Scatterplot (Kunzler, Arnold), hue="round" / "w"
1 2 3 plt.figure(figsize=(12 ,8 )) sns.scatterplot(data=df_sim, x="Kunzler" , y="Arnold" , hue="round" ) plt.show()
1 2 3 plt.figure(figsize=(12 ,8 )) sns.scatterplot(data=df_sim, x="Kunzler" , y="Arnold" , hue="w" ) plt.show()
Analysis
1 df_sim.sort_values(["round" , "Kunzler" ]).groupby("round" ).agg("mean" )
w
Kunzler
Arnold
total
round
1.0
0.750143
-3.750714
3.000571
-0.750143
2.0
0.741615
-3.708077
2.966462
-0.741615
3.0
0.645737
-3.343684
2.527947
-0.815737
4.0
0.645440
-3.487198
2.461759
-1.025440
5.0
0.615148
-3.510739
2.265591
-1.245148
6.0
0.603678
-3.658389
2.134711
-1.523678
7.0
0.590758
-3.828791
1.988033
-1.840758
8.0
0.584565
-4.062823
1.858259
-2.204565
9.0
0.575110
-4.310551
1.705441
-2.605110
10.0
0.571312
-4.616559
1.565247
-3.051312
11.0
0.569395
-4.961974
1.422579
-3.539395
12.0
0.561997
-5.309983
1.247986
-4.061997
13.0
0.556362
-5.696812
1.070450
-4.626362
14.0
0.552071
-6.120357
0.888286
-5.232071
15.0
0.559690
-6.633452
0.743762
-5.889690
16.0
0.546763
-7.073814
0.507051
-6.566763
17.0
0.540981
-7.579907
0.288926
-7.290981
18.0
0.540375
-8.141877
0.081502
-8.060375
19.0
0.532353
-8.696763
-0.165590
-8.862353
20.0
0.581473
-9.567364
-0.194109
-9.761473
21.0
0.622667
-10.428333
-0.264333
-10.692667
22.0
0.000000
-8.000000
-3.000000
-11.000000
Try to end it early... The upperright midpoint looks good
1 2 3 sns.set_theme(style="ticks" , font_scale=1.25 ,) sns.jointplot(data=df_sim, y="Kunzler" , x="Arnold" , hue="round" ,height=8 ) plt.show()
/usr/local/lib/python3.6/dist-packages/seaborn/distributions.py:305: UserWarning: Dataset has 0 variance; skipping density estimate.
warnings.warn(msg, UserWarning)
/usr/local/lib/python3.6/dist-packages/seaborn/distributions.py:305: UserWarning: Dataset has 0 variance; skipping density estimate.
warnings.warn(msg, UserWarning)
If we end early before round3, what would be a good proposition? Answer: \(w\in [0.5,0.53]\)
1 df_early = df_sim.loc[df_sim["round" ]<=3 ].sort_values("total" , ascending=False )
1 (df_early["Kunzler" ].min() + df_early["Kunzler" ].max()) / 2
-2.6799999999999997
1 (df_early["Arnold" ].min() + df_early["Arnold" ].max()) / 2
2.026500000000002
1 Arnold(0.53 ,0 ), Kunzler(0.53 ,0 )
(2.12, -2.6500000000000004)
1 Arnold(0.5 ,0 ), Kunzler(0.5 ,0 )
(2.0, -2.5)
1 2 3 plt.figure(figsize=(12 ,8 )) sns.scatterplot(data=df_early, x="Arnold" , y="Kunzler" , hue="round" ) plt.show()
Simulation 2: What if my counterpart does not end early?
Another simulation function: Exhibits the process of negotiation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def simulation (): bid_Kunzler = 10 bid_Arnold = 11 round = 0 rows = [] while ((bid_Kunzler+0.004 < bid_Arnold) & (round <=22 )): round += 1 if (np.random.random()>0.2 ): bid_Kunzler += (bid_Arnold - bid_Kunzler)*np.random.triangular(0 , 0 , 1 ) if (np.random.random()>0.2 ): bid_Arnold -= (bid_Arnold - bid_Kunzler)*np.random.triangular(0 , 0 , 1 ) w_Kunzler = bid_Kunzler- 10 w_Arnold = bid_Arnold-10 d = (round > 2 )*(round - 2 ) Kunzler_ = Kunzler(w_Kunzler, d) Arnold_ = Arnold(w_Arnold, d) rows.append(np.array([round, w_Kunzler, w_Arnold, Kunzler_, Arnold_])) df = pd.DataFrame(np.array(rows), columns = ["round" , "w_Kunzler" , "w_Arnold" , "Kunzler_" , "Arnold_" ]) df = df.assign(sum = lambda x: x.Kunzler_ + x.Arnold_) return df
round
w_Kunzler
w_Arnold
Kunzler_
Arnold_
sum
0
1.0
0.000000
0.868807
0.000000
3.475230
3.475230
1
2.0
0.000000
0.420516
0.000000
1.682066
1.682066
2
3.0
0.000297
0.420516
-0.116485
1.627066
1.510581
3
4.0
0.107588
0.201068
-0.797939
0.684272
-0.113667
4
5.0
0.132680
0.157974
-1.098401
0.436896
-0.661505
5
6.0
0.147227
0.156502
-1.376134
0.346006
-1.030128
6
7.0
0.149804
0.156216
-1.624022
0.249866
-1.374156
7
8.0
0.151529
0.156216
-1.897647
0.144866
-1.752782
8
9.0
0.155463
0.155972
-2.212317
0.028890
-2.183427
-3.0
-8.0
1 2 3 4 5 6 7 8 9 10 11 def find_Case (round, w_K, w_A ): while (True ): df = simulation() try : row = df.iloc[round-1 ] flag = (np.abs(row["w_Kunzler" ]-w_K)<0.01 ) & (np.abs(row["w_Arnold" ]-w_A)<0.01 ) except : flag = False if (flag): break return df
round
w_Kunzler
w_Arnold
Kunzler_
Arnold_
sum
0
1.0
0.000000
1.000000
0.000000
4.000000
4.000000
1
2.0
0.000000
1.000000
0.000000
4.000000
4.000000
2
3.0
0.382837
0.997914
-2.029186
3.936654
1.907469
3
4.0
0.387834
0.603973
-2.199168
2.295893
0.096725
4
5.0
0.495310
0.586222
-2.911552
2.149887
-0.761664
5
6.0
0.529410
0.584511
-3.287050
2.058045
-1.229006
6
7.0
0.529410
0.579932
-3.522050
1.944727
-1.577323
7
8.0
0.533581
0.579932
-3.807903
1.839727
-1.968176
8
9.0
0.541261
0.577473
-4.141303
1.714890
-2.426413
9
10.0
0.541261
0.577473
-4.466303
1.589890
-2.876413
10
11.0
0.541261
0.575655
-4.821303
1.447619
-3.373685
11
12.0
0.572203
0.575655
-5.361013
1.302619
-4.058394
round
w_Kunzler
w_Arnold
Kunzler_
Arnold_
sum
0
1.0
0.000000
1.000000
0.000000
4.000000
4.000000
1
2.0
0.000000
1.000000
0.000000
4.000000
4.000000
2
3.0
0.000000
0.470998
-0.115000
1.828994
1.713994
3
4.0
0.000000
0.337204
-0.260000
1.228817
0.968817
4
5.0
0.000000
0.094733
-0.435000
0.183932
-0.251068
5
6.0
0.000000
0.094733
-0.640000
0.098932
-0.541068
6
7.0
0.000000
0.072679
-0.875000
-0.084283
-0.959283
7
8.0
0.009111
0.068337
-1.185556
-0.206651
-1.392207
8
9.0
0.044854
0.058973
-1.659270
-0.359107
-2.018377
9
10.0
0.047908
0.056863
-1.999541
-0.492550
-2.492091
10
11.0
0.048806
0.055739
-2.359032
-0.632043
-2.991074
11
12.0
0.048806
0.052226
-2.744032
-0.791096
-3.535128
round
w_Kunzler
w_Arnold
Kunzler_
Arnold_
sum
0
1.0
0.155860
0.919539
-0.779300
3.678158
2.898858
1
2.0
0.262073
0.819940
-1.310366
3.279758
1.969392
2
3.0
0.304963
0.808350
-1.639815
3.178401
1.538586
3
4.0
0.304963
0.597116
-1.784815
2.268465
0.483650
4
5.0
0.400535
0.532053
-2.437677
1.933211
-0.504466
5
6.0
0.400584
0.417896
-2.642919
1.391584
-1.251335
6
7.0
0.412972
0.415010
-2.939859
1.285039
-1.654820
Do not concede before Round 4!!!
1 2 %cd /content/drive/My Drive/20FA !jupyter nb