2nd commit
This commit is contained in:
parent
94474cbf91
commit
4e1084b517
|
@ -0,0 +1 @@
|
|||
worker.py
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
91
0829/env.py
91
0829/env.py
|
@ -1,91 +0,0 @@
|
|||
import agentpy as ap
|
||||
|
||||
from random import uniform
|
||||
|
||||
from worker import WorkerAgent
|
||||
from firm import FirmAgent
|
||||
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
self.e_revenue = 119.3
|
||||
|
||||
# 在工人列表中添加工人
|
||||
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 语句的判断
|
||||
f = FirmAgent(self, self.p.is_RH_ratio >= uniform(0, 1))
|
||||
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()
|
||||
|
||||
if self.t == 100:
|
||||
self.stop()
|
||||
pass
|
||||
|
||||
def provide_lst_random_firms(self, the_worker: WorkerAgent):
|
||||
'''选择企业数量 = 企业总数*百分比
|
||||
选择企业的列表 = 随机选择的企业的个数
|
||||
如果员工处于被雇佣的状态:
|
||||
如果员工工作的企业在随机选定的企业列表中:
|
||||
打开列表中的企业
|
||||
移除该企业
|
||||
返回值:移除后,再重新选择随机选择企业
|
||||
否则:
|
||||
返回值:选择企业列表
|
||||
'''
|
||||
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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dict_para = {'n_worker': 100,
|
||||
'n_firm': 20,
|
||||
'percent_search': 0.2,
|
||||
'alpha': 0.5,
|
||||
'is_RH_ratio': 0.5}
|
||||
my_model = Env(dict_para)
|
||||
my_model.run()
|
||||
|
||||
|
138
0829/firm.py
138
0829/firm.py
|
@ -1,138 +0,0 @@
|
|||
import math
|
||||
from typing import Union, Any
|
||||
|
||||
import agentpy as ap
|
||||
from random import uniform, randint
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import numpy as np
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from worker import WorkerAgent
|
||||
|
||||
|
||||
class FirmAgent(ap.Agent):
|
||||
c_incentive: float
|
||||
s_IsRH: bool
|
||||
s_avg_senior_yield: float
|
||||
s_avg_junior_yield: float
|
||||
s_a_yield: float
|
||||
# s_salary: float
|
||||
initial_f_salary: float
|
||||
s_revenue: float
|
||||
s_profit: float
|
||||
l_senior_workers: list
|
||||
l_junior_workers: list
|
||||
l_applied_workers: list
|
||||
|
||||
def setup(self, is_RH):
|
||||
self.c_incentive = uniform(0, 1)
|
||||
# self.s_profit = randint(10, 20)
|
||||
self.l_applied_workers = []
|
||||
self.s_IsRH = is_RH
|
||||
self.initial_f_salary = randint(8000, 10000)
|
||||
|
||||
def apply(self, the_worker):
|
||||
self.l_applied_workers.append(the_worker)
|
||||
|
||||
def empty_apply(self):
|
||||
self.l_applied_workers = []
|
||||
|
||||
def select_worker(self):
|
||||
'''
|
||||
企业找到最想招聘的员工
|
||||
:return:
|
||||
'''
|
||||
n_workers = len(self.l_applied_workers)
|
||||
if n_workers > 0:
|
||||
selected_worker = None
|
||||
if n_workers > 1:
|
||||
# 对员工产出进行排队和比较
|
||||
# 先判断是什么选择方式
|
||||
if self.s_IsRH:
|
||||
max_s_yield, best_worker = 0.0, None
|
||||
for the_worker in self.l_applied_workers:
|
||||
if the_worker.s_yield > max_s_yield:
|
||||
max_s_yield = the_worker.s_yield
|
||||
best_worker = the_worker
|
||||
selected_worker = best_worker
|
||||
else:
|
||||
selected_worker = self.l_applied_workers[0] # TODO
|
||||
# print(f'{self}: my best firm is {best_firm} from {n_firms} firms with utility {max_utility}')
|
||||
# return best_worker
|
||||
# 当企业是想要利用产出最高的员工时,从申请的员工中选出产出最高的员工
|
||||
# if self.s_IsRH :
|
||||
# # 计算该名员工的工资水平: 原有工资水平* (1+incentive)
|
||||
# # bw_salary = self.best_worker.salary()
|
||||
#
|
||||
# # 将该名员工的产出与公司原有员工的产出进行对比,如果高于senior列表中的最后一名的产出,就进入senior_list, 否则进入junior_list
|
||||
# self.l_senior_workers.append(best_worker)
|
||||
# else:
|
||||
# self.l_junior_workers.append(best_worker)
|
||||
# # best_worker.apply(self)
|
||||
# else:
|
||||
# # 计算由于改名员工下一期的薪资总数(根据薪资函数更新)以及企业下一期的利润的差值,并选出最大值
|
||||
else:
|
||||
selected_worker = self.l_applied_workers[0]
|
||||
selected_worker.update_working_firm_is_hired(self)
|
||||
self.update_two_worker_list(selected_worker)
|
||||
|
||||
def update_two_worker_list(self, new_worker):
|
||||
lst_all_worker = self.l_senior_workers + self.l_junior_workers + [new_worker]
|
||||
lst_sorted = lst_all_worker.sort(key=lambda x: x['s_yield'], reverse=True) # from highest yield to lowest
|
||||
n_all_worker = len(lst_all_worker)
|
||||
# 向上取整数值
|
||||
n_senior_worker = math.ceil(n_all_worker * 0.2)
|
||||
n_junior_worker = n_all_worker - n_senior_worker
|
||||
self.l_senior_workers = lst_sorted[:n_senior_worker]
|
||||
if n_junior_worker == 0:
|
||||
self.l_junior_workers = []
|
||||
else:
|
||||
self.l_junior_workers = lst_sorted[n_senior_worker:]
|
||||
|
||||
def update_yields(self): # 需要改
|
||||
n_sw, n_jw = len(self.l_senior_workers), len(self.l_junior_workers)
|
||||
# acc_all_yield = 0
|
||||
|
||||
if n_sw == 0:
|
||||
self.s_avg_senior_yield = 0
|
||||
else:
|
||||
s_acc_senior_yield = 0
|
||||
for sw in self.l_senior_workers:
|
||||
# 加入工人主体的产出属性
|
||||
s_acc_senior_yield += sw.s_yield
|
||||
# acc_all_yield += sw.s_yield
|
||||
self.s_avg_senior_yield = s_acc_senior_yield / n_sw
|
||||
|
||||
if n_jw == 0:
|
||||
self.s_avg_junior_yield = 0
|
||||
else:
|
||||
s_acc_junior_yield = 0
|
||||
for jw in self.l_junior_workers:
|
||||
# 加入工人主体的产出属性
|
||||
s_acc_junior_yield += jw.s_yield
|
||||
self.s_avg_junior_yield = s_acc_junior_yield / n_jw
|
||||
self.s_a_yield = 0.8 * self.s_avg_senior_yield + 0.2 * self.s_avg_junior_yield
|
||||
|
||||
def logit_share(self):
|
||||
logit_share = math.exp(self.s_a_yield) / np.sum(math.exp(self.s_a_yield))
|
||||
return logit_share
|
||||
|
||||
def sum_salary(self, l_senior_workers, l_junior_workers):
|
||||
'''
|
||||
计算某公司整体的薪金水平
|
||||
'''
|
||||
l_all_workers = l_senior_workers + l_junior_workers
|
||||
sum_salary = self.salary
|
||||
for the_worker in l_all_workers:
|
||||
sum_salary += the_worker.salary
|
||||
return
|
||||
|
||||
def s_profit(self):
|
||||
# ?
|
||||
self.s_profit = self.logit_share() * self.p.e_revenue - self.sum_salary()
|
||||
return
|
||||
|
||||
def step(self):
|
||||
pass
|
16
0829/main.py
16
0829/main.py
|
@ -1,16 +0,0 @@
|
|||
# This is a sample Python script.
|
||||
|
||||
# Press Shift+F10 to execute it or replace it with your code.
|
||||
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
|
||||
|
||||
|
||||
def print_hi(name):
|
||||
# Use a breakpoint in the code line below to debug your script.
|
||||
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
|
||||
|
||||
|
||||
# Press the green button in the gutter to run the script.
|
||||
if __name__ == '__main__':
|
||||
print_hi('PyCharm')
|
||||
|
||||
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
|
|
@ -1,93 +0,0 @@
|
|||
import math
|
||||
|
||||
import agentpy as ap
|
||||
from random import uniform, randint
|
||||
|
||||
# 编程可以自动补充一些东西,减少报错
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from firm import FirmAgent
|
||||
|
||||
|
||||
class WorkerAgent(ap.Agent):
|
||||
select_firm: object
|
||||
c_effort: float
|
||||
s_is_hired: bool
|
||||
# c_work_months: int
|
||||
s_work_duration: int
|
||||
working_firm: 'FirmAgent'
|
||||
s_salary: float
|
||||
s_yield: float
|
||||
# s_w_applied: bool
|
||||
c_alpha: float
|
||||
|
||||
def setup(self, alpha):
|
||||
# super().__init__(unique_id, model)
|
||||
# self.num_workers = 10000
|
||||
self.c_effort = uniform(0, 1)
|
||||
# self.c_work_months = randint(0, 60)
|
||||
self.s_is_hired = False
|
||||
self.s_work_duration = randint(0, 60)
|
||||
self.c_alpha = alpha
|
||||
self.update_yield()
|
||||
self.s_salary = 0
|
||||
|
||||
# return
|
||||
|
||||
# def A_Utility(self, c_w_weight=0.5):
|
||||
# a = np.exp(FirmAgent.c_f_incentive, c_w_weight)
|
||||
# b = np.exp(FirmAgent.s_f_profit/max(FirmAgent.s_f_profit), 1-c_w_weight)
|
||||
# self.select_firm = a * b
|
||||
|
||||
def select_firm(self):
|
||||
'''
|
||||
挑选出来的企业列表
|
||||
数量:列表的长度
|
||||
'''
|
||||
lst_firms = self.model.provide_lst_random_firms(self)
|
||||
n_firms = len(lst_firms)
|
||||
# find the max incentive and profit among all firms
|
||||
max_incentive, max_profit = 0, 0
|
||||
for f in lst_firms:
|
||||
if f.c_incentive > max_incentive:
|
||||
max_incentive = f.c_incentive
|
||||
if f.s_profit > max_profit:
|
||||
max_profit = f.s_profit
|
||||
# computer the utility for each firm
|
||||
max_utility, best_firm = 0, None
|
||||
for f in lst_firms:
|
||||
u = math.pow(f.c_incentive / max_incentive, self.c_alpha) * math.pow(f.s_profit/max_profit, 1-self.c_alpha)
|
||||
if u > max_utility:
|
||||
max_utility = u
|
||||
best_firm = f
|
||||
# print(f'{self}: my best firm is {best_firm} from {n_firms} firms with utility {max_utility}')
|
||||
# 选出能够给自己带来最好的效用的企业,并输出/返回
|
||||
best_firm.apply(self)
|
||||
return best_firm
|
||||
|
||||
def update_wd_by_is_hired(self):
|
||||
if self.s_is_hired == 1:
|
||||
self.s_work_duration += 1
|
||||
self.update_yield()
|
||||
self.update_salary()
|
||||
|
||||
def update_salary(self, the_firm: 'FirmAgent'):
|
||||
if self.s_salary == 0:
|
||||
self.s_salary = the_firm.initial_f_salary
|
||||
pass
|
||||
else:
|
||||
self.s_salary = self.s_salary * (1 + the_firm.c_incentive)
|
||||
pass
|
||||
|
||||
def update_yield(self):
|
||||
self.s_yield = 2 / (1 + math.exp(-0.01 * self.s_work_duration * self.c_effort)) - 1
|
||||
|
||||
def update_working_firm_is_hired(self, f: 'FirmAgent'):
|
||||
self.s_is_hired = True
|
||||
self.working_firm = f
|
||||
|
||||
def step(self):
|
||||
self.update_wd_by_is_hired()
|
||||
'''
|
||||
是否更换公司成功的状态转换?
|
||||
'''
|
|
@ -0,0 +1,27 @@
|
|||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
num_time_step = 20
|
||||
num_iter = 10
|
||||
|
||||
env_data = pd.DataFrame(pd.read_excel('env_data.xlsx', engine='openpyxl'))
|
||||
|
||||
assert env_data.shape[0] == num_iter * (num_time_step + 1)
|
||||
|
||||
lst_df = []
|
||||
for i in range(num_iter):
|
||||
df_tmp = env_data.iloc[i * (num_time_step + 1): (i + 1) * (num_time_step + 1), 1:]
|
||||
lst_df.append(df_tmp)
|
||||
# df_tmp = env_data.iloc[1: 21]
|
||||
# lst_df.append(df_tmp)
|
||||
|
||||
|
||||
x = np.array(env_data[['t']])
|
||||
y = np.array(env_data[['out_w_avg_salary']])
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
plt.xlabel('t')
|
||||
plt.ylabel('out_w_avg_salary')
|
||||
plt.plot(x, y)
|
||||
plt.show()
|
163
env.py
163
env.py
|
@ -1,13 +1,16 @@
|
|||
import agentpy as ap
|
||||
|
||||
import numpy as np
|
||||
from random import uniform
|
||||
import math
|
||||
|
||||
from traits.trait_types import self
|
||||
|
||||
from worker import WorkerAgent
|
||||
from firm import FirmAgent
|
||||
|
||||
# plt.ion()
|
||||
|
||||
class Env(ap.Model):
|
||||
|
||||
float_market_size: float
|
||||
percent_rh: float
|
||||
percent_search: float
|
||||
|
@ -18,6 +21,17 @@ class Env(ap.Model):
|
|||
a_lst_worker: ap.AgentList
|
||||
a_lst_firm: ap.AgentList
|
||||
|
||||
"""
|
||||
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
|
||||
|
||||
def setup(self):
|
||||
# 工作人员、企业数量、搜寻企业数量赋值
|
||||
self.n_worker = self.p.n_worker
|
||||
|
@ -26,7 +40,7 @@ class Env(ap.Model):
|
|||
# 工人、企业列表
|
||||
self.a_lst_worker = ap.AgentList(self)
|
||||
self.a_lst_firm = ap.AgentList(self)
|
||||
self.e_revenue = 119.3
|
||||
self.e_revenue = 1193e+7
|
||||
|
||||
# 在工人列表中添加工人
|
||||
for i in range(self.n_worker):
|
||||
|
@ -52,15 +66,103 @@ class Env(ap.Model):
|
|||
# 第二步, firm 去选 worker
|
||||
self.a_lst_firm.select_worker()
|
||||
|
||||
if self.t == 100:
|
||||
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:
|
||||
self.stop()
|
||||
# self.picture_out()
|
||||
pass
|
||||
|
||||
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:
|
||||
# 两种方式,第一种是直接淘汰企业(此处设定为清空企业员工,清空企业利润值和价值,相当于重新添加了一个新的企业?)
|
||||
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
|
||||
# f.s_profit = 0
|
||||
# f.s_value = 0
|
||||
# 第二种方式,末位淘汰制,淘汰所有员工中单位产值(产值/工资)价值最低的
|
||||
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
|
||||
|
||||
|
||||
# 第二种方式,末位淘汰制,淘汰所有员工中生产价值最低的
|
||||
# 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
|
||||
|
||||
|
||||
|
||||
# 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}'
|
||||
|
||||
|
||||
def provide_lst_random_firms(self, the_worker: WorkerAgent):
|
||||
'''选择企业数量 = 企业总数*百分比
|
||||
选择企业的列表 = 随机选择的企业的个数
|
||||
如果员工处于被雇佣的状态:
|
||||
如果员工工作的企业在随机选定的企业列表中:
|
||||
如果员工工作的企业在随机选定的企业列表中
|
||||
打开列表中的企业
|
||||
移除该企业
|
||||
返回值:移除后,再重新选择随机选择企业
|
||||
|
@ -78,14 +180,59 @@ class Env(ap.Model):
|
|||
# 假如以上都不满足, 直接返回
|
||||
return ap.AgentList(self, a_lst_select_firms)
|
||||
|
||||
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
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dict_para = {'n_worker': 100,
|
||||
'n_firm': 20,
|
||||
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)
|
||||
my_model.run()
|
||||
#
|
||||
# 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 = {
|
||||
'n_worker': 500,
|
||||
'n_firm': 10,
|
||||
'percent_search': 0.2,
|
||||
'alpha': 0.5,
|
||||
# 'alpha': ap.Range(0, 1, 0.5),
|
||||
'is_RH_ratio': 0.5,
|
||||
}
|
||||
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')
|
||||
|
||||
|
|
Binary file not shown.
55
firm.py
55
firm.py
|
@ -22,16 +22,26 @@ class FirmAgent(ap.Agent):
|
|||
initial_f_salary: float
|
||||
s_revenue: float
|
||||
s_profit: float
|
||||
s_value: float
|
||||
firing_worker: 'WorkerAgent'
|
||||
l_senior_workers: list
|
||||
l_junior_workers: list
|
||||
l_applied_workers: list
|
||||
|
||||
# def __init__(self, model, *args, **kwargs):
|
||||
# super().__init__(model, args, kwargs)
|
||||
# self.l_all_workers = None
|
||||
|
||||
def setup(self, is_RH):
|
||||
self.c_incentive = uniform(0, 1)
|
||||
# self.s_profit = randint(10, 20)
|
||||
self.l_senior_workers, self.l_junior_workers = [], []
|
||||
self.l_all_workers = []
|
||||
self.l_applied_workers = []
|
||||
self.s_IsRH = is_RH
|
||||
self.initial_f_salary = randint(8000, 10000)
|
||||
self.s_profit = 0
|
||||
self.s_value = 0
|
||||
|
||||
def apply(self, the_worker):
|
||||
self.l_applied_workers.append(the_worker)
|
||||
|
@ -58,7 +68,21 @@ class FirmAgent(ap.Agent):
|
|||
best_worker = the_worker
|
||||
selected_worker = best_worker
|
||||
else:
|
||||
selected_worker = self.l_applied_workers[0] # TODO
|
||||
# selected_worker = self.l_applied_workers[0] # TODO
|
||||
# 加入worker进入到某个企业,企业更新了自己的利润,利润差值作为该名员工能带来的单位利润,排序利润
|
||||
# 但是代码中对于员工产出是(0,1)值,需要先更新员工所在列表,然后更新企业产出、利润、工资总额,再用假设利润-上期利润
|
||||
# 问题是,当期的估算不能考虑到有员工会在下一期离指的问题,或许考虑换成?max_单位产出成本?
|
||||
max_unit_yield_salary, p_salary, best_worker= 0.0,0.0, None
|
||||
for the_worker in self.l_applied_workers:
|
||||
if the_worker.s_salary == 0:
|
||||
the_worker.p_salary = self.initial_f_salary
|
||||
else:
|
||||
the_worker.p_salary = the_worker.s_salary*(1+self.c_incentive)
|
||||
the_worker.unit_yield_salary = the_worker.s_yield * 10000 / the_worker.p_salary
|
||||
if the_worker.unit_yield_salary > max_unit_yield_salary:
|
||||
max_unit_yield_salary = the_worker.unit_yield_salary
|
||||
best_worker = the_worker
|
||||
selected_worker = best_worker
|
||||
# print(f'{self}: my best firm is {best_firm} from {n_firms} firms with utility {max_utility}')
|
||||
# return best_worker
|
||||
# 当企业是想要利用产出最高的员工时,从申请的员工中选出产出最高的员工
|
||||
|
@ -80,18 +104,18 @@ class FirmAgent(ap.Agent):
|
|||
|
||||
def update_two_worker_list(self, new_worker):
|
||||
lst_all_worker = self.l_senior_workers + self.l_junior_workers + [new_worker]
|
||||
lst_sorted = lst_all_worker.sort(key=lambda x: x['s_yield'], reverse=True) # from highest yield to lowest
|
||||
lst_all_worker.sort(key=lambda x: x['s_yield'], reverse=True) # from highest yield to lowest
|
||||
n_all_worker = len(lst_all_worker)
|
||||
# 向上取整数值
|
||||
n_senior_worker = math.ceil(n_all_worker * 0.2)
|
||||
n_junior_worker = n_all_worker - n_senior_worker
|
||||
self.l_senior_workers = lst_sorted[:n_senior_worker]
|
||||
self.l_senior_workers = lst_all_worker[:n_senior_worker]
|
||||
if n_junior_worker == 0:
|
||||
self.l_junior_workers = []
|
||||
else:
|
||||
self.l_junior_workers = lst_sorted[n_senior_worker:]
|
||||
self.l_junior_workers = lst_all_worker[n_senior_worker:]
|
||||
|
||||
def update_yields(self): # 需要改
|
||||
def update_yields(self):
|
||||
n_sw, n_jw = len(self.l_senior_workers), len(self.l_junior_workers)
|
||||
# acc_all_yield = 0
|
||||
|
||||
|
@ -115,24 +139,19 @@ class FirmAgent(ap.Agent):
|
|||
self.s_avg_junior_yield = s_acc_junior_yield / n_jw
|
||||
self.s_a_yield = 0.8 * self.s_avg_senior_yield + 0.2 * self.s_avg_junior_yield
|
||||
|
||||
def logit_share(self):
|
||||
logit_share = math.exp(self.s_a_yield) / np.sum(math.exp(self.s_a_yield))
|
||||
return logit_share
|
||||
|
||||
def sum_salary(self, l_senior_workers, l_junior_workers):
|
||||
def get_sum_salary(self):
|
||||
'''
|
||||
计算某公司整体的薪金水平
|
||||
'''
|
||||
l_all_workers = l_senior_workers + l_junior_workers
|
||||
sum_salary = self.salary
|
||||
l_all_workers = self.l_senior_workers + self.l_junior_workers
|
||||
sum_salary = 0.0
|
||||
for the_worker in l_all_workers:
|
||||
sum_salary += the_worker.salary
|
||||
return
|
||||
sum_salary += the_worker.s_salary
|
||||
return sum_salary
|
||||
|
||||
def s_profit(self):
|
||||
# ?
|
||||
self.s_profit = self.logit_share() * self.p.e_revenue - self.sum_salary()
|
||||
return
|
||||
def update_s_profit(self):
|
||||
self.s_profit = self.s_revenue - self.get_sum_salary()
|
||||
self.s_value += self.s_profit
|
||||
|
||||
def step(self):
|
||||
pass
|
||||
|
|
49
worker.py
49
worker.py
|
@ -1,10 +1,12 @@
|
|||
import math
|
||||
import random
|
||||
|
||||
import agentpy as ap
|
||||
from random import uniform, randint
|
||||
|
||||
# 编程可以自动补充一些东西,减少报错
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from firm import FirmAgent
|
||||
|
||||
|
@ -30,6 +32,7 @@ class WorkerAgent(ap.Agent):
|
|||
self.s_work_duration = randint(0, 60)
|
||||
self.c_alpha = alpha
|
||||
self.update_yield()
|
||||
|
||||
self.s_salary = 0
|
||||
|
||||
# return
|
||||
|
@ -47,37 +50,56 @@ class WorkerAgent(ap.Agent):
|
|||
lst_firms = self.model.provide_lst_random_firms(self)
|
||||
n_firms = len(lst_firms)
|
||||
# find the max incentive and profit among all firms
|
||||
max_incentive, max_profit = 0, 0
|
||||
max_incentive, max_value = 0, 0
|
||||
for f in lst_firms:
|
||||
if f.c_incentive > max_incentive:
|
||||
max_incentive = f.c_incentive
|
||||
if f.s_profit > max_profit:
|
||||
max_profit = f.s_profit
|
||||
if f.s_value > max_value:
|
||||
max_value = f.s_value
|
||||
# computer the utility for each firm
|
||||
if max_value == 0:
|
||||
return random.choice(lst_firms)
|
||||
max_utility, best_firm = 0, None
|
||||
for f in lst_firms:
|
||||
u = math.pow(f.c_incentive / max_incentive, self.c_alpha) * math.pow(f.s_profit/max_profit, 1-self.c_alpha)
|
||||
if u > max_utility:
|
||||
max_utility = u
|
||||
best_firm = f
|
||||
if self.s_salary < f.s_profit * 1 / 10:
|
||||
u = math.pow(f.c_incentive / max_incentive, self.c_alpha) * math.pow(f.s_value / max_value,
|
||||
1 - self.c_alpha)
|
||||
if u > max_utility:
|
||||
max_utility = u
|
||||
best_firm = f
|
||||
# if self.s_salary < best_firm.s_profit * 5 / 100:
|
||||
best_firm.apply(self)
|
||||
|
||||
|
||||
# print(f'{self}: my best firm is {best_firm} from {n_firms} firms with utility {max_utility}')
|
||||
# 选出能够给自己带来最好的效用的企业,并输出/返回
|
||||
best_firm.apply(self)
|
||||
return best_firm
|
||||
# best_firm.apply(self)
|
||||
# return best_firm
|
||||
# self.update_wd_by_is_hired()
|
||||
|
||||
def update_wd_by_is_hired(self):
|
||||
if self.s_is_hired == 1:
|
||||
if self.s_is_hired:
|
||||
self.s_work_duration += 1
|
||||
self.update_yield()
|
||||
self.update_salary()
|
||||
self.update_salary(self.working_firm)
|
||||
|
||||
def update_salary(self, the_firm: 'FirmAgent'):
|
||||
|
||||
if self.s_salary == 0:
|
||||
self.s_salary = the_firm.initial_f_salary
|
||||
pass
|
||||
else:
|
||||
self.s_salary = self.s_salary * (1 + the_firm.c_incentive)
|
||||
pass
|
||||
if self.s_salary <= the_firm.s_profit*1/10:
|
||||
if self.s_salary * (1 + the_firm.c_incentive) <= the_firm.s_profit*1/10:
|
||||
self.s_salary = self.s_salary * (1 + the_firm.c_incentive)
|
||||
pass
|
||||
else:
|
||||
self.s_salary = the_firm.s_profit*1/10
|
||||
pass
|
||||
pass
|
||||
else:
|
||||
self.s_salary = the_firm.s_profit*1/10
|
||||
|
||||
|
||||
def update_yield(self):
|
||||
self.s_yield = 2 / (1 + math.exp(-0.01 * self.s_work_duration * self.c_effort)) - 1
|
||||
|
@ -85,6 +107,7 @@ class WorkerAgent(ap.Agent):
|
|||
def update_working_firm_is_hired(self, f: 'FirmAgent'):
|
||||
self.s_is_hired = True
|
||||
self.working_firm = f
|
||||
self.update_wd_by_is_hired()
|
||||
|
||||
def step(self):
|
||||
self.update_wd_by_is_hired()
|
||||
|
|
Loading…
Reference in New Issue