salary02/env.py

239 lines
8.5 KiB
Python
Raw Normal View History

2022-08-29 10:39:29 +08:00
import agentpy as ap
2022-10-31 15:05:22 +08:00
import numpy as np
2022-08-29 10:39:29 +08:00
from random import uniform
2022-10-31 15:05:22 +08:00
import math
from traits.trait_types import self
2022-08-29 10:39:29 +08:00
from worker import WorkerAgent
from firm import FirmAgent
2022-10-31 15:05:22 +08:00
# plt.ion()
2022-08-29 10:39:29 +08:00
class Env(ap.Model):
float_market_size: float
percent_rh: float
percent_search: float
n_worker: int
n_firm: int
e_revenue: float
a_lst_worker: ap.AgentList
a_lst_firm: ap.AgentList
2022-10-31 15:05:22 +08:00
"""
Worker: Mean(s), Gini(s)
Firm: Mean(($$\pi_{j,t}$$)), Gini($$\pi_{j,t}$$)
Env: Percent(IsHired)
"""
out_w_avg_salary: float
out_w_gini_salary: float
out_f_avg_profit: float
out_f_gini_profit: float
out_w_percent_hired: float
2022-08-29 10:39:29 +08:00
def setup(self):
# 工作人员、企业数量、搜寻企业数量赋值
self.n_worker = self.p.n_worker
self.n_firm = self.p.n_firm
self.percent_search = self.p.percent_search
# 工人、企业列表
self.a_lst_worker = ap.AgentList(self)
self.a_lst_firm = ap.AgentList(self)
2023-01-15 21:51:47 +08:00
self.e_revenue = 5815100000000
2022-08-29 10:39:29 +08:00
# 在工人列表中添加工人
for i in range(self.n_worker):
# 初始化 workeragent并把alpha属性传过去
w = WorkerAgent(self, self.p.alpha)
self.a_lst_worker.append(w)
# 在企业列表中添加企业放入一个is_RH_ratio, 即有多大比例的企业是属于RH类型的
for i in range(self.n_firm):
# 对于企业属性true or false 的判断, 影响到firm 板块下, self.s_IsRH = is_RH 语句的判断
2023-01-15 21:51:47 +08:00
f = FirmAgent(self, self.p.is_RH_ratio >= uniform(0, 1), self.p.is_FH_ratio >= uniform(0, 1))
2022-08-29 10:39:29 +08:00
self.a_lst_firm.append(f)
def update_e_revenue(self):
self.e_revenue += 0.01 * self.e_revenue
def step(self):
self.update_e_revenue()
# 先清空每次的选择列表
self.a_lst_firm.empty_apply()
# 一开始worker要去选择很多firm
self.a_lst_worker.select_firm()
# 第二步, firm 去选 worker
self.a_lst_firm.select_worker()
2022-10-31 15:05:22 +08:00
self.a_lst_firm.update_yields()
self.provide_logit_share()
self.a_lst_firm.update_s_profit()
self.create_and_destroy_bankrupt_firms()
# self.picture_out()
self.update()
if self.t == 200:
2022-08-29 10:39:29 +08:00
self.stop()
2022-10-31 15:05:22 +08:00
# self.picture_out()
2022-08-29 10:39:29 +08:00
pass
2022-10-31 15:05:22 +08:00
def update(self):
lst_salary = []
n_hired = 0
for w in self.a_lst_worker:
lst_salary.append(w.s_salary)
if w.s_is_hired:
n_hired += 1
n_workers = len(lst_salary)
self.out_w_avg_salary = sum(lst_salary) / n_workers
self.out_w_gini_salary = self.gini(lst_salary)
lst_profit = []
n_w_firm = 0
for f in self.a_lst_firm:
lst_profit.append(f.s_profit)
if f.s_profit > 0:
n_w_firm += 1
n_firms = len(lst_profit)
self.out_f_avg_profit = sum(lst_profit) / n_firms
self.out_f_gini_profit = self.gini(lst_profit)
self.out_w_percent_hired = n_hired / n_workers
self.record('out_w_avg_salary')
self.record('out_w_gini_salary')
self.record('out_f_avg_profit')
self.record('out_f_gini_profit')
self.record('out_w_percent_hired')
def create_and_destroy_bankrupt_firms(self):
n_bankrupt_firms = 0
for f in self.a_lst_firm:
if f.s_value < 0:
2023-01-15 21:51:47 +08:00
# 直接淘汰企业(此处设定为清空企业员工,清空企业利润值和价值,相当于重新添加了一个新的企业?)
2022-10-31 15:05:22 +08:00
n_bankrupt_firms += 1
2023-01-15 21:51:47 +08:00
for work in f.l_senior_workers:
work.s_is_hired = False
for work in f.l_junior_workers:
work.s_is_hired = False
f.s_profit = 0
f.s_value = 0
else:
if f.s_profit < 0:
if f.s_IsFH:
# 第一种方式,末位淘汰制,淘汰所有员工中生产价值最低的
f.l_junior_workers.sort(key=lambda x: x['s_yield'], reverse=True)
for work in f.l_junior_workers:
# f.l_junior_workers.sort(key=lambda x: x['s_yield'], reverse=True)
if work == f.l_junior_workers[-1]:
work.s_is_hired = False
else:
2022-10-31 15:05:22 +08:00
# 第二种方式,末位淘汰制,淘汰所有员工中单位产值(产值/工资)价值最低的
2023-01-15 21:51:47 +08:00
f.l_all_w = f.l_junior_workers + f.l_senior_workers
for work in f.l_all_w:
work.unit_yield_salary = work.s_yield * 10000 / work.s_salary
f.l_all_w.sort(key=lambda x: x['unit_yield_salary'], reverse=True)
if work == f.l_all_w[-1]:
work.s_is_hired = False
2022-10-31 15:05:22 +08:00
# for f in self.a_lst_firm:
# if f.s_profit < 0: # TODO
# n_bankrupt_firms += 1
# for work in f.l_senior_workers:
# work.s_is_hired = False
# for work in f.l_junior_workers:
# work.s_is_hired = False
# self.a_lst_firm.remove(f)
# del f
# if n_bankrupt_firms > 0:
# for _ in range(n_bankrupt_firms):
# f = FirmAgent(self, self.p.is_RH_ratio >= uniform(0, 1))
# self.a_lst_firm.append(f)
assert len(self.a_lst_firm) == self.n_firm, \
f'current num firm {len(self.a_lst_firm)} != expected num firm {self.n_firm}'
2022-08-29 10:39:29 +08:00
def provide_lst_random_firms(self, the_worker: WorkerAgent):
'''选择企业数量 = 企业总数*百分比
选择企业的列表 = 随机选择的企业的个数
如果员工处于被雇佣的状态
2022-10-31 15:05:22 +08:00
如果员工工作的企业在随机选定的企业列表中
2022-08-29 10:39:29 +08:00
打开列表中的企业
移除该企业
返回值移除后再重新选择随机选择企业
否则
返回值选择企业列表
'''
n_select_firms = int(self.percent_search * self.n_firm)
a_lst_select_firms = self.a_lst_firm.random(n_select_firms)
if the_worker.s_is_hired:
if the_worker.working_firm in a_lst_select_firms:
# 转换为 list
lst_f = list(self.a_lst_firm)
lst_f.remove(the_worker.working_firm)
return ap.AgentList(self, lst_f).random(n_select_firms)
# 假如以上都不满足, 直接返回
return ap.AgentList(self, a_lst_select_firms)
2022-10-31 15:05:22 +08:00
def provide_logit_share(self):
fen_mu = 0
for f in self.a_lst_firm:
fen_mu += math.exp(f.s_a_yield)
for f in self.a_lst_firm:
f.s_revenue = self.e_revenue * math.exp(f.s_a_yield) / fen_mu
# def picture_out(self, the_worker: WorkerAgent):
# a = self.t
# b = len(the_worker.s_salary)
# plt.plot(a, b, 'ro')
# return plt.show()
@staticmethod
def gini(x):
if len(x) == 0:
return 0
if sum(x) == 0:
return 0
x = np.array(x)
mad = np.abs(np.subtract.outer(x, x)).mean() # Mean absolute difference
r_mad = mad / np.mean(x) # Relative mean absolute difference
return 0.5 * r_mad
2022-08-29 10:39:29 +08:00
if __name__ == '__main__':
2022-12-09 22:07:01 +08:00
# dict_para = {'n_worker': 1000,
# 'n_firm': 100,
# 'percent_search': 0.2,
# 'alpha': 0.5,
# 'is_RH_ratio': 0.5}
# my_model = Env(dict_para)
2022-10-31 15:05:22 +08:00
#
# print(my_model.gini([10000, 0, 0, 0, 0, 0, 0]))
# my_model.run()
# # a = range(0, 101)
# # b = len(WorkerAgent.s_yield)
# # plt.plot(a,b)
# # plt.show()
# plt.show()
parameters = {
2023-01-15 21:51:47 +08:00
'n_worker': 1000,
'n_firm': 100,
2022-10-31 15:05:22 +08:00
'percent_search': 0.2,
'alpha': 0.5,
# 'alpha': ap.Range(0, 1, 0.5),
'is_RH_ratio': 0.5,
2023-01-15 21:51:47 +08:00
'is_FH_ratio': 0.5,
2022-10-31 15:05:22 +08:00
}
sample = ap.Sample(parameters)
# sample = ap.Sample(parameters, n=3)
#
exp = ap.Experiment(Env, sample, iterations=10, record=True)
results = exp.run()
results['variables']['Env'].to_excel('env_data.xlsx', engine='openpyxl')
2022-08-29 10:39:29 +08:00