forked from bbfamily/abu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
happy_life.py
executable file
·280 lines (239 loc) · 10.7 KB
/
happy_life.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# -*- encoding:utf-8 -*-
from __future__ import division
from __future__ import print_function
import numpy as np
from abc import ABCMeta, abstractmethod
from abupy import six
# 每个人平均寿命期望是75年,约75*365=27375天
K_INIT_LIVING_DAYS = 27375
class Person(object):
"""
人类
"""
def __init__(self):
# 初始化人平均能活的寿命
self.living = K_INIT_LIVING_DAYS
# 初始化幸福指数
self.happiness = 0
# 初始化财富值
self.wealth = 0
# 初始化名望权利
self.fame = 0
# 活着的第几天
self.living_day = 0
def live_one_day(self, seek):
"""
每天只能进行一个seek,这个seek决定了你今天追求的是什么,得到了什么
seek的类型属于下面将编写的BaseSeekDay
:param seek:
:return:
"""
# 调用每个独特的BaseSeekDay类都会实现的do_seek_day,得到今天的收获
consume_living, happiness, wealth, fame = seek.do_seek_day()
# 每天要减去生命消耗,有些seek前面还会增加生命
self.living -= consume_living
# seek得到的幸福指数积累
self.happiness += happiness
# seek得到的财富积累
self.wealth += wealth
# seek得到的名望权力积累
self.fame += fame
# 活完这一天了
self.living_day += 1
class BaseSeekDay(six.with_metaclass(ABCMeta, object)):
def __init__(self):
# 每个追求每天消耗生命的常数
self.living_consume = 0
# 每个追求每天幸福指数常数
self.happiness_base = 0
# 每个追求每天财富积累常数
self.wealth_base = 0
# 每个追求每天名望权利积累常数
self.fame_base = 0
# 每个追求每天消耗生命的可变因素序列
self.living_factor = [0]
# 每个追求每天幸福指数的可变因素序列
self.happiness_factor = [0]
# 每个追求每天财富积累的可变因素序列
self.wealth_factor = [0]
# 每个追求每天名望权利的可变因素序列
self.fame_factor = [0]
# 追求了多少天了这一生
self.do_seek_day_cnt = 0
# 子类进行常数及可变因素序列设置
self._init_self()
@abstractmethod
def _init_self(self, *args, **kwargs):
# 子类必须实现,设置自己的生命消耗的常数,幸福指数常数等常数设置
pass
@abstractmethod
def _gen_living_days(self, *args, **kwargs):
# 子类必须实现,设置自己的可变因素序列
pass
def do_seek_day(self):
"""
每一天的追求具体seek
:return:
"""
# 生命消耗=living_consume:消耗常数 * happiness_factor:可变序列
if self.do_seek_day_cnt >= len(self.living_factor):
# 超出len(self.living_factor), 就取最后一个living_factor[-1]
consume_living = \
self.living_factor[-1] * self.living_consume
else:
# 每个类自定义这个追求的消耗生命常数,以及living_factor,比如
# HealthSeekDay追求健康,living_factor序列的值即由负值->正值
# 每个子类living_factor会有自己特点的变化速度及序列长度,导致每个
# 追求对生命的消耗随着追求的次数变化不一
consume_living = self.living_factor[self.do_seek_day_cnt] \
* self.living_consume
# 幸福指数=happiness_base:幸福常数 * happiness_factor:可变序列
if self.do_seek_day_cnt >= len(self.happiness_factor):
# 超出len(self.happiness_factor), 就取最后一个
# 由于happiness_factor值由:n—>0 所以happiness_factor[-1]=0
# 即随着追求一个事物的次数过多后会变的没有幸福感
happiness = self.happiness_factor[
-1] * self.happiness_base
else:
# 每个类自定义这个追求的幸福指数常数,以及happiness_factor
# happiness_factor子类的定义一般是从高->低变化
happiness = self.happiness_factor[
self.do_seek_day_cnt] * self.happiness_base
# 财富积累=wealth_base:积累常数 * wealth_factor:可变序列
if self.do_seek_day_cnt >= len(self.wealth_factor):
# 超出len(self.wealth_factor), 就取最后一个
wealth = self.wealth_factor[-1] * self.wealth_base
else:
# 每个类自定义这个追求的财富指数常数,以及wealth_factor
wealth = self.wealth_factor[
self.do_seek_day_cnt] * self.wealth_base
# 权利积累=fame_base:积累常数 * fame_factor:可变序列
if self.do_seek_day_cnt >= len(self.fame_factor):
# 超出len(self.fame_factor), 就取最后一个
fame = self.fame_factor[-1] * self.fame_base
else:
# 每个类自定义这个追求的名望权利指数常数,以及fame_factor
fame = self.fame_factor[
self.do_seek_day_cnt] * self.fame_base
# 追求了多少天了这一生 + 1
self.do_seek_day_cnt += 1
# 返回这个追求这一天对生命的消耗,得到的幸福,财富,名望权利
return consume_living, happiness, wealth, fame
def regular_mm(group):
# 最小-最大规范化
return (group - group.min()) / (group.max() - group.min())
class HealthSeekDay(BaseSeekDay):
"""
HealthSeekDay追求健康长寿的一天:
形象:健身,旅游,娱乐,做感兴趣的事情。
抽象:追求健康长寿。
"""
def _init_self(self):
# 每天对生命消耗的常数=1,即代表1天
self.living_consume = 1
# 每天幸福指数常数=1
self.happiness_base = 1
# 设定可变因素序列
self._gen_living_days()
def _gen_living_days(self):
# 只生成12000个序列,因为下面的happiness_factor序列值由1->0
# 所以大于12000次的追求都将只是单纯消耗生命,并不增加幸福指数
# 即随着做一件事情的次数越来越多,幸福感越来越低,直到完全体会不到幸福
days = np.arange(1, 12000)
# 基础函数选用sqrt, 影响序列变化速度
living_days = np.sqrt(days)
"""
对生命消耗可变因素序列值由-1->1, 也就是这个追求一开始的时候对生命
的消耗为负增长,延长了生命,随着追求的次数不断增多对生命的消耗转为正
数因为即使一个人天天锻炼身体,天天吃营养品,也还是会有自然死亡的那
一天
"""
# *2-1的目的:regular_mm在0-1之间,HealthSeekDay要结果在-1,1之间
self.living_factor = regular_mm(living_days) * 2 - 1
# 结果在1-0之间 [::-1]: 将0->1转换到1->0
self.happiness_factor = regular_mm(days)[::-1]
class StockSeekDay(BaseSeekDay):
"""
StockSeekDay追求财富金钱的一天:
形象:做股票投资赚钱的事情。
抽象:追求财富金钱
"""
def _init_self(self, show=False):
# 每天对生命消耗的常数=2,即代表2天
self.living_consume = 2
# 每天幸福指数常数=0.5
self.happiness_base = 0.5
# 财富积累常数=10,默认=0
self.wealth_base = 10
# 设定可变因素序列
self._gen_living_days()
def _gen_living_days(self):
# 只生成10000个序列
days = np.arange(1, 10000)
# 针对生命消耗living_factor的基础函数还是sqrt
living_days = np.sqrt(days)
# 由于不需要像HealthSeekDay从负数开始,所以直接regular_mm 即:0->1
self.living_factor = regular_mm(living_days)
# 针对幸福感可变序列使用了np.power4,即变化速度比sqrt快
happiness_days = np.power(days, 4)
# 幸福指数可变因素会快速递减由1->0
self.happiness_factor = regular_mm(happiness_days)[::-1]
"""
这里简单设定wealth_factor=living_factor
living_factor(0-1), 导致wealth_factor(0-1), 即财富积累越到
后面越有效率,速度越快,头一个100万最难赚
"""
self.wealth_factor = self.living_factor
class FameSeekDay(BaseSeekDay):
"""
FameTask追求名望权力的一天:
追求名望权力
"""
def _init_self(self):
# 每天对生命消耗的常数=3,即代表3天
self.living_consume = 3
# 每天幸福指数常数=0.6
self.happiness_base = 0.6
# 名望权利积累常数=10,默认=0
self.fame_base = 10
# 设定可变因素序列
self._gen_living_days()
def _gen_living_days(self):
# 只生成12000个序列
days = np.arange(1, 12000)
# 针对生命消耗living_factor的基础函数还是sqrt
living_days = np.sqrt(days)
# 由于不需要像HealthSeekDay从负数开始,所以直接regular_mm 即:0->1
self.living_factor = regular_mm(living_days)
# 针对幸福感可变序列使用了np.power2
# 即变化速度比StockSeekDay慢但比HealthSeekDay快
happiness_days = np.power(days, 2)
# 幸福指数可变因素递减由1->0
self.happiness_factor = regular_mm(happiness_days)[::-1]
# 这里简单设定fame_factor=living_factor
self.fame_factor = self.living_factor
def my_life(weights):
"""
追求健康长寿快乐的权重:weights[0]
追求财富金钱的权重:weights[1]
追求名望权力的权重:weights[2]
"""
# 追求健康长寿快乐
seek_health = HealthSeekDay()
# 追求财富金钱
seek_stock = StockSeekDay()
# 追求名望权力
seek_fame = FameSeekDay()
# 放在一个list中对对应下面np.random.choice中的index[0, 1, 2]
seek_list = [seek_health, seek_stock, seek_fame]
# 初始化我
me = Person()
# 加权随机抽取序列。80000天肯定够了, 80000天快220年了。。。
seek_choice = np.random.choice([0, 1, 2], 80000, p=weights)
while me.living > 0:
# 追求从加权随机抽取序列已经初始化好的
seek_ind = seek_choice[me.living_day]
seek = seek_list[seek_ind]
# 只要还活着,就追求
me.live_one_day(seek)
return round(me.living_day / 365, 2), round(me.happiness, 2), round(me.wealth, 2), round(me.fame, 2)