昨天去迪士尼玩了14个项目……累坏
理论部分
首先讲一下消费束(Consumption bundle)。这里的基本假设是市场上只有两种物品,两种物品价格已知,消费者的效用函数已知,消费者的收入m固定(不含禀赋)。
所以,从本质上来说,我们要做的就是找到最优消费束(x*,y*)关于
的函数关系,即
其次是凹凸性:凹函数(concave),凸函数(convex),拟线性函数(Quasi-Linear)
上过课的同学一定能记得,计算Consumption bundle易错点是:对凹凸性不同的效用函数要分不同情况处理;含有Min()的函数其图像是折线(不可导);含有Max()的函数属于凸函数也要特殊处理。
1. 对于一般形式的函数对于一般的凹函数(e.g.
)
1)用求微分的diff()函数计算效用边际替代率MRS_U、价格边际替代率MRS_M。
2)由一阶最优化条件MRS_U = MRS_M,求解该方程即可得到最优解(x*,y*)。对于凹的拟线性函数(e.g.
):
步骤同上,但最后一步中 程序求出的解只包含x=a而不包含
对于一般的凸函数(e.g.
):
直接判别:比较预算约束线横截距点horizon和纵截距点vertical的效用大小,取较大的值。
2. 对于含有Min()的函数(e.g.
):
1)用正则匹配出
两个表达式ineq1,ineq2。
2)令
即为最优解所在的直线,令之与预算约束线求交点即为 (x*,y*)。
3. 对于含有Max()的函数:
处理方法同一般凸函数,直接判别横纵截距点。
程序实现
先举例补充一下sympy的基本用法:Eq(x+1, y) 表示等式x+1=y
solve(Eq(x+1, y), x) 表示求解等式x+1=y, 解得一个list, 包含一个dict解集{x: y-1}
x = Symbol('x') 表示定义x为一个变量,在输入输出中用'x'表示,在程序中用x表示
U.subs(y,y+1) 表示将表达式U中的所有变量y赋值/替换为y+1
程序可以应用的效用函数(Utility Function)范围是:
暂时不包含
这类的形式。
例题:效用函数
, 物品x的价格18,物品y价格1,总收入m是135,求最优消费束。
Step 1.在实际解题的过程中,由于sympy库所要求的输入格式太严格,我选择对输入的字符串做一个预处理。也就是insert()和initial()函数,其作用是在变量x或y前补上手写中容易省略的*号(乘号)。
def insert(original, new, pos):
'''Inserts new inside original at pos.'''
new = original[:pos] + new + original[pos:]
return new
def initial(s):
waiting = []
count = 0
for i in range(len(s) - 1):
if s[i] in '123456789.' and (s[i + 1] == 'x' or s[i + 1] == 'y'):
waiting.append(i)
for i in waiting:
count += 1
s = insert(s, '*', (i + count))
return s
Step 2. 函数凹凸类型判断:is_concave()函数
def is_concave():
global horizon, vertical, U
random_x1 = random.uniform(0, horizon)
random_y1 = solve(Eq(U. subs(x, random_x1), 4), y)[0] # 这个要把x带进去
random_x2 = random.uniform(0, horizon)
random_y2 = solve(Eq(U.subs(x, random_x2), 4), y)[0]
mp_x = (random_x1 + random_x2) / 2
mp_y = (random_y1 + random_y2) / 2
temp = U.subs(x, mp_x).subs(y, mp_y) - \
U.subs(x, random_x1).subs(y, random_y1)
if temp < 0:
return True
else:
return False
使用了凹函数的标准定义:若某一等效用线上任意两点连线上的点,其效用值大于该等效用线的效用值,则该效用函数是凹函数,否则为凸函数。
使用了random模块中的random()函数,随机在(0, horizon)的范围上产生random_x1、random_x2。并以Utility=4为例,计算得到相应的y1、y2值。最后比较(random_x1, y1)(random_x2, y2)的中点(mp_x, mp_y)的效用值和(random_x1, y1)的效用值,判断是否为凹函数。
Step 3. 分情况求解:
1)凸函数concave():
def concave():
global raw_U, horizon, vertical, Optimal_x, Optimal_y
temp = U.subs(x, horizon).subs(y, 0) - U.subs(y, vertical).subs(x, 0)
if temp > 0:
Optimal_x = horizon
Optimal_y = 0
elif temp == 0:
Optimal_x = horizon
Optimal_y = 0
else:
Optimal_x = 0
Optimal_y = vertical
return
2 ) Max函数concave_max():
同上,唯一区别是U和ineq1、ineq2
def concave_max():
global raw_U, horizon, vertical, Optimal_x, Optimal_y
temp = ineq1.subs(x, horizon).subs(y, 0) - ineq2.subs(y, vertical).subs(x, 0) #而顺序不一定,TODO
if temp > 0:
Optimal_x = horizon
Optimal_y = 0
elif temp == 0:
Optimal_x = horizon
Optimal_y = 0
else:
Optimal_x = 0
Optimal_y = vertical
return
2)凹函数convex():
def convex():
global raw_U, horizon, vertical, Optimal_x, Optimal_y, ans
try:
ans[0]
try:
Optimal_x = solve(Eq(ans[0][y], budegt_constrain_line))[0]
except:
Optimal_x = ans[0][x] # 拟线性函数
except:
print('Oppps!好像无解')
3) Min函数:非常简洁
boundary = solve(Eq(ineq1, ineq2), y)[0]
Optimal_x = solve(Eq(boundary, budegt_constrain_line))[0]
Step 4. 求解y*:
直接在预算约束线上带入x求解y
Optimal_y = budegt_constrain_line.subs(x, Optimal_x)
Step 5. 画图:将(Optimal_x,Optimal_y) 代入Utility Function,求出最大化的效用值
由于将sympy表达式转化为matplotlib表达式比较繁琐,所以还是选择用sympy.plot_implicit()作图
将预算集和最大化等效用线用p1.extend()一起画出来
画图时坐标范围是[0, 1.2倍截距]
Utility = U.subs(x, Optimal_x).subs(y, Optimal_y)
p1 = plot_implicit(Eq(U, Utility), (x, 0, 1.2 * horizon),
(y, 0, 1.2 * vertical), line_color='#df0070', title='Consumption bundle is ' + str(Consumption_bundle), show=False)
p1.extend(plot_implicit(M < m, (x, 0, 1.2 * horizon),
(y, 0, 1.2 * vertical), line_color='#00a8a8', show=False))
p1.show()
效果如本文封面图(颜色可以自己调整)
全部代码的90%已经分段贴在上面了,如果有兴趣要自己运行程序的可以跑下面的完整代码。含有例题信息的源代码github.com运行结果
下期预告
斯勒茨基方程(Slutsky Equation)
计算 需求
计算 收入效应、替代效应
听名字很可怕 其实……都是套路嘛……